mirror of
https://github.com/golang/go
synced 2024-11-18 12:54:44 -07:00
06cc1d0a36
Add additional benchmarks following the pattern of symbol benchmarks. One for initial workspace load, and another for completion. Change-Id: Iba826b188cb81dffabb1b08287dc7b76250dc54c Reviewed-on: https://go-review.googlesource.com/c/tools/+/250802 Run-TryBot: Robert Findley <rfindley@google.com> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Rebecca Stambler <rstambler@golang.org>
160 lines
5.1 KiB
Go
160 lines
5.1 KiB
Go
// Copyright 2020 The Go Authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style
|
|
// license that can be found in the LICENSE file.
|
|
|
|
package regtest
|
|
|
|
import (
|
|
"flag"
|
|
"fmt"
|
|
"testing"
|
|
|
|
"golang.org/x/tools/internal/lsp"
|
|
"golang.org/x/tools/internal/lsp/fake"
|
|
"golang.org/x/tools/internal/lsp/protocol"
|
|
)
|
|
|
|
var iwlBench = struct {
|
|
workdir string
|
|
}{}
|
|
|
|
func init() {
|
|
flag.StringVar(&iwlBench.workdir, "iwl_workdir", "", "if set, run IWL benchmark in this directory")
|
|
}
|
|
|
|
func TestBenchmarkIWL(t *testing.T) {
|
|
if iwlBench.workdir == "" {
|
|
t.Skip("-iwl_workdir not configured")
|
|
}
|
|
opts := stressTestOptions(iwlBench.workdir)
|
|
// Don't skip hooks, so that we can wait for IWL.
|
|
opts = append(opts, SkipHooks(false))
|
|
b := testing.Benchmark(func(b *testing.B) {
|
|
for i := 0; i < b.N; i++ {
|
|
withOptions(opts...).run(t, "", func(t *testing.T, env *Env) {
|
|
env.Await(
|
|
CompletedWork(lsp.DiagnosticWorkTitle(lsp.FromInitialWorkspaceLoad), 1),
|
|
)
|
|
})
|
|
}
|
|
})
|
|
printBench(b)
|
|
}
|
|
|
|
var symbolBench = struct {
|
|
workdir, query, matcher, style string
|
|
printResults bool
|
|
}{}
|
|
|
|
func init() {
|
|
flag.StringVar(&symbolBench.workdir, "symbol_workdir", "", "if set, run symbol benchmark in this directory")
|
|
flag.StringVar(&symbolBench.query, "symbol_query", "test", "symbol query to use in benchmark")
|
|
flag.StringVar(&symbolBench.matcher, "symbol_matcher", "", "symbol matcher to use in benchmark")
|
|
flag.StringVar(&symbolBench.style, "symbol_style", "", "symbol style to use in benchmark")
|
|
flag.BoolVar(&symbolBench.printResults, "symbol_print_results", false, "whether to print symbol query results")
|
|
}
|
|
|
|
func TestBenchmarkSymbols(t *testing.T) {
|
|
if symbolBench.workdir == "" {
|
|
t.Skip("-symbol_workdir not configured")
|
|
}
|
|
opts := stressTestOptions(symbolBench.workdir)
|
|
conf := fake.EditorConfig{}
|
|
if symbolBench.matcher != "" {
|
|
conf.SymbolMatcher = &symbolBench.matcher
|
|
}
|
|
if symbolBench.style != "" {
|
|
conf.SymbolStyle = &symbolBench.style
|
|
}
|
|
opts = append(opts, WithEditorConfig(conf))
|
|
withOptions(opts...).run(t, "", func(t *testing.T, env *Env) {
|
|
// We can't Await in this test, since we have disabled hooks. Instead, run
|
|
// one symbol request to completion to ensure all necessary cache entries
|
|
// are populated.
|
|
results, err := env.Editor.Server.Symbol(env.Ctx, &protocol.WorkspaceSymbolParams{
|
|
Query: symbolBench.query,
|
|
})
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if symbolBench.printResults {
|
|
fmt.Println("Results:")
|
|
for i := 0; i < len(results); i++ {
|
|
fmt.Printf("\t%d. %s\n", i, results[i].Name)
|
|
}
|
|
}
|
|
b := testing.Benchmark(func(b *testing.B) {
|
|
for i := 0; i < b.N; i++ {
|
|
if _, err := env.Editor.Server.Symbol(env.Ctx, &protocol.WorkspaceSymbolParams{
|
|
Query: symbolBench.query,
|
|
}); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
}
|
|
})
|
|
printBench(b)
|
|
})
|
|
}
|
|
|
|
func printBench(b testing.BenchmarkResult) {
|
|
fmt.Println("Benchmark stats:")
|
|
fmt.Println(b.String())
|
|
fmt.Println(b.MemString())
|
|
}
|
|
|
|
func dummyCompletionBenchmarkFunction() { const s = "placeholder"; fmt.Printf("%s", s) }
|
|
|
|
var completionBench = struct {
|
|
workdir, fileName, locationRegexp string
|
|
printResults bool
|
|
}{}
|
|
|
|
func init() {
|
|
flag.StringVar(&completionBench.workdir, "completion_workdir", "", "if set run completion benchmark in this directory (other benchmark flags expect an x/tools dir)")
|
|
flag.StringVar(&completionBench.fileName, "completion_file", "internal/lsp/regtest/bench_test.go", "relative path to the file to complete")
|
|
flag.StringVar(&completionBench.locationRegexp, "completion_regexp", `dummyCompletionBenchmarkFunction.*fmt\.Printf\("%s", s(\))`, "regexp location to complete at")
|
|
flag.BoolVar(&completionBench.printResults, "completion_print_results", false, "whether to print completion results")
|
|
}
|
|
|
|
func TestBenchmarkCompletion(t *testing.T) {
|
|
if completionBench.workdir == "" {
|
|
t.Skip("-completion_workdir not configured")
|
|
}
|
|
opts := stressTestOptions(completionBench.workdir)
|
|
// Completion gives bad results if IWL is not yet complete, so we must await
|
|
// it first (and therefore need hooks).
|
|
opts = append(opts, SkipHooks(false))
|
|
withOptions(opts...).run(t, "", func(t *testing.T, env *Env) {
|
|
env.Await(
|
|
CompletedWork(lsp.DiagnosticWorkTitle(lsp.FromInitialWorkspaceLoad), 1),
|
|
)
|
|
env.OpenFile(completionBench.fileName)
|
|
params := &protocol.CompletionParams{}
|
|
params.Context.TriggerCharacter = "s"
|
|
params.Context.TriggerKind = protocol.TriggerCharacter
|
|
params.TextDocument.URI = env.Sandbox.Workdir.URI(completionBench.fileName)
|
|
params.Position = env.RegexpSearch(completionBench.fileName, completionBench.locationRegexp).ToProtocolPosition()
|
|
|
|
// Run one completion to make sure everything is warm.
|
|
list, err := env.Editor.Server.Completion(env.Ctx, params)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if completionBench.printResults {
|
|
fmt.Println("Results:")
|
|
for i := 0; i < len(list.Items); i++ {
|
|
fmt.Printf("\t%d. %v\n", i, list.Items[i])
|
|
}
|
|
}
|
|
b := testing.Benchmark(func(b *testing.B) {
|
|
for i := 0; i < b.N; i++ {
|
|
_, err := env.Editor.Server.Completion(env.Ctx, params)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
}
|
|
})
|
|
printBench(b)
|
|
})
|
|
}
|