github.com/zeebo/mon@v0.0.0-20211012163247-13d39bdb54fa/inthist/varint_test.go (about)

     1  package inthist
     2  
     3  import (
     4  	"encoding/binary"
     5  	"fmt"
     6  	"runtime"
     7  	"testing"
     8  
     9  	"github.com/zeebo/assert"
    10  	"github.com/zeebo/mon/internal/buffer"
    11  	"github.com/zeebo/pcg"
    12  )
    13  
    14  func TestVarint(t *testing.T) {
    15  	var le = binary.LittleEndian
    16  
    17  	t.Run("Safe", func(t *testing.T) {
    18  		for i := uint(0); i <= 32; i++ {
    19  			buf := buffer.Of(make([]byte, 5))
    20  
    21  			nbytes, val := varintStats(1<<i - 1)
    22  			buf = buf.Grow()
    23  			le.PutUint64(buf.Front8()[:], val)
    24  			buf = buf.Advance(uintptr(nbytes))
    25  
    26  			got, _, ok := safeVarintConsume(buf.Reset())
    27  			assert.That(t, ok)
    28  			assert.Equal(t, uint32(1<<i-1), got)
    29  
    30  			t.Logf("%-2d %032b %08b\n", i, got, buf.Prefix())
    31  		}
    32  	})
    33  
    34  	t.Run("Fast", func(t *testing.T) {
    35  		for i := uint(0); i <= 32; i++ {
    36  			buf := buffer.Of(make([]byte, 8))
    37  
    38  			nbytes, val := varintStats(1<<i - 1)
    39  			buf = buf.Grow()
    40  			le.PutUint64(buf.Front8()[:], val)
    41  			buf = buf.Advance(uintptr(nbytes))
    42  
    43  			_, dec := fastVarintConsume(le.Uint64(buf.Reset().Front8()[:]))
    44  			assert.Equal(t, uint32(1<<i-1), dec)
    45  
    46  			t.Logf("%-2d %032b %08b\n", i, dec, buf.Prefix())
    47  		}
    48  	})
    49  }
    50  
    51  func BenchmarkVarint(b *testing.B) {
    52  	var le = binary.LittleEndian
    53  
    54  	randVals := make([]uint32, 1024*1024)
    55  	for i := range randVals {
    56  		randVals[i] = uint32(1<<pcg.Uint32n(32) - 1)
    57  	}
    58  	randBuf := buffer.Of(make([]byte, 16))
    59  	for _, val := range randVals {
    60  		nbytes, enc := varintStats(val)
    61  		randBuf = randBuf.Grow()
    62  		le.PutUint64(randBuf.Front8()[:], enc)
    63  		randBuf = randBuf.Advance(uintptr(nbytes))
    64  	}
    65  	randBuf = randBuf.Reset()
    66  
    67  	b.Run("Stats", func(b *testing.B) {
    68  		for _, i := range []uint{1, 32} {
    69  			b.Run(fmt.Sprint(i), func(b *testing.B) {
    70  				n := uint32(1<<i - 1)
    71  
    72  				var x uint8
    73  				var y uint64
    74  				for i := 0; i < b.N; i++ {
    75  					x, y = varintStats(n)
    76  				}
    77  				runtime.KeepAlive(x)
    78  				runtime.KeepAlive(y)
    79  			})
    80  		}
    81  
    82  		b.Run("Rand", func(b *testing.B) {
    83  			var x uint8
    84  			var y uint64
    85  			for i := 0; i < b.N; i++ {
    86  				x, y = varintStats(randVals[i%(1024*1024)])
    87  			}
    88  			runtime.KeepAlive(x)
    89  			runtime.KeepAlive(y)
    90  		})
    91  	})
    92  
    93  	b.Run("Append", func(b *testing.B) {
    94  		for _, i := range []uint{1, 32} {
    95  			b.Run(fmt.Sprint(i), func(b *testing.B) {
    96  				n := uint32(1<<i - 1)
    97  				buf := buffer.Of(make([]byte, 16))
    98  
    99  				for i := 0; i < b.N; i++ {
   100  					_, val := varintStats(n)
   101  					buf = buf.Grow()
   102  					le.PutUint64(buf.Front8()[:], val)
   103  				}
   104  			})
   105  		}
   106  
   107  		b.Run("Rand", func(b *testing.B) {
   108  			buf := buffer.Of(make([]byte, 16))
   109  
   110  			for i := 0; i < b.N; i++ {
   111  				_, val := varintStats(randVals[i%(1024*1024)])
   112  				buf = buf.Grow()
   113  				le.PutUint64(buf.Front8()[:], val)
   114  			}
   115  		})
   116  	})
   117  
   118  	b.Run("Consume", func(b *testing.B) {
   119  		for _, i := range []uint{1, 32} {
   120  			b.Run(fmt.Sprint(i), func(b *testing.B) {
   121  				n := uint32(1<<i - 1)
   122  				buf := buffer.Of(make([]byte, 5))
   123  
   124  				nbytes, val := varintStats(n)
   125  				buf = buf.Grow()
   126  				le.PutUint64(buf.Front8()[:], val)
   127  				buf = buf.Advance(uintptr(nbytes))
   128  
   129  				for i := 0; i < b.N; i++ {
   130  					safeVarintConsume(buf)
   131  				}
   132  			})
   133  		}
   134  
   135  		b.Run("Rand", func(b *testing.B) {
   136  			buf := randBuf.Reset()
   137  			for i := 0; i < b.N; i++ {
   138  				if buf.Remaining() == 0 {
   139  					buf = buf.Reset()
   140  				}
   141  				_, buf, _ = safeVarintConsume(buf)
   142  			}
   143  		})
   144  	})
   145  
   146  	b.Run("FastConsume", func(b *testing.B) {
   147  		for _, i := range []uint{1, 32} {
   148  			b.Run(fmt.Sprint(i), func(b *testing.B) {
   149  				n := uint32(1<<i - 1)
   150  				buf := buffer.Of(make([]byte, 8))
   151  
   152  				nbytes, val := varintStats(n)
   153  				buf = buf.Grow()
   154  				le.PutUint64(buf.Front8()[:], val)
   155  				buf = buf.Advance(uintptr(nbytes))
   156  
   157  				var dec uint32
   158  				for i := 0; i < b.N; i++ {
   159  					_, dec = fastVarintConsume(le.Uint64(buf.Front8()[:]))
   160  				}
   161  				runtime.KeepAlive(dec)
   162  			})
   163  		}
   164  
   165  		b.Run("Rand", func(b *testing.B) {
   166  			buf := randBuf.Reset()
   167  			for i := 0; i < b.N; i++ {
   168  				if buf.Remaining() < 8 {
   169  					buf = buf.Reset()
   170  				}
   171  				nbytes, _ := fastVarintConsume(le.Uint64(buf.Front8()[:]))
   172  				buf = buf.Advance(uintptr(nbytes))
   173  			}
   174  		})
   175  	})
   176  }