github.com/likebike/go--@v0.0.0-20190911215757-0bd925d16e96/go/src/runtime/mapspeed_test.go (about) 1 // Copyright 2013 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 package runtime_test 5 6 import ( 7 "fmt" 8 "strconv" 9 "strings" 10 "testing" 11 ) 12 13 const size = 10 14 15 func BenchmarkHashStringSpeed(b *testing.B) { 16 strings := make([]string, size) 17 for i := 0; i < size; i++ { 18 strings[i] = fmt.Sprintf("string#%d", i) 19 } 20 sum := 0 21 m := make(map[string]int, size) 22 for i := 0; i < size; i++ { 23 m[strings[i]] = 0 24 } 25 idx := 0 26 b.ResetTimer() 27 for i := 0; i < b.N; i++ { 28 sum += m[strings[idx]] 29 idx++ 30 if idx == size { 31 idx = 0 32 } 33 } 34 } 35 36 type chunk [17]byte 37 38 func BenchmarkHashBytesSpeed(b *testing.B) { 39 // a bunch of chunks, each with a different alignment mod 16 40 var chunks [size]chunk 41 // initialize each to a different value 42 for i := 0; i < size; i++ { 43 chunks[i][0] = byte(i) 44 } 45 // put into a map 46 m := make(map[chunk]int, size) 47 for i, c := range chunks { 48 m[c] = i 49 } 50 idx := 0 51 b.ResetTimer() 52 for i := 0; i < b.N; i++ { 53 if m[chunks[idx]] != idx { 54 b.Error("bad map entry for chunk") 55 } 56 idx++ 57 if idx == size { 58 idx = 0 59 } 60 } 61 } 62 63 func BenchmarkHashInt32Speed(b *testing.B) { 64 ints := make([]int32, size) 65 for i := 0; i < size; i++ { 66 ints[i] = int32(i) 67 } 68 sum := 0 69 m := make(map[int32]int, size) 70 for i := 0; i < size; i++ { 71 m[ints[i]] = 0 72 } 73 idx := 0 74 b.ResetTimer() 75 for i := 0; i < b.N; i++ { 76 sum += m[ints[idx]] 77 idx++ 78 if idx == size { 79 idx = 0 80 } 81 } 82 } 83 84 func BenchmarkHashInt64Speed(b *testing.B) { 85 ints := make([]int64, size) 86 for i := 0; i < size; i++ { 87 ints[i] = int64(i) 88 } 89 sum := 0 90 m := make(map[int64]int, size) 91 for i := 0; i < size; i++ { 92 m[ints[i]] = 0 93 } 94 idx := 0 95 b.ResetTimer() 96 for i := 0; i < b.N; i++ { 97 sum += m[ints[idx]] 98 idx++ 99 if idx == size { 100 idx = 0 101 } 102 } 103 } 104 func BenchmarkHashStringArraySpeed(b *testing.B) { 105 stringpairs := make([][2]string, size) 106 for i := 0; i < size; i++ { 107 for j := 0; j < 2; j++ { 108 stringpairs[i][j] = fmt.Sprintf("string#%d/%d", i, j) 109 } 110 } 111 sum := 0 112 m := make(map[[2]string]int, size) 113 for i := 0; i < size; i++ { 114 m[stringpairs[i]] = 0 115 } 116 idx := 0 117 b.ResetTimer() 118 for i := 0; i < b.N; i++ { 119 sum += m[stringpairs[idx]] 120 idx++ 121 if idx == size { 122 idx = 0 123 } 124 } 125 } 126 127 func BenchmarkMegMap(b *testing.B) { 128 m := make(map[string]bool) 129 for suffix := 'A'; suffix <= 'G'; suffix++ { 130 m[strings.Repeat("X", 1<<20-1)+fmt.Sprint(suffix)] = true 131 } 132 key := strings.Repeat("X", 1<<20-1) + "k" 133 b.ResetTimer() 134 for i := 0; i < b.N; i++ { 135 _, _ = m[key] 136 } 137 } 138 139 func BenchmarkMegOneMap(b *testing.B) { 140 m := make(map[string]bool) 141 m[strings.Repeat("X", 1<<20)] = true 142 key := strings.Repeat("Y", 1<<20) 143 b.ResetTimer() 144 for i := 0; i < b.N; i++ { 145 _, _ = m[key] 146 } 147 } 148 149 func BenchmarkMegEqMap(b *testing.B) { 150 m := make(map[string]bool) 151 key1 := strings.Repeat("X", 1<<20) 152 key2 := strings.Repeat("X", 1<<20) // equal but different instance 153 m[key1] = true 154 b.ResetTimer() 155 for i := 0; i < b.N; i++ { 156 _, _ = m[key2] 157 } 158 } 159 160 func BenchmarkMegEmptyMap(b *testing.B) { 161 m := make(map[string]bool) 162 key := strings.Repeat("X", 1<<20) 163 b.ResetTimer() 164 for i := 0; i < b.N; i++ { 165 _, _ = m[key] 166 } 167 } 168 169 func BenchmarkSmallStrMap(b *testing.B) { 170 m := make(map[string]bool) 171 for suffix := 'A'; suffix <= 'G'; suffix++ { 172 m[fmt.Sprint(suffix)] = true 173 } 174 key := "k" 175 b.ResetTimer() 176 for i := 0; i < b.N; i++ { 177 _, _ = m[key] 178 } 179 } 180 181 func BenchmarkMapStringKeysEight_16(b *testing.B) { benchmarkMapStringKeysEight(b, 16) } 182 func BenchmarkMapStringKeysEight_32(b *testing.B) { benchmarkMapStringKeysEight(b, 32) } 183 func BenchmarkMapStringKeysEight_64(b *testing.B) { benchmarkMapStringKeysEight(b, 64) } 184 func BenchmarkMapStringKeysEight_1M(b *testing.B) { benchmarkMapStringKeysEight(b, 1<<20) } 185 186 func benchmarkMapStringKeysEight(b *testing.B, keySize int) { 187 m := make(map[string]bool) 188 for i := 0; i < 8; i++ { 189 m[strings.Repeat("K", i+1)] = true 190 } 191 key := strings.Repeat("K", keySize) 192 b.ResetTimer() 193 for i := 0; i < b.N; i++ { 194 _ = m[key] 195 } 196 } 197 198 func BenchmarkIntMap(b *testing.B) { 199 m := make(map[int]bool) 200 for i := 0; i < 8; i++ { 201 m[i] = true 202 } 203 b.ResetTimer() 204 for i := 0; i < b.N; i++ { 205 _, _ = m[7] 206 } 207 } 208 209 // Accessing the same keys in a row. 210 func benchmarkRepeatedLookup(b *testing.B, lookupKeySize int) { 211 m := make(map[string]bool) 212 // At least bigger than a single bucket: 213 for i := 0; i < 64; i++ { 214 m[fmt.Sprintf("some key %d", i)] = true 215 } 216 base := strings.Repeat("x", lookupKeySize-1) 217 key1 := base + "1" 218 key2 := base + "2" 219 b.ResetTimer() 220 for i := 0; i < b.N/4; i++ { 221 _ = m[key1] 222 _ = m[key1] 223 _ = m[key2] 224 _ = m[key2] 225 } 226 } 227 228 func BenchmarkRepeatedLookupStrMapKey32(b *testing.B) { benchmarkRepeatedLookup(b, 32) } 229 func BenchmarkRepeatedLookupStrMapKey1M(b *testing.B) { benchmarkRepeatedLookup(b, 1<<20) } 230 231 func BenchmarkNewEmptyMap(b *testing.B) { 232 b.ReportAllocs() 233 for i := 0; i < b.N; i++ { 234 _ = make(map[int]int) 235 } 236 } 237 238 func BenchmarkNewSmallMap(b *testing.B) { 239 b.ReportAllocs() 240 for i := 0; i < b.N; i++ { 241 m := make(map[int]int) 242 m[0] = 0 243 m[1] = 1 244 } 245 } 246 247 func BenchmarkMapIter(b *testing.B) { 248 m := make(map[int]bool) 249 for i := 0; i < 8; i++ { 250 m[i] = true 251 } 252 b.ResetTimer() 253 for i := 0; i < b.N; i++ { 254 for range m { 255 } 256 } 257 } 258 259 func BenchmarkMapIterEmpty(b *testing.B) { 260 m := make(map[int]bool) 261 b.ResetTimer() 262 for i := 0; i < b.N; i++ { 263 for range m { 264 } 265 } 266 } 267 268 func BenchmarkSameLengthMap(b *testing.B) { 269 // long strings, same length, differ in first few 270 // and last few bytes. 271 m := make(map[string]bool) 272 s1 := "foo" + strings.Repeat("-", 100) + "bar" 273 s2 := "goo" + strings.Repeat("-", 100) + "ber" 274 m[s1] = true 275 m[s2] = true 276 b.ResetTimer() 277 for i := 0; i < b.N; i++ { 278 _ = m[s1] 279 } 280 } 281 282 type BigKey [3]int64 283 284 func BenchmarkBigKeyMap(b *testing.B) { 285 m := make(map[BigKey]bool) 286 k := BigKey{3, 4, 5} 287 m[k] = true 288 for i := 0; i < b.N; i++ { 289 _ = m[k] 290 } 291 } 292 293 type BigVal [3]int64 294 295 func BenchmarkBigValMap(b *testing.B) { 296 m := make(map[BigKey]BigVal) 297 k := BigKey{3, 4, 5} 298 m[k] = BigVal{6, 7, 8} 299 for i := 0; i < b.N; i++ { 300 _ = m[k] 301 } 302 } 303 304 func BenchmarkSmallKeyMap(b *testing.B) { 305 m := make(map[int16]bool) 306 m[5] = true 307 for i := 0; i < b.N; i++ { 308 _ = m[5] 309 } 310 } 311 312 func BenchmarkMapPopulate(b *testing.B) { 313 for size := 1; size < 1000000; size *= 10 { 314 b.Run(strconv.Itoa(size), func(b *testing.B) { 315 b.ReportAllocs() 316 for i := 0; i < b.N; i++ { 317 m := make(map[int]bool) 318 for j := 0; j < size; j++ { 319 m[j] = true 320 } 321 } 322 }) 323 } 324 } 325 326 type ComplexAlgKey struct { 327 a, b, c int64 328 _ int 329 d int32 330 _ int 331 e string 332 _ int 333 f, g, h int64 334 } 335 336 func BenchmarkComplexAlgMap(b *testing.B) { 337 m := make(map[ComplexAlgKey]bool) 338 var k ComplexAlgKey 339 m[k] = true 340 for i := 0; i < b.N; i++ { 341 _ = m[k] 342 } 343 }