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