github.com/egonelbre/exp@v0.0.0-20240430123955-ed1d3aa93911/bench/bulkencoder/encoder_test.go (about) 1 // Hopefully there are no bugs. 2 3 // RasperryPi 4 4 // 5 // goos: linux 6 // goarch: arm64 7 // BenchmarkBulk-4 19346 62017 ns/op 8 // BenchmarkByte-4 13394 89582 ns/op 9 package encoder_test 10 11 import ( 12 "encoding/binary" 13 "testing" 14 ) 15 16 type BulkEncoder struct { 17 fill uint64 18 off uint32 19 20 at uint64 21 data []uint64 22 } 23 24 func NewBulkEncoder(bytes int) *BulkEncoder { 25 return &BulkEncoder{data: make([]uint64, bytes/8)} 26 } 27 28 func (enc *BulkEncoder) WriteByte(v byte) { 29 enc.fill |= uint64(v) << enc.off 30 enc.off += 8 31 if enc.off >= 64 { 32 enc.data[enc.at] = enc.fill 33 enc.at++ 34 enc.fill = 0 35 enc.off = 0 36 } 37 } 38 39 func (enc *BulkEncoder) WriteUint32(v uint32) { 40 enc.fill |= uint64(v) << enc.off 41 enc.off += 32 42 if enc.off >= 64 { 43 enc.off -= 64 44 enc.fill = uint64(v) >> (32 - enc.off) 45 enc.data[enc.at] = enc.fill 46 enc.at++ 47 } 48 } 49 50 func (enc *BulkEncoder) Reset() { 51 enc.fill, enc.off, enc.at = 0, 0, 0 52 } 53 54 type ByteEncoder struct { 55 at uint64 56 data []byte 57 } 58 59 func NewByteEncoder(bytes int) *ByteEncoder { 60 return &ByteEncoder{data: make([]byte, bytes)} 61 } 62 63 func (enc *ByteEncoder) WriteByte(v byte) { 64 enc.data[enc.at] = v 65 enc.at++ 66 } 67 68 func (enc *ByteEncoder) WriteUint32(v uint32) { 69 binary.LittleEndian.PutUint32(enc.data[enc.at:], v) 70 enc.at += 4 71 } 72 73 func (enc *ByteEncoder) Reset() { enc.at = 0 } 74 75 const N = 10 * 1024 76 77 func BenchmarkBulk_byte(b *testing.B) { 78 enc := NewBulkEncoder(N) 79 for k := 0; k < b.N; k++ { 80 enc.Reset() 81 for i := 0; i < N; i++ { 82 enc.WriteByte(byte(i)) 83 } 84 } 85 } 86 87 func BenchmarkBulk_4xbyte(b *testing.B) { 88 enc := NewBulkEncoder(4 * N) 89 for k := 0; k < b.N; k++ { 90 enc.Reset() 91 for i := 0; i < N; i++ { 92 enc.WriteByte(byte(i)) 93 enc.WriteByte(byte(i)) 94 enc.WriteByte(byte(i)) 95 enc.WriteByte(byte(i)) 96 } 97 } 98 } 99 100 func BenchmarkBulk_uint32(b *testing.B) { 101 enc := NewBulkEncoder(N * 4) 102 for k := 0; k < b.N; k++ { 103 enc.Reset() 104 for i := 0; i < N; i++ { 105 enc.WriteUint32(uint32(i)) 106 } 107 } 108 } 109 110 func BenchmarkBulk_4xuint32(b *testing.B) { 111 enc := NewBulkEncoder(N * 4 * 4) 112 for k := 0; k < b.N; k++ { 113 enc.Reset() 114 for i := 0; i < N; i++ { 115 enc.WriteUint32(uint32(i)) 116 enc.WriteUint32(uint32(i)) 117 enc.WriteUint32(uint32(i)) 118 enc.WriteUint32(uint32(i)) 119 } 120 } 121 } 122 123 func BenchmarkBulk_mix(b *testing.B) { 124 enc := NewBulkEncoder(N + N*4 + 32) 125 for k := 0; k < b.N; k++ { 126 enc.Reset() 127 for i := 0; i < N; i++ { 128 enc.WriteByte(byte(i)) 129 enc.WriteUint32(uint32(i)) 130 } 131 } 132 } 133 134 func BenchmarkByte_byte(b *testing.B) { 135 enc := NewByteEncoder(N) 136 for k := 0; k < b.N; k++ { 137 enc.Reset() 138 for i := 0; i < N; i++ { 139 enc.WriteByte(byte(i)) 140 } 141 } 142 } 143 144 func BenchmarkByte_4xbyte(b *testing.B) { 145 enc := NewByteEncoder(4 * N) 146 for k := 0; k < b.N; k++ { 147 enc.Reset() 148 for i := 0; i < N; i++ { 149 enc.WriteByte(byte(i)) 150 enc.WriteByte(byte(i)) 151 enc.WriteByte(byte(i)) 152 enc.WriteByte(byte(i)) 153 } 154 } 155 } 156 157 func BenchmarkByte_uint32(b *testing.B) { 158 enc := NewByteEncoder(N * 4) 159 for k := 0; k < b.N; k++ { 160 enc.Reset() 161 for i := 0; i < N; i++ { 162 enc.WriteUint32(uint32(i)) 163 } 164 } 165 } 166 167 func BenchmarkByte_4xuint32(b *testing.B) { 168 enc := NewByteEncoder(N * 4 * 4) 169 for k := 0; k < b.N; k++ { 170 enc.Reset() 171 for i := 0; i < N; i++ { 172 enc.WriteUint32(uint32(i)) 173 enc.WriteUint32(uint32(i)) 174 enc.WriteUint32(uint32(i)) 175 enc.WriteUint32(uint32(i)) 176 } 177 } 178 } 179 180 func BenchmarkByte_mix(b *testing.B) { 181 enc := NewByteEncoder(N + N*4 + 32) 182 for k := 0; k < b.N; k++ { 183 enc.Reset() 184 for i := 0; i < N; i++ { 185 enc.WriteByte(byte(i)) 186 enc.WriteUint32(uint32(i)) 187 } 188 } 189 }