Skip to content

Instantly share code, notes, and snippets.

@odeke-em
Created February 10, 2018 07:16
Show Gist options
  • Save odeke-em/1b0bdd33304ab3190e6a09776880dae9 to your computer and use it in GitHub Desktop.
Save odeke-em/1b0bdd33304ab3190e6a09776880dae9 to your computer and use it in GitHub Desktop.
Benchmarking naive UvarintSize vs simple shifts
$ go test -v -run=^$ -count=10
$ benchstat old.txt new.txt
$ benchstat old.txt new.txt 
name    old time/op    new time/op    delta
Size-4     139ns ± 3%      83ns ± 2%  -40.39%         (p=0.000 n=9+10)

name    old alloc/op   new alloc/op   delta
Size-4    0.00B ±NaN%    0.00B ±NaN%     ~     (all samples are equal)

name    old allocs/op  new allocs/op  delta
Size-4     0.00 ±NaN%     0.00 ±NaN%     ~     (all samples are equal)
package ft
import (
"encoding/binary"
"testing"
)
func uvarintSize(i uint64) int {
var buf [10]byte
return binary.PutUvarint(buf[:], i)
}
func byShifts(i uint64) int {
n := 1
// every border of 128 counts a byte
// so 0x80 delinates the next increment of a byte.
// ie every 7 bits.
for i >= 0x80 {
i >>= 7
n += 1
}
return n
}
var values = []struct {
n uint64
want int
}{
{0, 1},
{1, 1},
{2, 1},
{0x7F, 1}, // 127, that's exactly 1
{0x80, 2},
{0xFF, 2},
{0xFFE, 2}, // Because 0x0FFE
{0x1FFE, 2},
{0x8080, 3}, // 0x80, needs 2 bytes, 127 for 1 and the +1
{0xFF1FFE, 4},
{0x10FF1FF1, 5},
{0x010FF1FF1, 5},
{0x310FF1FF1, 5},
{0x1310000000, 6},
{0xFF1310000000, 7},
{0x10FF1310000000, 8},
}
func BenchmarkUvarintSize(b *testing.B) {
for e := 0; e < b.N; e++ {
for i, v := range values {
if got, want := uvarintSize(v.n), v.want; got != want {
b.Fatalf("#%d (%+v) got=%d want=%d", i, v, got, want)
}
}
}
b.ReportAllocs()
}
func BenchmarkWithShifts(b *testing.B) {
for e := 0; e < b.N; e++ {
for i, v := range values {
if got, want := byShifts(v.n), v.want; got != want {
b.Fatalf("#%d (%+v) got=%d want=%d", i, v, got, want)
}
}
}
b.ReportAllocs()
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment