Skip to content

Instantly share code, notes, and snippets.

@excavador
Created July 9, 2024 15:26
Show Gist options
  • Save excavador/52c358d456ada6d68e17a47d73e976b3 to your computer and use it in GitHub Desktop.
Save excavador/52c358d456ada6d68e17a47d73e976b3 to your computer and use it in GitHub Desktop.
Example on how to make comparative benchmark in Golang

There is hash_test.go

How to run each benchmark once to see the list of them

➜ go test -run=. -bench=. -benchtime=1x .
goos: linux
goarch: amd64
pkg: github.com/example/benchmark
cpu: 11th Gen Intel(R) Core(TM) i7-1165G7 @ 2.80GHz
Benchmark/load=RAM/hash=sha1-8         	       1	  35781627 ns/op	33556616 B/op	       8 allocs/op
Benchmark/load=RAM/hash=sha256-8       	       1	  22204713 ns/op	33554600 B/op	       4 allocs/op
Benchmark/load=RAM/hash=sha512-8       	       1	  52675641 ns/op	33554720 B/op	       3 allocs/op
Benchmark/load=CPU/hash=sha1-8         	       1	  30481283 ns/op	 1048720 B/op	       4 allocs/op
Benchmark/load=CPU/hash=sha256-8       	       1	  18132268 ns/op	 1048736 B/op	       3 allocs/op
Benchmark/load=CPU/hash=sha512-8       	       1	  47242309 ns/op	 1048864 B/op	       3 allocs/op
PASS
ok  	github.com/example/benchmark	0.212s

How to generate results

➜ go test -run='.' -bench="." -count=20 > result.txt
...

How to summarize results

➜ go run golang.org/x/perf/cmd/benchstat@latest -col=/hash result.txt

goos: linux
goarch: amd64
pkg: github.com/example/benchmark
cpu: 11th Gen Intel(R) Core(TM) i7-1165G7 @ 2.80GHz
            │     sha1     │               sha256                │               sha512                │
            │    sec/op    │   sec/op     vs base                │   sec/op     vs base                │
/load=RAM-8   43.01m ± 23%   27.12m ± 1%  -36.95% (p=0.000 n=20)   65.82m ± 1%  +53.03% (p=0.000 n=20)
/load=CPU-8   36.60m ±  2%   22.21m ± 1%  -39.33% (p=0.000 n=20)   60.62m ± 1%  +65.62% (p=0.000 n=20)
geomean       39.68m         24.54m       -38.15%                  63.17m       +59.20%

            │     sha1     │               sha256                │               sha512                │
            │     B/op     │     B/op      vs base               │     B/op      vs base               │
/load=RAM-8   32.00Mi ± 0%   32.00Mi ± 0%  +0.00% (p=0.000 n=20)   32.00Mi ± 0%  +0.00% (p=0.000 n=20)
/load=CPU-8   1.000Mi ± 0%   1.000Mi ± 0%  +0.00% (p=0.000 n=20)   1.000Mi ± 0%  +0.00% (p=0.000 n=20)
geomean       5.657Mi        5.657Mi       +0.00%                  5.657Mi       +0.00%

            │    sha1    │               sha256                │               sha512                │
            │ allocs/op  │ allocs/op   vs base                 │ allocs/op   vs base                 │
/load=RAM-8   2.000 ± 0%   2.000 ± 0%       ~ (p=1.000 n=20) ¹   2.000 ± 0%       ~ (p=1.000 n=20) ¹
/load=CPU-8   2.000 ± 0%   2.000 ± 0%       ~ (p=1.000 n=20) ¹   2.000 ± 0%       ~ (p=1.000 n=20) ¹
geomean       2.000        2.000       +0.00%                    2.000       +0.00%
¹ all samples are equal
package benchmark
import (
"crypto/sha1"
"crypto/sha256"
"crypto/sha512"
"encoding/binary"
"hash"
"testing"
)
const size = 1024 * 1024
const X = 32
var source []byte
func init() {
source = make([]byte, X*size)
for i := uint64(0); i < uint64(len(source))/8; i += 8 {
binary.BigEndian.PutUint64(source[i:i+8], i)
}
}
func Compute(h hash.Hash, data []byte, round int) {
h.Reset()
for i := 0; i < round; i++ {
h.Write(data)
}
_ = h.Sum(nil)
}
func Bench(b *testing.B, h hash.Hash, memX int, round int) {
b.ReportAllocs()
for i := 0; i < b.N; i++ {
var buffer = make([]byte, size*memX)
copy(buffer, source)
Compute(h, buffer, round)
}
}
func Suote(b *testing.B, memX int, round int) {
b.Run("hash=sha1", func(b *testing.B) {
Bench(b, sha1.New(), memX, round)
})
b.Run("hash=sha256", func(b *testing.B) {
Bench(b, sha256.New(), memX, round)
})
b.Run("hash=sha512", func(b *testing.B) {
Bench(b, sha512.New(), memX, round)
})
}
func Benchmark(b *testing.B) {
b.Run("load=RAM", func(b *testing.B) {
Suote(b, X, 1)
})
b.Run("load=CPU", func(b *testing.B) {
Suote(b, 1, X)
})
}
@excavador
Copy link
Author

Alternative way to render results

➜ go run golang.org/x/perf/cmd/benchstat@latest -row=/load -col=/hash result.txt
goos: linux
goarch: amd64
pkg: github.com/example/benchmark
cpu: 11th Gen Intel(R) Core(TM) i7-1165G7 @ 2.80GHz
        │     sha1     │               sha256                │               sha512                │
        │    sec/op    │   sec/op     vs base                │   sec/op     vs base                │
RAM       43.01m ± 23%   27.12m ± 1%  -36.95% (p=0.000 n=20)   65.82m ± 1%  +53.03% (p=0.000 n=20)
CPU       36.60m ±  2%   22.21m ± 1%  -39.33% (p=0.000 n=20)   60.62m ± 1%  +65.62% (p=0.000 n=20)
geomean   39.68m         24.54m       -38.15%                  63.17m       +59.20%

        │     sha1     │               sha256                │               sha512                │
        │     B/op     │     B/op      vs base               │     B/op      vs base               │
RAM       32.00Mi ± 0%   32.00Mi ± 0%  +0.00% (p=0.000 n=20)   32.00Mi ± 0%  +0.00% (p=0.000 n=20)
CPU       1.000Mi ± 0%   1.000Mi ± 0%  +0.00% (p=0.000 n=20)   1.000Mi ± 0%  +0.00% (p=0.000 n=20)
geomean   5.657Mi        5.657Mi       +0.00%                  5.657Mi       +0.00%

        │    sha1    │               sha256                │               sha512                │
        │ allocs/op  │ allocs/op   vs base                 │ allocs/op   vs base                 │
RAM       2.000 ± 0%   2.000 ± 0%       ~ (p=1.000 n=20) ¹   2.000 ± 0%       ~ (p=1.000 n=20) ¹
CPU       2.000 ± 0%   2.000 ± 0%       ~ (p=1.000 n=20) ¹   2.000 ± 0%       ~ (p=1.000 n=20) ¹
geomean   2.000        2.000       +0.00%                    2.000       +0.00%
¹ all samples are equal

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment