| // 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 |
| } |
| } |
| }) |
| } |