Last active
May 18, 2022 08:50
-
-
Save SchumacherFM/876741809c1b99d4d81b to your computer and use it in GitHub Desktop.
GoLang Benchmark: Map, StringSlice, Array, StructSlice
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
// run with: $ go test --bench=. -test.benchmem . | |
// @see https://twitter.com/karlseguin/status/524452778093977600 | |
import ( | |
"math/rand" | |
"strconv" | |
"testing" | |
) | |
const ( | |
SIZE = 10 | |
LOOKUPS = 200 | |
) | |
// Excluded means that the setup of the lookup variable is created once outside the bench loop | |
// Included means that the setup of the lookup variable is created new each loop | |
func BenchmarkStringMapExcluded(b *testing.B) { | |
lookup := make(map[string]string, SIZE) | |
for i := 0; i < SIZE; i += 1 { | |
k := strconv.Itoa(i) // FYI: converts int to string | |
lookup[k] = "value" | |
} | |
rand.Seed(int64(b.N)) | |
b.ResetTimer() | |
for n := 0; n < b.N; n++ { | |
for i := 0; i < LOOKUPS; i++ { | |
needle := strconv.Itoa(rand.Intn(SIZE)) | |
if _, ok := lookup[needle]; ok { | |
} | |
} | |
} | |
} | |
func BenchmarkStringMapIncluded(b *testing.B) { | |
rand.Seed(int64(b.N)) | |
b.ResetTimer() | |
for n := 0; n < b.N; n++ { | |
lookup := make(map[string]string, SIZE) | |
for i := 0; i < SIZE; i += 1 { | |
k := strconv.Itoa(i) // FYI: converts int to string | |
lookup[k] = "value" | |
} | |
for i := 0; i < LOOKUPS; i++ { | |
needle := strconv.Itoa(rand.Intn(SIZE)) | |
if _, ok := lookup[needle]; ok { | |
} | |
} | |
} | |
} | |
func BenchmarkStringSliceExcluded(b *testing.B) { | |
lookup := make([]string, SIZE*2) | |
for i := 0; i < SIZE; i += 2 { | |
lookup[i] = strconv.Itoa(i / 2) | |
lookup[i+1] = "value" | |
} | |
rand.Seed(int64(b.N)) | |
b.ResetTimer() | |
for n := 0; n < b.N; n++ { | |
for i := 0; i < LOOKUPS; i++ { | |
needle := strconv.Itoa(rand.Intn(SIZE)) | |
for j := 0; j < SIZE; j += 2 { | |
if lookup[j] == needle { | |
} | |
} | |
} | |
} | |
} | |
func BenchmarkStringSliceIncluded(b *testing.B) { | |
rand.Seed(int64(b.N)) | |
b.ResetTimer() | |
for n := 0; n < b.N; n++ { | |
lookup := make([]string, SIZE*2) | |
for i := 0; i < SIZE; i += 2 { | |
lookup[i] = strconv.Itoa(i / 2) | |
lookup[i+1] = "value" | |
} | |
for i := 0; i < LOOKUPS; i++ { | |
needle := strconv.Itoa(rand.Intn(SIZE)) | |
for j := 0; j < SIZE; j += 2 { | |
if lookup[j] == needle { | |
} | |
} | |
} | |
} | |
} | |
func BenchmarkStringArraysExcluded(b *testing.B) { | |
lookup := [SIZE * 2]string{} | |
for i := 0; i < SIZE; i += 2 { | |
lookup[i] = strconv.Itoa(i / 2) | |
lookup[i+1] = "value" | |
} | |
rand.Seed(int64(b.N)) | |
b.ResetTimer() | |
for i := 0; i < b.N; i++ { | |
for i := 0; i < LOOKUPS; i++ { | |
needle := strconv.Itoa(rand.Intn(SIZE)) | |
for j := 0; j < SIZE; j += 2 { | |
if lookup[j] == needle { | |
} | |
} | |
} | |
} | |
} | |
func BenchmarkStringArraysIncluded(b *testing.B) { | |
rand.Seed(int64(b.N)) | |
b.ResetTimer() | |
for i := 0; i < b.N; i++ { | |
lookup := [SIZE * 2]string{} | |
for i := 0; i < SIZE; i += 2 { | |
lookup[i] = strconv.Itoa(i / 2) | |
lookup[i+1] = "value" | |
} | |
for i := 0; i < LOOKUPS; i++ { | |
needle := strconv.Itoa(rand.Intn(SIZE)) | |
for j := 0; j < SIZE; j += 2 { | |
if lookup[j] == needle { | |
} | |
} | |
} | |
} | |
} | |
func BenchmarkStructSliceExcluded(b *testing.B) { | |
lookup := make([]struct{ key, value string }, SIZE) | |
for i := 0; i < SIZE; i++ { | |
lookup[i].key = strconv.Itoa(i) | |
lookup[i].value = "value" | |
} | |
rand.Seed(int64(b.N)) | |
b.ResetTimer() | |
for n := 0; n < b.N; n++ { | |
for i := 0; i < LOOKUPS; i++ { | |
needle := strconv.Itoa(rand.Intn(SIZE)) | |
for j := 0; j < SIZE; j++ { | |
if lookup[j].key == needle { | |
} | |
} | |
} | |
} | |
} | |
func BenchmarkStructSliceIncluded(b *testing.B) { | |
rand.Seed(int64(b.N)) | |
b.ResetTimer() | |
for n := 0; n < b.N; n++ { | |
lookup := make([]struct{ key, value string }, SIZE) | |
for i := 0; i < SIZE; i++ { | |
lookup[i].key = strconv.Itoa(i) | |
lookup[i].value = "value" | |
} | |
for i := 0; i < LOOKUPS; i++ { | |
needle := strconv.Itoa(rand.Intn(SIZE)) | |
for j := 0; j < SIZE; j++ { | |
if lookup[j].key == needle { | |
} | |
} | |
} | |
} | |
} |
$ go test --bench=. -test.benchmem .
PASS
BenchmarkStringMapExcluded 100000 28148 ns/op 200 B/op 12 allocs/op
BenchmarkStringMapIncluded 100000 29652 ns/op 846 B/op 15 allocs/op
BenchmarkStringSliceExcluded 100000 28277 ns/op 200 B/op 12 allocs/op
BenchmarkStringSliceIncluded 100000 28587 ns/op 205 B/op 12 allocs/op
BenchmarkStringArraysExcluded 100000 28299 ns/op 200 B/op 12 allocs/op
BenchmarkStringArraysIncluded 100000 28262 ns/op 205 B/op 12 allocs/op
BenchmarkStructSliceExcluded 50000 39858 ns/op 200 B/op 12 allocs/op
BenchmarkStructSliceIncluded 50000 40250 ns/op 210 B/op 13 allocs/op
ok github.com/SchumacherFM/gotest 23.697s
@SchumacherFM which Go version did you use?
For slice, why not break when match?
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
MacBook Air Mid 2012; 1.8 GHz Intel Core i5