testing
package to write benchmarks. func BenchmarkSample(b *testing.B) { for i := 0; i < bN; i++ { if x := fmt.Sprintf("%d", 42); x != "42" { b.Fatalf("Unexpected string: %s", x) } } }
go test -bench=. bench_test.go
go test -bench=. bench_test.go
.testing: warning: no tests to run
Pass
BenchmarkSample 10,000,000 206 ns / op
ok command-line-arguments 2.274s
go test -bench=.
tests only the speed of your code, but you can add the -benchmem
flag, which will allow you to test the memory consumption and the number of memory allocations. It will look like this:Pass
BenchmarkSample 10,000,000 208 ns / op 32 B / op 2 allocs / op
b.ReportAllocs()
method.b.SetBytes(n int64)
method. For example: func BenchmarkSample(b *testing.B) { b.SetBytes(2) for i := 0; i < bN; i++ { if x := fmt.Sprintf("%d", 42); x != "42" { b.Fatalf("Unexpected string: %s", x) } } }
Pass
BenchmarkSample 5000000 324 ns / op 6.17 MB / s 32 B / op 2 allocs / op
ok command-line-arguments 1.999s
6.17 MB/s
in my case.Set
data structure for testing: type Set struct { set map[interface{}]struct{} mu sync.Mutex } func (s *Set) Add(x interface{}) { s.mu.Lock() s.set[x] = struct{}{} s.mu.Unlock() } func (s *Set) Delete(x interface{}) { s.mu.Lock() delete(s.set, x) s.mu.Unlock() }
Delete
method: func BenchmarkSetDelete(b *testing.B) { var testSet []string for i := 0; i < 1024; i++ { testSet = append(testSet, strconv.Itoa(i)) } for i := 0; i < bN; i++ { b.StopTimer() set := Set{set: make(map[interface{}]struct{})} for _, elem := range testSet { set.Add(elem) } for _, elem := range testSet { set.Delete(elem) } } }
testSet
slice testSet
included in the first iteration (and this is not a very big problem, because there will be many iterations)Add
method call is included in each iteration.b.ResetTimer()
, b.StopTimer()
and b.StartTimer()
. Here is their use in the previous benchmark: func BenchmarkSetDelete(b *testing.B) { var testSet []string for i := 0; i < 1024; i++ { testSet = append(testSet, strconv.Itoa(i)) } b.ResetTimer() for i := 0; i < bN; i++ { b.StopTimer() set := Set{set: make(map[interface{}]struct{})} for _, elem := range testSet { set.Add(elem) } b.StartTimer() for _, elem := range testSet { set.Delete(elem) } } }
Delete
method.json
and a benchmark for it: type testStruct struct { X int Y string } func (t *testStruct) ToJSON() ([]byte, error) { return json.Marshal(t) } func BenchmarkToJSON(b *testing.B) { tmp := &testStruct{X: 1, Y: "string"} js, err := tmp.ToJSON() if err != nil { b.Fatal(err) } b.SetBytes(int64(len(js))) b.ResetTimer() for i := 0; i < bN; i++ { if _, err := tmp.ToJSON(); err != nil { b.Fatal(err) } } }
ToJSON
method: func (t *testStruct) ToJSON() ([]byte, error) { return []byte(`{"X": ` + strconv.Itoa(tX) + `, "Y": "` + tY + `"}`), nil }
go test -bench =. -benchmem bench_test.go> new.txt
git stash
go test -bench =. -benchmem bench_test.go> old.txt
go get golang.org/x/tools/cmd/benchcmp
. Here are the comparison results:# benchcmp old.txt new.txt
benchmark old ns / op new ns / op delta
BenchmarkToJSON 1579 495 -68.65%
benchmark old MB / s new MB / s speedup
BenchmarkToJSON 12.66 46.41 3.67x
benchmark old allocates new allocs delta
BenchmarkToJSON 2 2 + 0.00%
benchmark old bytes delta
BenchmarkToJSON 184 48 -73.91%
cpu
and memory
profiles during benchmarking:go test -bench =. -benchmem -cpuprofile = cpu.out -memprofile = mem.out bench_test.go
Source: https://habr.com/ru/post/268585/
All Articles