github.com/coyove/nj@v0.0.0-20221110084952-c7f8db1065c3/tests/gobench/bytes_test.go (about) 1 package bench 2 3 import ( 4 "bytes" 5 "math/rand" 6 "sort" 7 "strconv" 8 "testing" 9 "time" 10 "unsafe" 11 ) 12 13 func concatBytes(a, b []byte) []byte { 14 c := make([]byte, len(a)+len(b)) 15 copy(c, a) 16 copy(c[len(a):], b) 17 return c 18 } 19 20 func bytesString(a []byte) string { 21 return *(*string)(unsafe.Pointer(&a)) 22 } 23 24 func bytesString2(a []byte) string { 25 return string(a) 26 } 27 28 func TestBytesInterface(t *testing.T) { 29 a := []byte("zzz") 30 m := map[interface{}]int{} 31 m[bytesString(a)] = 99 32 a[1] = 'a' 33 t.Log(m) 34 } 35 36 var dummies = []string{strconv.Itoa(rand.Int()), strconv.Itoa(rand.Int()), strconv.Itoa(rand.Int()), strconv.Itoa(rand.Int())} 37 38 func BenchmarkBytes(b *testing.B) { 39 v1, v2 := make([]byte, 18), make([]byte, 18) 40 rand.Read(v1) 41 rand.Read(v2) 42 43 for i := 0; i < b.N; i++ { 44 v3 := concatBytes(v1, v2) 45 if bytes.Equal(v3, nil) { 46 b.Fatal(1) 47 } 48 } 49 } 50 51 func BenchmarkString(b *testing.B) { 52 v1, v2 := dummies[rand.Intn(len(dummies))], dummies[rand.Intn(len(dummies))] 53 for i := 0; i < b.N; i++ { 54 v3 := v1 + v2 55 if v3 == "" { 56 b.Fatal(1) 57 } 58 } 59 } 60 61 func BenchmarkBytesReplace(b *testing.B) { 62 v1 := dummies[rand.Intn(len(dummies))] 63 64 for i := 0; i < b.N; i++ { 65 x := []byte(v1) 66 x[1] = 'z' 67 v3 := string(x) 68 if v3 == "" { 69 b.Fatal(1) 70 } 71 } 72 } 73 74 func BenchmarkStringReplace(b *testing.B) { 75 v1 := dummies[rand.Intn(len(dummies))] 76 for i := 0; i < b.N; i++ { 77 v3 := v1[:1] + "z" + v1[2:] 78 if v3 == "" { 79 b.Fatal(1) 80 } 81 } 82 } 83 84 type IntMap []uint64 85 86 func (m IntMap) Get(k uint64) (v uint64, ok bool) { 87 offset := len(m) / 2 88 j := offset 89 90 if j > 0 && m[0] == k { 91 return m[offset], true 92 } 93 94 if j > 1 && m[1] == k { 95 return m[1+offset], true 96 } 97 // return 0, false 98 99 for i := 2; i < j; { 100 h := int(uint(i+j) >> 1) // avoid overflow when computing h 101 102 k2 := &m[h] 103 if *k2 == k { 104 return *(*uint64)(unsafe.Pointer(uintptr(unsafe.Pointer(k2)) + uintptr(offset)*unsafe.Sizeof(uint64(0)))), true 105 // return m.values[h+offset], true 106 } 107 108 if *k2 < k { 109 i = h + 1 110 } else { 111 j = h 112 } 113 } 114 115 return 0, false 116 } 117 118 func (m *IntMap) Add(k uint64, v uint64) { 119 offset := len(*m) / 2 120 i, j := 0, offset 121 122 for i < j { 123 h := int(uint(i+j) >> 1) // avoid overflow when computing h 124 // i ≤ h < j 125 if (*m)[h] == k { 126 (*m)[h+offset] = v 127 return 128 } 129 130 if (*m)[h] < k { 131 i = h + 1 // preserves f(i-1) == false 132 } else { 133 j = h // preserves f(j) == true 134 } 135 } 136 137 *m = append(*m, 0, 0) 138 copy((*m)[i+offset+2:], (*m)[i+offset:]) 139 (*m)[i+offset+1] = v 140 copy((*m)[i+1:], (*m)[i:i+offset]) 141 (*m)[i] = k 142 } 143 144 type kvSwapper []uint64 145 146 func (s kvSwapper) Len() int { 147 return len(s) / 2 148 } 149 150 func (s kvSwapper) Less(i, j int) bool { 151 return (s)[i] < (s)[j] 152 } 153 154 func (s kvSwapper) Swap(i, j int) { 155 (s)[i], (s)[j] = (s)[j], (s)[i] 156 i, j = i+len(s)/2, j+len(s)/2 157 (s)[i], (s)[j] = (s)[j], (s)[i] 158 } 159 160 func (m *IntMap) BatchSet(kv []uint64) { 161 *m = kv 162 sort.Sort(kvSwapper(*m)) 163 } 164 165 var N = 16 166 167 func TestMapBatch(t *testing.T) { 168 rand.Seed(time.Now().Unix()) 169 170 m := IntMap{} 171 m2 := map[uint64]bool{} 172 173 args := make([]uint64, N*2) 174 for i := 0; i < N; i++ { 175 x := uint64(rand.Int()) 176 m2[x] = true 177 args[i] = x 178 args[i+N] = x 179 } 180 181 m.BatchSet(args) 182 183 for k := range m2 { 184 if v, _ := m.Get(k); v != k { 185 t.Fatal(m) 186 } 187 } 188 } 189 190 func TestMapAdd(t *testing.T) { 191 m := IntMap{} 192 m2 := map[uint64]bool{} 193 for i := 0; i < N; i++ { 194 x := uint64(rand.Int()) 195 m.Add(x, x) 196 m2[x] = true 197 } 198 199 for k := range m2 { 200 if v, _ := m.Get(k); v != k { 201 t.Fatal(m) 202 } 203 } 204 } 205 206 func BenchmarkNativeMapIndex(b *testing.B) { 207 b.StopTimer() 208 m := map[uint64]uint64{} 209 for i := 0; i < N; i++ { 210 x := uint64(rand.Int()) 211 m[x] = x 212 } 213 b.StartTimer() 214 215 for i := 0; i < b.N; i++ { 216 if m[uint64(i)] == 999 { 217 b.Fatal(m) 218 } 219 } 220 } 221 222 func BenchmarkMapIndex(b *testing.B) { 223 b.StopTimer() 224 m := IntMap{} 225 for i := 0; i < N; i++ { 226 x := uint64(rand.Int()) 227 m.Add(x, x) 228 } 229 b.StartTimer() 230 231 for i := 0; i < b.N; i++ { 232 if v, _ := m.Get(uint64(i)); v == 999 { 233 b.Fatal(m) 234 } 235 } 236 237 //b.Log(m) 238 } 239 240 func BenchmarkNativeMapAdd(b *testing.B) { 241 for i := 0; i < b.N; i++ { 242 m := map[uint64]uint64{} 243 for i := 0; i < N; i++ { 244 x := uint64(rand.Int()) 245 m[x] = x 246 } 247 } 248 } 249 250 func BenchmarkMapAdd(b *testing.B) { 251 for i := 0; i < b.N; i++ { 252 m := IntMap{} 253 for i := 0; i < N; i++ { 254 x := uint64(rand.Int()) 255 m.Add(x, x) 256 } 257 } 258 } 259 260 func BenchmarkMapBatch(b *testing.B) { 261 for i := 0; i < b.N; i++ { 262 m := IntMap{} 263 kv := make([]uint64, N*2) 264 for i := 0; i < N; i++ { 265 x := uint64(rand.Int()) 266 kv[i] = x 267 kv[i+N] = x 268 } 269 m.BatchSet(kv) 270 } 271 } 272 273 func BenchmarkAdd(b *testing.B) { 274 x, y, z := byte(rand.Int()), byte(rand.Int()), byte(rand.Int()) 275 for i := 0; i < b.N; i++ { 276 for k := 0; k < 100; k++ { 277 if a := y + x; a == z { 278 b.Fatal(x, y) 279 } 280 } 281 } 282 } 283 284 func BenchmarkXorAdd(b *testing.B) { 285 x, y, z := byte(rand.Int()), byte(rand.Int()), byte(rand.Int()) 286 for i := 0; i < b.N; i++ { 287 for k := 0; k < 100; k++ { 288 if a := x<<4 | y; a == z { 289 b.Fatal(x, y) 290 } 291 } 292 } 293 }