blob: add07838322564c5efeb5ae39177aafb29276b18 [file] [log] [blame] [edit]
// Copyright 2021 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 token_test
import (
"go/build"
"go/token"
"math/rand/v2"
"os"
"path/filepath"
"testing"
)
func BenchmarkSearchInts(b *testing.B) {
data := make([]int, 10000)
for i := 0; i < 10000; i++ {
data[i] = i
}
const x = 8
if r := token.SearchInts(data, x); r != x {
b.Errorf("got index = %d; want %d", r, x)
}
b.ResetTimer()
for i := 0; i < b.N; i++ {
token.SearchInts(data, x)
}
}
func BenchmarkFileSet_Position(b *testing.B) {
rng := rand.New(rand.NewPCG(rand.Uint64(), rand.Uint64()))
// Create a FileSet based on the files of net/http,
// a single large package.
netHTTPFset := token.NewFileSet()
pkg, err := build.Default.Import("net/http", "", 0)
if err != nil {
b.Fatal(err)
}
for _, filename := range pkg.GoFiles {
filename = filepath.Join(pkg.Dir, filename)
fi, err := os.Stat(filename)
if err != nil {
b.Fatal(err)
}
netHTTPFset.AddFile(filename, -1, int(fi.Size()))
}
// Measure randomly distributed Pos values across net/http.
b.Run("random", func(b *testing.B) {
base := netHTTPFset.Base()
for b.Loop() {
pos := token.Pos(rng.IntN(base))
_ = netHTTPFset.Position(pos)
}
})
// Measure random lookups within the same file of net/http.
// (It's faster because of the "last file" cache.)
b.Run("file", func(b *testing.B) {
var file *token.File
for file = range netHTTPFset.Iterate {
break
}
base, size := file.Base(), file.Size()
for b.Loop() {
_ = netHTTPFset.Position(token.Pos(base + rng.IntN(size)))
}
})
// Measure random lookups on a FileSet with a great many files.
b.Run("manyfiles", func(b *testing.B) {
fset := token.NewFileSet()
for range 25000 {
fset.AddFile("", -1, 10000)
}
base := fset.Base()
for b.Loop() {
pos := token.Pos(rng.IntN(base))
_ = fset.Position(pos)
}
})
}
func BenchmarkFileSet_AddExistingFiles(b *testing.B) {
rng := rand.New(rand.NewPCG(rand.Uint64(), rand.Uint64()))
// Create the "universe" of files.
fset := token.NewFileSet()
var files []*token.File
for range 25000 {
files = append(files, fset.AddFile("", -1, 10000))
}
token.Shuffle(rng, files)
// choose returns n random files.
choose := func(n int) []*token.File {
res := make([]*token.File, n)
for i := range res {
res[i] = files[rand.IntN(n)]
}
return files[:n]
}
// Measure the cost of creating a FileSet with a large number
// of files added in small handfuls, with some overlap.
// This case is critical to gopls.
b.Run("sequence", func(b *testing.B) {
for b.Loop() {
b.StopTimer()
fset2 := token.NewFileSet()
fset2.AddExistingFiles(files[:10000]...)
b.StartTimer()
for range 1000 {
fset2.AddExistingFiles(choose(10)...) // about one package
}
}
})
}