Skip to content

Commit 2bb7f1c

Browse files
committed
gopls/internal/test/integration/bench: improve completion benchmarks
Make the following improvements to the completion benchmarks: - Run the "CompletionFollowingEdit" benchmarks with and without edits. Accordingly, rename it to just "BenchmarkCompletion", and shorten subtest names. - BenchmarkCompletion is a cleaner way to specify completion tests. Deprecate other styles. - Support running completion tests with a massive GOPATH, by passing -completion_gopath. - Add a tools_unimportedselector test that seems to do a good job of exercising slow unimported completion. Other unimportedcompletion tests were short-circuited in one way or another (for example, because kubernetes uses vendoring, gopls doesn't scan GOPATH). This will invalidate our benchmark dashboard, so we should merge this change before subsequent CLs that optimize unimported completion. For golang/go#63459 Change-Id: I9d7a06e3c1a7239b531ed8ff534f3174f4ac4ae8 Reviewed-on: https://go-review.googlesource.com/c/tools/+/560457 Reviewed-by: Alan Donovan <[email protected]> LUCI-TryBot-Result: Go LUCI <[email protected]>
1 parent f6dc1e9 commit 2bb7f1c

File tree

1 file changed

+56
-16
lines changed

1 file changed

+56
-16
lines changed

gopls/internal/test/integration/bench/completion_test.go

+56-16
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ import (
1515
"golang.org/x/tools/gopls/internal/test/integration/fake"
1616
)
1717

18-
// TODO(rfindley): update these completion tests to run on multiple repos.
18+
var completionGOPATH = flag.String("completion_gopath", "", "if set, use this GOPATH for BenchmarkCompletion")
1919

2020
type completionBenchOptions struct {
2121
file, locationRegexp string
@@ -25,6 +25,7 @@ type completionBenchOptions struct {
2525
beforeCompletion func(*Env) // run before each completion
2626
}
2727

28+
// Deprecated: new tests should be expressed in BenchmarkCompletion.
2829
func benchmarkCompletion(options completionBenchOptions, b *testing.B) {
2930
repo := getRepo(b, "tools")
3031
_ = repo.sharedEnv(b) // ensure cache is warm
@@ -146,15 +147,15 @@ func (c *completer) _() {
146147
}, b)
147148
}
148149

149-
type completionFollowingEditTest struct {
150+
type completionTest struct {
150151
repo string
151152
name string
152153
file string // repo-relative file to create
153154
content string // file content
154155
locationRegexp string // regexp for completion
155156
}
156157

157-
var completionFollowingEditTests = []completionFollowingEditTest{
158+
var completionTests = []completionTest{
158159
{
159160
"tools",
160161
"selector",
@@ -168,6 +169,32 @@ func (c *completer) _() {
168169
`,
169170
`func \(c \*completer\) _\(\) {\n\tc\.inference\.kindMatches\((c)`,
170171
},
172+
{
173+
"tools",
174+
"unimportedident",
175+
"internal/lsp/source/completion/completion2.go",
176+
`
177+
package completion
178+
179+
func (c *completer) _() {
180+
lo
181+
}
182+
`,
183+
`lo()`,
184+
},
185+
{
186+
"tools",
187+
"unimportedselector",
188+
"internal/lsp/source/completion/completion2.go",
189+
`
190+
package completion
191+
192+
func (c *completer) _() {
193+
log.
194+
}
195+
`,
196+
`log\.()`,
197+
},
171198
{
172199
"kubernetes",
173200
"selector",
@@ -213,14 +240,18 @@ func (p *Pivot) _() {
213240
//
214241
// Edits force type-checked packages to be invalidated, so we want to measure
215242
// how long it takes before completion results are available.
216-
func BenchmarkCompletionFollowingEdit(b *testing.B) {
217-
for _, test := range completionFollowingEditTests {
243+
func BenchmarkCompletion(b *testing.B) {
244+
for _, test := range completionTests {
218245
b.Run(fmt.Sprintf("%s_%s", test.repo, test.name), func(b *testing.B) {
219-
for _, completeUnimported := range []bool{true, false} {
220-
b.Run(fmt.Sprintf("completeUnimported=%v", completeUnimported), func(b *testing.B) {
221-
for _, budget := range []string{"0s", "100ms"} {
222-
b.Run(fmt.Sprintf("budget=%s", budget), func(b *testing.B) {
223-
runCompletionFollowingEdit(b, test, completeUnimported, budget)
246+
for _, followingEdit := range []bool{true, false} {
247+
b.Run(fmt.Sprintf("edit=%v", followingEdit), func(b *testing.B) {
248+
for _, completeUnimported := range []bool{true, false} {
249+
b.Run(fmt.Sprintf("unimported=%v", completeUnimported), func(b *testing.B) {
250+
for _, budget := range []string{"0s", "100ms"} {
251+
b.Run(fmt.Sprintf("budget=%s", budget), func(b *testing.B) {
252+
runCompletion(b, test, followingEdit, completeUnimported, budget)
253+
})
254+
}
224255
})
225256
}
226257
})
@@ -229,13 +260,20 @@ func BenchmarkCompletionFollowingEdit(b *testing.B) {
229260
}
230261
}
231262

263+
// For optimizing unimported completion, it can be useful to benchmark with a
264+
// huge GOMODCACHE.
232265
var gomodcache = flag.String("gomodcache", "", "optional GOMODCACHE for unimported completion benchmarks")
233266

234-
func runCompletionFollowingEdit(b *testing.B, test completionFollowingEditTest, completeUnimported bool, budget string) {
267+
func runCompletion(b *testing.B, test completionTest, followingEdit, completeUnimported bool, budget string) {
235268
repo := getRepo(b, test.repo)
236-
sharedEnv := repo.sharedEnv(b) // ensure cache is warm
269+
gopath := *completionGOPATH
270+
if gopath == "" {
271+
// use a warm GOPATH
272+
sharedEnv := repo.sharedEnv(b)
273+
gopath = sharedEnv.Sandbox.GOPATH()
274+
}
237275
envvars := map[string]string{
238-
"GOPATH": sharedEnv.Sandbox.GOPATH(), // use the warm cache
276+
"GOPATH": gopath,
239277
}
240278

241279
if *gomodcache != "" {
@@ -248,7 +286,7 @@ func runCompletionFollowingEdit(b *testing.B, test completionFollowingEditTest,
248286
"completeUnimported": completeUnimported,
249287
"completionBudget": budget,
250288
},
251-
}, "completionFollowingEdit", false)
289+
}, "completion", false)
252290
defer env.Close()
253291

254292
env.CreateBuffer(test.file, "// __TEST_PLACEHOLDER_0__\n"+test.content)
@@ -278,12 +316,14 @@ func runCompletionFollowingEdit(b *testing.B, test completionFollowingEditTest,
278316

279317
b.ResetTimer()
280318

281-
if stopAndRecord := startProfileIfSupported(b, env, qualifiedName(test.repo, "completionFollowingEdit")); stopAndRecord != nil {
319+
if stopAndRecord := startProfileIfSupported(b, env, qualifiedName(test.repo, "completion")); stopAndRecord != nil {
282320
defer stopAndRecord()
283321
}
284322

285323
for i := 0; i < b.N; i++ {
286-
editPlaceholder()
324+
if followingEdit {
325+
editPlaceholder()
326+
}
287327
loc := env.RegexpSearch(test.file, test.locationRegexp)
288328
env.Completion(loc)
289329
}

0 commit comments

Comments
 (0)