gopls/internal/test: attempt to fix BenchmarkSemanticTokens
The reason we haven't been generating new benchmarks
for x/tools is that they're all failing:
https://ci.chromium.org/ui/p/golang/builders/ci/x_tools-go1.26-linux-arm64_c4as16-perf_vs_gopls_0_11?status=FAILURE
Specifically, the BenchmarkSemanticTokens is failing with:
"panic: runtime error: index out of range [17] with length 0"
https://logs.chromium.org/logs/golang/buildbucket/cr-buildbucket/8677996571488419617/+/u/step/27/log/3
The panic is coming from interpretTokens when it tries to access an
index in legend.TokenTypes. legend.TokenTypes is only empty when
SemanticTokensProvider is nil, if the editor environment is
initialized to not provide semantic tokens. However, the BenchmarkSemanticTokens
does set semanticTokens = true when calling newEnv, so this is confusing.
The benchmarks don't fail locally, so maybe there is some concurrency
issue with the env that it doesn't initialize the semantic token
provider correctly. We should call env.Close() to cleanup the env
after the benchmark run finishes. Do this in BenchmarkSemanticTokens
and also in BenchmarkDiagnosePackageFiles.
We could also make interpretTokens safer by checking if legend.TokenTypes
is empty, but I'm not sure.
For golang/go#80113
diff --git a/gopls/internal/test/integration/bench/diagnostic_test.go b/gopls/internal/test/integration/bench/diagnostic_test.go
index 39b3a9c..3e4cee9 100644
--- a/gopls/internal/test/integration/bench/diagnostic_test.go
+++ b/gopls/internal/test/integration/bench/diagnostic_test.go
@@ -29,6 +29,7 @@
"pullDiagnostics": true, // currently required for pull diagnostic support
},
}, "diagnosePackageFiles", false)
+ defer env.Close()
// 10 arbitrary files in a single package.
files := []string{
diff --git a/gopls/internal/test/integration/bench/semtok_test.go b/gopls/internal/test/integration/bench/semtok_test.go
index 4f9d290..fc162d5 100644
--- a/gopls/internal/test/integration/bench/semtok_test.go
+++ b/gopls/internal/test/integration/bench/semtok_test.go
@@ -17,6 +17,7 @@
"semanticTokens": true,
},
}, "SemanticTokens", false)
+ defer env.Close()
env.Await(InitialWorkspaceLoad)
| Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. |
| Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. |
Thanks for investigating!
Should every newEnv call be paired with a call to Close? I count six calls to Close and 7 to newEnv.
It might be less error-prone to change the type of newEnv to return a pair `(env *Env, close func())` so that the caller must think about the close function. Then no Close method is needed.
| Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. |
| Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. |
Thanks for investigating!
Should every newEnv call be paired with a call to Close? I count six calls to Close and 7 to newEnv.
It might be less error-prone to change the type of newEnv to return a pair `(env *Env, close func())` so that the caller must think about the close function. Then no Close method is needed.
Yep, each newEnv should have a corresponding Close, I thought I got them all.
That sounds good, but we can't delete Close because it's also used in cleanup() which runs on the shared repos after benchmarks have finished.
| Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. |
// must be called on the Env when it is no longer needed.called when the Env is
env.Close()```
if err := env.Close(); err != nil {
tb.Log(err)
}
```
so we don't lose this information from the log.
| Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. |
| Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. |
// must be called on the Env when it is no longer needed.called when the Env is
Done
env.Close()```
if err := env.Close(); err != nil {
tb.Log(err)
}
```
so we don't lose this information from the log.
*Env.Close doesn't return anything and already does TB.Errorf on error (*repo.Close returns error). Should I change that behavior?
| Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. |
env.Close()Madeline Kalil```
if err := env.Close(); err != nil {
tb.Log(err)
}
```
so we don't lose this information from the log.
*Env.Close doesn't return anything and already does TB.Errorf on error (*repo.Close returns error). Should I change that behavior?
No; sorry, I got confused by seeing repo.Close below, which is only for use after sharedEnv, I think. So you can change the code to simply `return env, env.Close`.
| Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. |
| Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. |
| Commit-Queue | +1 |
env.Close()Madeline Kalil```
if err := env.Close(); err != nil {
tb.Log(err)
}
```
so we don't lose this information from the log.
Alan Donovan*Env.Close doesn't return anything and already does TB.Errorf on error (*repo.Close returns error). Should I change that behavior?
No; sorry, I got confused by seeing repo.Close below, which is only for use after sharedEnv, I think. So you can change the code to simply `return env, env.Close`.
| Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. |
| Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. |
| Code-Review | +2 |
| Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. |
gopls/internal/test: attempt to fix BenchmarkSemanticTokens
The reason we haven't been generating new benchmarks
for x/tools is that they're all failing:
https://ci.chromium.org/ui/p/golang/builders/ci/x_tools-go1.26-linux-arm64_c4as16-perf_vs_gopls_0_11?status=FAILURE
Specifically, the BenchmarkSemanticTokens is failing with:
"panic: runtime error: index out of range [17] with length 0"
https://logs.chromium.org/logs/golang/buildbucket/cr-buildbucket/8677996571488419617/+/u/step/27/log/3
The panic is coming from interpretTokens when it tries to access an
index in legend.TokenTypes. legend.TokenTypes is only empty when
SemanticTokensProvider is nil, if the editor environment is
initialized to not provide semantic tokens. However, the BenchmarkSemanticTokens
does set semanticTokens = true when calling newEnv, so this is confusing.
The benchmarks don't fail locally, so maybe there is some concurrency
issue with the env that it doesn't initialize the semantic token
provider correctly. We should call env.Close() to cleanup the env
after the benchmark run finishes. Do this in BenchmarkSemanticTokens
and also in BenchmarkDiagnosePackageFiles.
We could also make interpretTokens safer by checking if legend.TokenTypes
is empty, but I'm not sure.
For golang/go#80113
| Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. |