Skip to content

x/tools/gopls: imports extremely slow with large module cache #32750

Closed
@myitcv

Description

@myitcv

What version of Go are you using (go version)?

$ go version
go version devel +44c9354c5a Fri Jun 21 05:21:30 2019 +0000 linux/amd64
$ go list -m golang.org/x/tools
golang.org/x/tools v0.0.0-20190620191750-1fa568393b23
$ go list -m golang.org/x/tools/gopls
golang.org/x/tools/gopls v0.0.0-20190620191750-1fa568393b23

Does this issue reproduce with the latest release?

Yes

What operating system and processor architecture are you using (go env)?

go env Output
$ go env
GO111MODULE="on"
GOARCH="amd64"
GOBIN="/home/myitcv/gostuff/src/github.com/myitcv/govim/cmd/govim/.bin"
GOCACHE="/home/myitcv/.cache/go-build"
GOENV="/home/myitcv/.config/go/env"
GOEXE=""
GOFLAGS=""
GOHOSTARCH="amd64"
GOHOSTOS="linux"
GONOPROXY=""
GONOSUMDB=""
GOOS="linux"
GOPATH="/home/myitcv/gostuff"
GOPRIVATE=""
GOPROXY="https://proxy.golang.org,direct"
GOROOT="/home/myitcv/gos"
GOSUMDB="sum.golang.org"
GOTMPDIR=""
GOTOOLDIR="/home/myitcv/gos/pkg/tool/linux_amd64"
GCCGO="gccgo"
AR="ar"
CC="gcc"
CXX="g++"
CGO_ENABLED="1"
GOMOD="/home/myitcv/gostuff/src/github.com/myitcv/govim/go.mod"
CGO_CFLAGS="-g -O2"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-g -O2"
CGO_FFLAGS="-g -O2"
CGO_LDFLAGS="-g -O2"
PKG_CONFIG="pkg-config"
GOGCCFLAGS="-fPIC -m64 -pthread -fmessage-length=0 -fdebug-prefix-map=/tmp/go-build977371100=/tmp/go-build -gno-record-gcc-switches"

What did you do?

The issue I keep tripping across is making refactoring changes that, for example, rename variables. If I fail to rename all instances of the variable (perhaps I've copy-pasted some code from somewhere), there's a chance I've left behind a selector expression with the old variable name... which is now treated by imports as if it were a qualified identifier for a package that has not yet been imported.

Like #32726, imports then heads off into the module cache searching through all potential matches. With a 5GB module cache, this is not a quick operation.

I think imports should:

  • pre-load and cache its results from the module cache
  • have that cache be invalidated where the modification time of any non-module cache-based go.{mod,sum} reachable from the main module changes
  • when the cache is invalidated, re-warm the cache in the background

Yes, this will cause possibly stale results in the case that another main module causes changes in the module cache, but I think that's a sacrifice worth making for the general speed of imports.

What did you expect to see?

Instant responses to imports-based format-on-save.

What did you see instead?

~10sec delays.


cc @stamblerre @ianthehat @heschik

Activity

added
NeedsInvestigationSomeone must examine and confirm this is a valid issue and not a duplicate of an existing one.
goplsIssues related to the Go language server, gopls.
on Jun 24, 2019
added this to the Unreleased milestone on Jun 24, 2019
bmhatfield

bmhatfield commented on Jun 28, 2019

@bmhatfield

Is there a command I can run on my machine to demonstrate if I am experiencing this? I only have a 250MB module cache, but imports take 30-45s on my machine at least. I do have a likely somewhat larger than normal repo with many packages in it, however.

stamblerre

stamblerre commented on Jun 28, 2019

@stamblerre
Contributor

Do you see this kind of latency when you run goimports via the command line or is it only when gopls invokes it?

heschi

heschi commented on Jun 28, 2019

@heschi
Contributor

@bmhatfield Run goimports -v on the file and see how long it's taking to do directory scans. It should be pretty clear from the output but if not attach it here and I'll take a look.

bmhatfield

bmhatfield commented on Jun 28, 2019

@bmhatfield

I took a file that was having difficulty performing imports (30-45s in vscode "running save participants") and never actually completing the imports. I edited it into a state where VSCode reliably is sluggish and fails to perform imports/formatting (by deleting 3 import lines).

goimports -v runs in less than a second and the output contains the correct imports.

stamblerre

stamblerre commented on Jun 28, 2019

@stamblerre
Contributor

Do you see similar latencies with other gopls features, like jump to definition or autocomplete?

bmhatfield

bmhatfield commented on Jun 28, 2019

@bmhatfield

Jump to definition: 2-3s latencies, with a blue "processing bar" that moves across the top of the window.
Autocomplete: feels instant.

stamblerre

stamblerre commented on Jun 28, 2019

@stamblerre
Contributor

Wow, that's a very strange range of latencies. Definition should definitely feel instant as well. I would have expected every feature to be slow rather than some, and then even so, it seems like go-to-definition is still faster than imports. Do you mind sharing a full gopls log (View: Debug Console -> Output -> Tasks -> gopls) just so I can get a fuller picture?

bmhatfield

bmhatfield commented on Jun 28, 2019

@bmhatfield

Happy to - should we migrate this conversation to #32360, given that I am not experiencing the "large module cache" issue? Or prefer here still?

24 remaining items

assigned and unassigned on Aug 30, 2019
myitcv

myitcv commented on Sep 5, 2019

@myitcv
MemberAuthor

Thanks. See some benefits here as a result of https://golang.org/cl/184921 and https://golang.org/cl/186301.

Pre-warming of this cache has not been implemented yet.

This will also help. However, for Vim users (via whatever plugin) this will also likely become something of a pain. Because Vim users typically start/stop Vim regularly, especially when used from the terminal. Hence, if gopls is being started/stopped each time (communicating over stdin/stdout) then every time Vim is started (and there are often multiple instances of Vim open) this pre-warming will happen.

So any pre-warming will, I suspect, need to go hand-in-hand with ensuring the socket-based communication with gopls is on a par with the pipe-based approach. I would guess it is, but cc @stamblerre and @ianthehat for thoughts?

myitcv

myitcv commented on Sep 5, 2019

@myitcv
MemberAuthor

Will continue conversation in #34111

stamblerre

stamblerre commented on Sep 5, 2019

@stamblerre
Contributor

Sounds good. @myitcv: Do you feel that this issue has been resolved enough that we can close this? (We can track future imports improvements in other issues.)

myitcv

myitcv commented on Sep 5, 2019

@myitcv
MemberAuthor

Do you feel that this issue has been resolved enough that we can close this?

I think the final piece in the puzzle is probably:

Pre-warming of this cache has not been implemented yet.

But I think that only makes sense post #34111 for the reasons laid out in that description.

So yes, can probably close this if we create a follow up issue for the pre-warming of the cache, an issue that is contingent on #34111

stamblerre

stamblerre commented on Sep 5, 2019

@stamblerre
Contributor

Sounds good. Closing this and filed #34115 to track pre-warming the cache.

locked and limited conversation to collaborators on Sep 4, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    FrozenDueToAgeNeedsInvestigationSomeone must examine and confirm this is a valid issue and not a duplicate of an existing one.goplsIssues related to the Go language server, gopls.

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

      Development

      No branches or pull requests

        Participants

        @josharian@bmhatfield@myitcv@stamblerre@suzmue

        Issue actions

          x/tools/gopls: imports extremely slow with large module cache · Issue #32750 · golang/go