Source file src/go/token/position_bench_test.go

     1  // Copyright 2021 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package token_test
     6  
     7  import (
     8  	"go/build"
     9  	"go/token"
    10  	"math/rand/v2"
    11  	"os"
    12  	"path/filepath"
    13  	"testing"
    14  )
    15  
    16  func BenchmarkSearchInts(b *testing.B) {
    17  	data := make([]int, 10000)
    18  	for i := 0; i < 10000; i++ {
    19  		data[i] = i
    20  	}
    21  	const x = 8
    22  	if r := token.SearchInts(data, x); r != x {
    23  		b.Errorf("got index = %d; want %d", r, x)
    24  	}
    25  	b.ResetTimer()
    26  	for i := 0; i < b.N; i++ {
    27  		token.SearchInts(data, x)
    28  	}
    29  }
    30  
    31  func BenchmarkFileSet_Position(b *testing.B) {
    32  	rng := rand.New(rand.NewPCG(rand.Uint64(), rand.Uint64()))
    33  
    34  	// Create a FileSet based on the files of net/http,
    35  	// a single large package.
    36  	netHTTPFset := token.NewFileSet()
    37  	pkg, err := build.Default.Import("net/http", "", 0)
    38  	if err != nil {
    39  		b.Fatal(err)
    40  	}
    41  	for _, filename := range pkg.GoFiles {
    42  		filename = filepath.Join(pkg.Dir, filename)
    43  		fi, err := os.Stat(filename)
    44  		if err != nil {
    45  			b.Fatal(err)
    46  		}
    47  		netHTTPFset.AddFile(filename, -1, int(fi.Size()))
    48  	}
    49  
    50  	// Measure randomly distributed Pos values across net/http.
    51  	b.Run("random", func(b *testing.B) {
    52  		base := netHTTPFset.Base()
    53  		for b.Loop() {
    54  			pos := token.Pos(rng.IntN(base))
    55  			_ = netHTTPFset.Position(pos)
    56  		}
    57  	})
    58  
    59  	// Measure random lookups within the same file of net/http.
    60  	// (It's faster because of the "last file" cache.)
    61  	b.Run("file", func(b *testing.B) {
    62  		var file *token.File
    63  		for file = range netHTTPFset.Iterate {
    64  			break
    65  		}
    66  		base, size := file.Base(), file.Size()
    67  		for b.Loop() {
    68  			_ = netHTTPFset.Position(token.Pos(base + rng.IntN(size)))
    69  		}
    70  	})
    71  
    72  	// Measure random lookups on a FileSet with a great many files.
    73  	b.Run("manyfiles", func(b *testing.B) {
    74  		fset := token.NewFileSet()
    75  		for range 25000 {
    76  			fset.AddFile("", -1, 10000)
    77  		}
    78  		base := fset.Base()
    79  		for b.Loop() {
    80  			pos := token.Pos(rng.IntN(base))
    81  			_ = fset.Position(pos)
    82  		}
    83  	})
    84  }
    85  
    86  func BenchmarkFileSet_AddExistingFiles(b *testing.B) {
    87  	rng := rand.New(rand.NewPCG(rand.Uint64(), rand.Uint64()))
    88  
    89  	// Create the "universe" of files.
    90  	fset := token.NewFileSet()
    91  	var files []*token.File
    92  	for range 25000 {
    93  		files = append(files, fset.AddFile("", -1, 10000))
    94  	}
    95  	token.Shuffle(rng, files)
    96  
    97  	// choose returns n random files.
    98  	choose := func(n int) []*token.File {
    99  		res := make([]*token.File, n)
   100  		for i := range res {
   101  			res[i] = files[rand.IntN(n)]
   102  		}
   103  		return files[:n]
   104  	}
   105  
   106  	// Measure the cost of	creating a FileSet with a large number
   107  	// of files added in small handfuls, with some overlap.
   108  	// This case is critical to gopls.
   109  	b.Run("sequence", func(b *testing.B) {
   110  		for b.Loop() {
   111  			b.StopTimer()
   112  			fset2 := token.NewFileSet()
   113  			fset2.AddExistingFiles(files[:10000]...)
   114  			b.StartTimer()
   115  
   116  			for range 1000 {
   117  				fset2.AddExistingFiles(choose(10)...) // about one package
   118  			}
   119  		}
   120  	})
   121  }
   122  

View as plain text