go: x/tools/gopls: poor performance and crash on google-cloud-go
gopls version: v0.12.0-pre.1 (go1.20.3) gopls flags: update flags: proxy extension version: 0.38.0 go version: 1.20.3 environment: Visual Studio Code darwin initialization error: undefined issue timestamp: Tue, 09 May 2023 14:45:46 GMT restart history: Tue, 09 May 2023 14:43:43 GMT: activation (enabled: true)
ATTENTION: PLEASE PROVIDE THE DETAILS REQUESTED BELOW.
Describe what you observed.
gopls crashed while in google-cloud-go. I believe I was searching to open a file before this happened.
Please attach the stack trace from the crash. A window with the error message should have popped up in the lower half of your screen. Please copy the stack trace and error messages from that window and paste it in this issue.
https://gist.github.com/codyoss/f19310e0db7499861e7f3d92ad056625
Failed to auto-collect gopls trace: unrecognized crash pattern.
Also got the following message post crash: extension-output-golang.go-#3-gopls (server): tokenization, wrapping and folding have been turned off for this large file in order to reduce memory usage and avoid freezing or crashing. and Connection to server got closed. Server will not be restarted.
About this issue
- Original URL
- State: closed
- Created a year ago
- Reactions: 1
- Comments: 34 (23 by maintainers)
Commits related to this issue
- gopls: add google-cloud-go as a benchmark repo This repo is large, and exercises use-cases with many workspace modules. For golang/go#60089 Change-Id: I93b9c99ce52bd7ae25f65fdb9bf0568c25375411 Revi... — committed to golang/tools by findleyr a year ago
- gopls/internal/lsp: optimize checks for ignored files Optimize checking for ignored files to avoid unnecessary checks, and only build prefixes once. Along the way, fix a bug where path segments were ... — committed to golang/tools by findleyr a year ago
- gopls/internal/lsp/filecache: limit Get parallelism too This change causes Get to be subject to the same concurrency-limiting semaphore just added to Set, as a user (predictably) encountered thread e... — committed to golang/tools by adonovan a year ago
- gopls/internal/lsp/filecache: front with a 100MB in-memory LRU cache Put a 100MB in-memory LRU cache in front of the filecache, to reduce I/O for repeated cache access, such as we observe with worksp... — committed to golang/tools by findleyr a year ago
- gopls/internal/regtest/bench: add a benchmark for diagnosing saves As we discovered while investigating golang/go#60089, mod tidy operations can significantly affect the amount of time it takes gopls... — committed to golang/tools by findleyr a year ago
- gopls/internal/lsp/mod: optimizations for mod tidy diagnostics Run mod tidy diagnostics in parallel, and don't parse files to determine missing imports if there are no missing requires. BenchmarkDia... — committed to golang/tools by findleyr a year ago
- gopls/internal/lsp: keep track of overlays on the files map The overlays method showed up as a hot spot in the google-cloud-go repo (via reloadOrphanedFiles), because it walks all files to find the s... — committed to golang/tools by findleyr a year ago
- gopls/internal/lsp/cache: only delete the most relevant mod tidy handle For workspaces with a lot of modules, deleting every mod tidy handle on every save is too expensive. Approximate the correct be... — committed to golang/tools by findleyr a year ago
- gopls: add a new "subdirWatchPatterns" setting As discovered in golang/go#60089, file watching patterns behave very differently in different clients. We avoided a bad client-side bug in VS Code by sp... — committed to golang/tools by findleyr a year ago
Discussing with @codyoss, we believe this is related to our
go mod tidylogic.Historically, gopls has conservatively re-run go mod tidy when files are saved (because saved files may theoretically change the tidy result, before overlay support).
This runs for each go.mod file in the workspace, and eagerly parses Go files in the module to analyze the tidy result.
Mix in the VS Code setting that auto-saves files after a delay, gopls@v0.12.0’s more aggressive eviction of parsed files, and the new google-cloud-go go.work file with 145 modules, and you have a recipe for disaster.
Fortunately, this is yet again easy to fix…
@adonovan another crash: https://gist.github.com/codyoss/866fe1c54ca191e40d6b6438bff8bb58
Will do!
Cody, if you have the patience please do try again with the latest source as the recently merged change should not only fix the crash but reduce the number of goroutines and the amount of I/O concurrency, which may have other performance effects. Thanks again for these very helpful bug reports.
Thanks Cody. Huh, this looks like a runtime issue.
Could someone from @golang/runtime take a look at Cody’s crash?
Cody: could you confirm that you’re still on Go 1.20.3?
The CLs above set up some benchmarks for this repo, and then fix the low hanging fruit mentioned above to optimize the time it takes to diagnose the workspace from ~1.5s->300ms.
I’ll note that the initial workspace load on my machine went from 2 minutes@v0.11.0 (!!) to 17s@v0.12.0-pre.1, and the in-use memory went from 6-7GB to 1GB. Gopls should perform significantly better overall on v0.12.0-pre.1, and in fact this is what I observe on my linux laptop. I am curious to test more on Mac+VS Code.
I am very suspicious of system calls: I observed that even on linux, 20%+ of CPU was spent in system calls related to the file cache. I expect this could be much worse on darwin. As an experiment, I put a 100MB in-memory LRU cache in front of our file-based cache, in https://go.dev/cl/494100, which significantly reduces the system call overhead. I’ll test this on darwin tomorrow.
@codyoss if it’s too slow for your daily dev, that’s actionable.
I’ll take a look.