Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

x/tools/gopls: unimported package search using up completion budget #41665

muirdm opened this issue Sep 27, 2020 · 4 comments

x/tools/gopls: unimported package search using up completion budget #41665

muirdm opened this issue Sep 27, 2020 · 4 comments


Copy link

@muirdm muirdm commented Sep 27, 2020

On master (5d1fdd8fa3469142b9369713b23d8413d6d83189) I'm seeing mysteriously disappearing deep completions:

In the above example, I expect the candidate "foo.blah.baz.l" to continue to show up, but it disappears as I type.

I think completing fo<> works because "fo" matches enough "easy" unimported candidates so we don't hit the slow unimported package case. Once I get to foo<>, we hit the slow case in unimportedPackages and that gobbles up the completion budget so there is none left for deep completions.

The above example doesn't reproduce in a vacuum. I assume you need a "big enough" go.mod to hit some threshold. Below is the go.mod and foo.go file I used for my example:

Big go.mod
module foo

go 1.13

require ( v0.53.0 v1.5.0 v0.2.0 v1.1.1 v1.6.0 v1.29.11 v0.20.0 v1.0.0-rc.14.0.20200127194803-2226f427d358 v1.0.2-0.20180526013208-73b1f3905474 v0.0.0-20180905225744-ee1a9a0726d2 // indirect v0.0.0-20170710130525-51713292c3b1 v3.2.1-0.20190620180102-5e25c22bd5d6+incompatible // indirect v1.6.2 v0.0.0-20190308151101-6c680f768e74 v1.0.1 v1.4.7 v1.2.1-0.20190220221249-0403632d5b90 v0.0.0-20170307190818-16278e9db813 // indirect v0.2.0 v0.11.2-0.20170327191450-1e5f1161c641 v0.16.1-0.20170327191703-71201497bace v0.0.0-20200624222514-34081eda590e v1.3.1 v1.3.4 v0.0.1 v1.8.2 v2.0.5 v1.1.1 // indirect v1.0.3-0.20160926154116-0ff6a2ce414a v0.0.0-20160816184729-a5775781a543 v0.0.0-20160920230813-757bef944d0f v0.0.0-20160817190122-0164a00ab4cd v0.0.0-20160816222338-c13558c2b1c4 // indirect v1.4.1 v1.0.2-0.20191001231223-f32f5fe8d6a8 // indirect v1.0.0 // indirect v1.9.3-0.20191112205758-ce4ce462ed0a // indirect v0.0.0-20131111012553-2788f0dbd169 // indirect v1.3.2-0.20180705143725-8e9d9df2e208 v1.2.1-0.20190813065522-78223426e7c6 v3.6.4 v0.7.1 v0.0.0-20181019084807-186a8a2128df v2.0.3+incompatible v1.0.1 // indirect v1.0.3 v0.0.0-20161214220750-7ab6b01a30d0 v0.0.0-20161109192638-16c6a8e9da10 // indirect v0.0.0-20180916011732-0a3d74bf9ce4 v0.9.0-pre1.0.20180410130117-e11c6ff8170b v0.0.0-20190812154241-14fe0d1b01d4 v0.0.0-20180808181731-1377b4b71adb v0.0.0-20170815201139-e6b59f6144be v0.20.0 v0.6.4 v1.3.4 v0.0.0-20190827072141-edfb9018d271 v0.0.0-20181024002044-dbf71b6a931e v0.0.0-20140409082417-3ff2c19514a8 v0.0.0-20180823194901-e990b50b8fb7 v0.1.0 v1.15.0 v0.19.0 v0.0.0-20200622213623-75b288015ac9 v0.0.0-20200207192155-f17229e696bd v0.0.0-20191009234506-e7c1f5e7dbb8 v0.0.0-20200625001655-4c5254603344 v0.0.0-20200107190931-bf48bf16ab8d v0.0.0-20200323222414-85ca7c5b95cd v0.3.2 v0.0.0-20190308202827-9d24e82272b4 v0.0.0-20200731060945-b5fad4ed8dd6 v0.6.2 v0.20.0 v0.0.0-20200303153909-beee998c1893 v1.30.0 v3.0.0-20150716171945-2caba252f4dc // indirect v1.0.0-20170511165959-379148ca0225 // indirect v2.0.0-20160411212932-81ebce5c23df v2.1.2 // indirect v1.0.0-20180719183105-8007e27cdb32 v7.3.0 // indirect v2.5.1 v5.0.86 v1.20.0 v2.2.7 v0.0.1-2019.2.3 v0.0.0-20180718204440-ae3c365c0348 v0.0.0-20200802201014-ab5a8192947d
package main

import (

func main() {
	var foo struct {
		blah struct {
			baz struct {
				l *time.Location

	var _ *time.Location = fo

Below is a CPU pprof from me spamming completion after foo<>:

@gopherbot gopherbot added this to the Unreleased milestone Sep 27, 2020
Copy link

@stamblerre stamblerre commented Sep 28, 2020

Thanks for figuring out this repro!

/cc @heschik @dandua98

@stamblerre stamblerre modified the milestones: Unreleased, gopls/v0.5.1 Sep 28, 2020
Copy link

@gopherbot gopherbot commented Sep 28, 2020

Change mentions this issue: internal/lsp/source: use completion budget for only deep completions

Copy link

@gopherbot gopherbot commented Sep 28, 2020

Change mentions this issue: internal/lsp/source: run unimported completions after other deep completions.

Copy link

@gopherbot gopherbot commented Sep 29, 2020

Change mentions this issue: internal/lsp/source: run deep completions before unimported completions

gopherbot pushed a commit to golang/tools that referenced this issue Sep 29, 2020
…before unimported completions

Unimported completions are expensive and can use up a large portion of
completion budget just to find initial deep search candidates. This
change moves these expensive operations which search through the module
cache to after normal deep completions so we search through more useful
candidates first.

Fixes golang/go#41434
Fixes golang/go#41665

Change-Id: I6f3963f8c65c1a97833a35738d2e96420de2f6ee
Run-TryBot: Danish Dua <>
gopls-CI: kokoro <>
TryBot-Result: Go Bot <>
Reviewed-by: Heschi Kreinick <>
Trust: Danish Dua <>
(cherry picked from commit c43c25c)
Run-TryBot: Rebecca Stambler <>
Reviewed-by: Danish Dua <>
Trust: Rebecca Stambler <>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
None yet
Linked pull requests

Successfully merging a pull request may close this issue.

None yet
3 participants