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.
17 func BenchmarkHashStringSpeed(b *testing.B) {
18 strings := make([]string, size)
19 for i := 0; i < size; i++ {
20 strings[i] = fmt.Sprintf("string#%d", i)
23 m := make(map[string]int, size)
24 for i := 0; i < size; i++ {
29 for i := 0; i < b.N; i++ {
30 sum += m[strings[idx]]
40 func BenchmarkHashBytesSpeed(b *testing.B) {
41 // a bunch of chunks, each with a different alignment mod 16
42 var chunks [size]chunk
43 // initialize each to a different value
44 for i := 0; i < size; i++ {
45 chunks[i][0] = byte(i)
48 m := make(map[chunk]int, size)
49 for i, c := range chunks {
54 for i := 0; i < b.N; i++ {
55 if m[chunks[idx]] != idx {
56 b.Error("bad map entry for chunk")
65 func BenchmarkHashInt32Speed(b *testing.B) {
66 ints := make([]int32, size)
67 for i := 0; i < size; i++ {
71 m := make(map[int32]int, size)
72 for i := 0; i < size; i++ {
77 for i := 0; i < b.N; i++ {
86 func BenchmarkHashInt64Speed(b *testing.B) {
87 ints := make([]int64, size)
88 for i := 0; i < size; i++ {
92 m := make(map[int64]int, size)
93 for i := 0; i < size; i++ {
98 for i := 0; i < b.N; i++ {
106 func BenchmarkHashStringArraySpeed(b *testing.B) {
107 stringpairs := make([][2]string, size)
108 for i := 0; i < size; i++ {
109 for j := 0; j < 2; j++ {
110 stringpairs[i][j] = fmt.Sprintf("string#%d/%d", i, j)
114 m := make(map[[2]string]int, size)
115 for i := 0; i < size; i++ {
116 m[stringpairs[i]] = 0
120 for i := 0; i < b.N; i++ {
121 sum += m[stringpairs[idx]]
129 func BenchmarkMegMap(b *testing.B) {
130 m := make(map[string]bool)
131 for suffix := 'A'; suffix <= 'G'; suffix++ {
132 m[strings.Repeat("X", 1<<20-1)+fmt.Sprint(suffix)] = true
134 key := strings.Repeat("X", 1<<20-1) + "k"
136 for i := 0; i < b.N; i++ {
141 func BenchmarkMegOneMap(b *testing.B) {
142 m := make(map[string]bool)
143 m[strings.Repeat("X", 1<<20)] = true
144 key := strings.Repeat("Y", 1<<20)
146 for i := 0; i < b.N; i++ {
151 func BenchmarkMegEqMap(b *testing.B) {
152 m := make(map[string]bool)
153 key1 := strings.Repeat("X", 1<<20)
154 key2 := strings.Repeat("X", 1<<20) // equal but different instance
157 for i := 0; i < b.N; i++ {
162 func BenchmarkMegEmptyMap(b *testing.B) {
163 m := make(map[string]bool)
164 key := strings.Repeat("X", 1<<20)
166 for i := 0; i < b.N; i++ {
171 func BenchmarkMegEmptyMapWithInterfaceKey(b *testing.B) {
172 m := make(map[any]bool)
173 key := strings.Repeat("X", 1<<20)
175 for i := 0; i < b.N; i++ {
180 func BenchmarkSmallStrMap(b *testing.B) {
181 m := make(map[string]bool)
182 for suffix := 'A'; suffix <= 'G'; suffix++ {
183 m[fmt.Sprint(suffix)] = true
187 for i := 0; i < b.N; i++ {
192 func BenchmarkMapStringKeysEight_16(b *testing.B) { benchmarkMapStringKeysEight(b, 16) }
193 func BenchmarkMapStringKeysEight_32(b *testing.B) { benchmarkMapStringKeysEight(b, 32) }
194 func BenchmarkMapStringKeysEight_64(b *testing.B) { benchmarkMapStringKeysEight(b, 64) }
195 func BenchmarkMapStringKeysEight_1M(b *testing.B) { benchmarkMapStringKeysEight(b, 1<<20) }
197 func benchmarkMapStringKeysEight(b *testing.B, keySize int) {
198 m := make(map[string]bool)
199 for i := 0; i < 8; i++ {
200 m[strings.Repeat("K", i+1)] = true
202 key := strings.Repeat("K", keySize)
204 for i := 0; i < b.N; i++ {
209 func BenchmarkIntMap(b *testing.B) {
210 m := make(map[int]bool)
211 for i := 0; i < 8; i++ {
215 for i := 0; i < b.N; i++ {
220 func BenchmarkMapFirst(b *testing.B) {
221 for n := 1; n <= 16; n++ {
222 b.Run(fmt.Sprintf("%d", n), func(b *testing.B) {
223 m := make(map[int]bool)
224 for i := 0; i < n; i++ {
228 for i := 0; i < b.N; i++ {
234 func BenchmarkMapMid(b *testing.B) {
235 for n := 1; n <= 16; n++ {
236 b.Run(fmt.Sprintf("%d", n), func(b *testing.B) {
237 m := make(map[int]bool)
238 for i := 0; i < n; i++ {
242 for i := 0; i < b.N; i++ {
248 func BenchmarkMapLast(b *testing.B) {
249 for n := 1; n <= 16; n++ {
250 b.Run(fmt.Sprintf("%d", n), func(b *testing.B) {
251 m := make(map[int]bool)
252 for i := 0; i < n; i++ {
256 for i := 0; i < b.N; i++ {
263 func BenchmarkMapCycle(b *testing.B) {
264 // Arrange map entries to be a permutation, so that
265 // we hit all entries, and one lookup is data dependent
266 // on the previous lookup.
268 p := rand.New(rand.NewSource(1)).Perm(N)
270 for i := 0; i < N; i++ {
275 for i := 0; i < b.N; i++ {
281 // Accessing the same keys in a row.
282 func benchmarkRepeatedLookup(b *testing.B, lookupKeySize int) {
283 m := make(map[string]bool)
284 // At least bigger than a single bucket:
285 for i := 0; i < 64; i++ {
286 m[fmt.Sprintf("some key %d", i)] = true
288 base := strings.Repeat("x", lookupKeySize-1)
292 for i := 0; i < b.N/4; i++ {
300 func BenchmarkRepeatedLookupStrMapKey32(b *testing.B) { benchmarkRepeatedLookup(b, 32) }
301 func BenchmarkRepeatedLookupStrMapKey1M(b *testing.B) { benchmarkRepeatedLookup(b, 1<<20) }
303 func BenchmarkMakeMap(b *testing.B) {
304 b.Run("[Byte]Byte", func(b *testing.B) {
306 for i := 0; i < b.N; i++ {
307 m = make(map[byte]byte, 10)
311 b.Run("[Int]Int", func(b *testing.B) {
313 for i := 0; i < b.N; i++ {
314 m = make(map[int]int, 10)
320 func BenchmarkNewEmptyMap(b *testing.B) {
322 for i := 0; i < b.N; i++ {
323 _ = make(map[int]int)
327 func BenchmarkNewSmallMap(b *testing.B) {
329 for i := 0; i < b.N; i++ {
330 m := make(map[int]int)
336 func BenchmarkMapIter(b *testing.B) {
337 m := make(map[int]bool)
338 for i := 0; i < 8; i++ {
342 for i := 0; i < b.N; i++ {
348 func BenchmarkMapIterEmpty(b *testing.B) {
349 m := make(map[int]bool)
351 for i := 0; i < b.N; i++ {
357 func BenchmarkSameLengthMap(b *testing.B) {
358 // long strings, same length, differ in first few
359 // and last few bytes.
360 m := make(map[string]bool)
361 s1 := "foo" + strings.Repeat("-", 100) + "bar"
362 s2 := "goo" + strings.Repeat("-", 100) + "ber"
366 for i := 0; i < b.N; i++ {
373 func BenchmarkBigKeyMap(b *testing.B) {
374 m := make(map[BigKey]bool)
377 for i := 0; i < b.N; i++ {
384 func BenchmarkBigValMap(b *testing.B) {
385 m := make(map[BigKey]BigVal)
387 m[k] = BigVal{6, 7, 8}
388 for i := 0; i < b.N; i++ {
393 func BenchmarkSmallKeyMap(b *testing.B) {
394 m := make(map[int16]bool)
396 for i := 0; i < b.N; i++ {
401 func BenchmarkMapPopulate(b *testing.B) {
402 for size := 1; size < 1000000; size *= 10 {
403 b.Run(strconv.Itoa(size), func(b *testing.B) {
405 for i := 0; i < b.N; i++ {
406 m := make(map[int]bool)
407 for j := 0; j < size; j++ {
415 type ComplexAlgKey struct {
425 func BenchmarkComplexAlgMap(b *testing.B) {
426 m := make(map[ComplexAlgKey]bool)
429 for i := 0; i < b.N; i++ {
434 func BenchmarkGoMapClear(b *testing.B) {
435 b.Run("Reflexive", func(b *testing.B) {
436 for size := 1; size < 100000; size *= 10 {
437 b.Run(strconv.Itoa(size), func(b *testing.B) {
438 m := make(map[int]int, size)
439 for i := 0; i < b.N; i++ {
440 m[0] = size // Add one element so len(m) != 0 avoiding fast paths.
446 b.Run("NonReflexive", func(b *testing.B) {
447 for size := 1; size < 100000; size *= 10 {
448 b.Run(strconv.Itoa(size), func(b *testing.B) {
449 m := make(map[float64]int, size)
450 for i := 0; i < b.N; i++ {
451 m[1.0] = size // Add one element so len(m) != 0 avoiding fast paths.
459 func BenchmarkMapStringConversion(b *testing.B) {
460 for _, length := range []int{32, 64} {
461 b.Run(strconv.Itoa(length), func(b *testing.B) {
462 bytes := make([]byte, length)
463 b.Run("simple", func(b *testing.B) {
465 m := make(map[string]int)
467 for i := 0; i < b.N; i++ {
471 b.Run("struct", func(b *testing.B) {
473 type stringstruct struct{ s string }
474 m := make(map[stringstruct]int)
475 m[stringstruct{string(bytes)}] = 0
476 for i := 0; i < b.N; i++ {
477 _ = m[stringstruct{string(bytes)}]
480 b.Run("array", func(b *testing.B) {
482 type stringarray [1]string
483 m := make(map[stringarray]int)
484 m[stringarray{string(bytes)}] = 0
485 for i := 0; i < b.N; i++ {
486 _ = m[stringarray{string(bytes)}]
495 func BenchmarkMapInterfaceString(b *testing.B) {
498 for i := 0; i < 100; i++ {
499 m[fmt.Sprintf("%d", i)] = true
504 for i := 0; i < b.N; i++ {
508 func BenchmarkMapInterfacePtr(b *testing.B) {
511 for i := 0; i < 100; i++ {
518 for i := 0; i < b.N; i++ {
525 hintGreaterThan8 = 32
528 func BenchmarkNewEmptyMapHintLessThan8(b *testing.B) {
530 for i := 0; i < b.N; i++ {
531 _ = make(map[int]int, hintLessThan8)
535 func BenchmarkNewEmptyMapHintGreaterThan8(b *testing.B) {
537 for i := 0; i < b.N; i++ {
538 _ = make(map[int]int, hintGreaterThan8)