github.com/aclements/go-misc@v0.0.0-20240129233631-2f6ede80790c/varint/bench_test.go (about) 1 // Copyright 2016 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 varint 6 7 import ( 8 "fmt" 9 "math/rand" 10 "testing" 11 ) 12 13 func TestDecodeVarintAsm(t *testing.T) { 14 type fn struct { 15 name string 16 f func([]byte) (uint64, int) 17 } 18 for _, f := range []fn{ 19 {"decodeVarintAsmLoop", decodeVarintAsmLoop}, 20 {"decodeVarintAsmBMI2", decodeVarintAsmBMI2}, 21 {"decodeVarintAsm1", decodeVarintAsm1}, 22 {"decodeVarintAsm2", decodeVarintAsm2}, 23 } { 24 for _, bmi2 := range []bool{false, true} { 25 for _, pad := range []bool{false, true} { 26 name := fmt.Sprintf("f:%s/bmi2:%v/pad:%v", f.name, bmi2, pad) 27 t.Run(name, func(t *testing.T) { 28 testDecodeVarintAsm(t, f.f, bmi2, pad) 29 }) 30 } 31 } 32 } 33 } 34 35 func testDecodeVarintAsm(t *testing.T, f func([]byte) (uint64, int), bmi2, pad bool) { 36 if bmi2 && !hasBMI2 { 37 t.Skip("BMI2 not supported on this CPU") 38 } 39 40 oldHasBMI2 := hasBMI2 41 defer func() { hasBMI2 = oldHasBMI2 }() 42 hasBMI2 = bmi2 43 44 padding := []byte{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff} 45 for x1 := uint(0); x1 < 64; x1++ { 46 for x2 := uint(0); x2 < x1; x2++ { 47 var v uint64 = (1 << x1) | (1 << x2) 48 buf := EncodeVarint(v) 49 vlen := len(buf) 50 if pad { 51 buf = append(buf, padding...) 52 } 53 x, n := f(buf) 54 if x != v || n != vlen { 55 t.Errorf("decode(encode(%#x)) = %#x, %d; want %#x, %d %x", v, x, n, v, vlen, buf) 56 } 57 } 58 } 59 } 60 61 var testBuf []byte 62 63 var testLengths [11][]byte 64 65 func init() { 66 r := rand.New(rand.NewSource(1)) 67 for i := 0; i < 1000; i++ { 68 val := uint64(r.Uint32()) 69 testBuf = append(testBuf, EncodeVarint(val)...) 70 } 71 72 for length := 1; length <= 10; length++ { 73 encoded := EncodeVarint(1 << uint(7*(length-1))) 74 if len(encoded) != length { 75 panic("unexpected encoded length") 76 } 77 for i := 0; i < 1000; i++ { 78 testLengths[length] = append(testLengths[length], encoded...) 79 } 80 } 81 } 82 83 func BenchmarkDecodeVarint(b *testing.B) { 84 for i := 0; i < b.N; i++ { 85 buf := testBuf 86 for len(buf) > 0 { 87 _, n := DecodeVarint(buf) 88 buf = buf[n:] 89 } 90 } 91 } 92 93 func BenchmarkDecodeVarintN(b *testing.B) { 94 for length := 1; length < len(testLengths); length++ { 95 name := fmt.Sprintf("bytes:%d", length) 96 b.Run(name, func(b *testing.B) { 97 for i := 0; i < b.N; i++ { 98 buf := testLengths[length] 99 for len(buf) > 0 { 100 _, n := DecodeVarint(buf) 101 buf = buf[n:] 102 } 103 } 104 }) 105 } 106 } 107 108 func BenchmarkDecodeVarintAsmLoop(b *testing.B) { 109 for i := 0; i < b.N; i++ { 110 buf := testBuf 111 for len(buf) > 0 { 112 _, n := decodeVarintAsmLoop(buf) 113 buf = buf[n:] 114 } 115 } 116 } 117 118 func BenchmarkDecodeVarintAsmLoopN(b *testing.B) { 119 for length := 1; length < len(testLengths); length++ { 120 name := fmt.Sprintf("bytes:%d", length) 121 b.Run(name, func(b *testing.B) { 122 for i := 0; i < b.N; i++ { 123 buf := testLengths[length] 124 for len(buf) > 0 { 125 _, n := decodeVarintAsmLoop(buf) 126 buf = buf[n:] 127 } 128 } 129 }) 130 } 131 } 132 133 func BenchmarkDecodeVarintAsmBMI2(b *testing.B) { 134 for i := 0; i < b.N; i++ { 135 buf := testBuf 136 for len(buf) > 0 { 137 _, n := decodeVarintAsmBMI2(buf) 138 buf = buf[n:] 139 } 140 } 141 } 142 143 func BenchmarkDecodeVarintAsmBMI2N(b *testing.B) { 144 for length := 1; length < len(testLengths); length++ { 145 name := fmt.Sprintf("bytes:%d", length) 146 b.Run(name, func(b *testing.B) { 147 for i := 0; i < b.N; i++ { 148 buf := testLengths[length] 149 for len(buf) > 0 { 150 _, n := decodeVarintAsmBMI2(buf) 151 buf = buf[n:] 152 } 153 } 154 }) 155 } 156 } 157 158 func BenchmarkDecodeVarintAsm1(b *testing.B) { 159 for i := 0; i < b.N; i++ { 160 buf := testBuf 161 for len(buf) > 0 { 162 _, n := decodeVarintAsm1(buf) 163 buf = buf[n:] 164 } 165 } 166 } 167 168 func BenchmarkDecodeVarintAsm2(b *testing.B) { 169 for i := 0; i < b.N; i++ { 170 buf := testBuf 171 for len(buf) > 0 { 172 _, n := decodeVarintAsm2(buf) 173 buf = buf[n:] 174 } 175 } 176 }