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  }