@@ -18,16 +18,21 @@ import (
1818type completionBenchOptions struct {
1919 file , locationRegexp string
2020
21- // hook to run edits before initial completion
22- preCompletionEdits func (* Env )
21+ // Hooks to run edits before initial completion
22+ setup func (* Env ) // run before the benchmark starts
23+ beforeCompletion func (* Env ) // run before each completion
2324}
2425
2526func benchmarkCompletion (options completionBenchOptions , b * testing.B ) {
2627 dir := benchmarkDir ()
2728
2829 // Use a new environment for each test, to avoid any existing state from the
2930 // previous session.
30- sandbox , editor , awaiter , err := connectEditor (dir )
31+ sandbox , editor , awaiter , err := connectEditor (dir , fake.EditorConfig {
32+ Settings : map [string ]interface {}{
33+ "completionBudget" : "1m" , // arbitrary long completion budget
34+ },
35+ })
3136 if err != nil {
3237 b .Fatal (err )
3338 }
@@ -45,11 +50,10 @@ func benchmarkCompletion(options completionBenchOptions, b *testing.B) {
4550 Sandbox : sandbox ,
4651 Awaiter : awaiter ,
4752 }
48- env .OpenFile (options .file )
4953
5054 // Run edits required for this completion.
51- if options .preCompletionEdits != nil {
52- options .preCompletionEdits (env )
55+ if options .setup != nil {
56+ options .setup (env )
5357 }
5458
5559 // Run a completion to make sure the system is warm.
@@ -70,6 +74,9 @@ func benchmarkCompletion(options completionBenchOptions, b *testing.B) {
7074 // initialization).
7175 b .Run ("completion" , func (b * testing.B ) {
7276 for i := 0 ; i < b .N ; i ++ {
77+ if options .beforeCompletion != nil {
78+ options .beforeCompletion (env )
79+ }
7380 env .Completion (options .file , pos )
7481 }
7582 })
@@ -92,7 +99,7 @@ func endPosInBuffer(env *Env, name string) fake.Pos {
9299func BenchmarkStructCompletion (b * testing.B ) {
93100 file := "internal/lsp/cache/session.go"
94101
95- preCompletionEdits := func (env * Env ) {
102+ setup := func (env * Env ) {
96103 env .OpenFile (file )
97104 originalBuffer := env .Editor .BufferText (file )
98105 env .EditBuffer (file , fake.Edit {
@@ -102,25 +109,27 @@ func BenchmarkStructCompletion(b *testing.B) {
102109 }
103110
104111 benchmarkCompletion (completionBenchOptions {
105- file : file ,
106- locationRegexp : `var testVariable map\[string\]bool = Session{}(\.)` ,
107- preCompletionEdits : preCompletionEdits ,
112+ file : file ,
113+ locationRegexp : `var testVariable map\[string\]bool = Session{}(\.)` ,
114+ setup : setup ,
108115 }, b )
109116}
110117
111118// Benchmark import completion in tools codebase.
112119func BenchmarkImportCompletion (b * testing.B ) {
120+ const file = "internal/lsp/source/completion/completion.go"
113121 benchmarkCompletion (completionBenchOptions {
114- file : "internal/lsp/source/completion/completion.go" ,
122+ file : file ,
115123 locationRegexp : `go\/()` ,
124+ setup : func (env * Env ) { env .OpenFile (file ) },
116125 }, b )
117126}
118127
119128// Benchmark slice completion in tools codebase.
120129func BenchmarkSliceCompletion (b * testing.B ) {
121130 file := "internal/lsp/cache/session.go"
122131
123- preCompletionEdits := func (env * Env ) {
132+ setup := func (env * Env ) {
124133 env .OpenFile (file )
125134 originalBuffer := env .Editor .BufferText (file )
126135 env .EditBuffer (file , fake.Edit {
@@ -130,9 +139,9 @@ func BenchmarkSliceCompletion(b *testing.B) {
130139 }
131140
132141 benchmarkCompletion (completionBenchOptions {
133- file : file ,
134- locationRegexp : `var testVariable \[\]byte (=)` ,
135- preCompletionEdits : preCompletionEdits ,
142+ file : file ,
143+ locationRegexp : `var testVariable \[\]byte (=)` ,
144+ setup : setup ,
136145 }, b )
137146}
138147
@@ -144,7 +153,7 @@ func (c *completer) _() {
144153 c.inference.kindMatches(c.)
145154}
146155`
147- preCompletionEdits := func (env * Env ) {
156+ setup := func (env * Env ) {
148157 env .OpenFile (file )
149158 originalBuffer := env .Editor .BufferText (file )
150159 env .EditBuffer (file , fake.Edit {
@@ -154,8 +163,42 @@ func (c *completer) _() {
154163 }
155164
156165 benchmarkCompletion (completionBenchOptions {
157- file : file ,
158- locationRegexp : `func \(c \*completer\) _\(\) {\n\tc\.inference\.kindMatches\((c)` ,
159- preCompletionEdits : preCompletionEdits ,
166+ file : file ,
167+ locationRegexp : `func \(c \*completer\) _\(\) {\n\tc\.inference\.kindMatches\((c)` ,
168+ setup : setup ,
169+ }, b )
170+ }
171+
172+ // Benchmark completion following an arbitrary edit.
173+ //
174+ // Edits force type-checked packages to be invalidated, so we want to measure
175+ // how long it takes before completion results are available.
176+ func BenchmarkCompletionFollowingEdit (b * testing.B ) {
177+ file := "internal/lsp/source/completion/completion2.go"
178+ fileContent := `
179+ package completion
180+
181+ func (c *completer) _() {
182+ c.inference.kindMatches(c.)
183+ // __MAGIC_STRING_1
184+ }
185+ `
186+ setup := func (env * Env ) {
187+ env .CreateBuffer (file , fileContent )
188+ }
189+
190+ n := 1
191+ beforeCompletion := func (env * Env ) {
192+ old := fmt .Sprintf ("__MAGIC_STRING_%d" , n )
193+ new := fmt .Sprintf ("__MAGIC_STRING_%d" , n + 1 )
194+ n ++
195+ env .RegexpReplace (file , old , new )
196+ }
197+
198+ benchmarkCompletion (completionBenchOptions {
199+ file : file ,
200+ locationRegexp : `func \(c \*completer\) _\(\) {\n\tc\.inference\.kindMatches\((c)` ,
201+ setup : setup ,
202+ beforeCompletion : beforeCompletion ,
160203 }, b )
161204}
0 commit comments