mapspeed_test.go 5.9 KB

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