I decided to do a simple benchmark between two solutions I often use in my code.
The situation is: you have an input, not necessarily known at compile time, and you'l like to assign a value that depends on it. I made this benchmark using strings and ints as inputs.
The solutions I see for this are the following:
- Use a switch case
- create a map that returns the correspoding value
So which is the fastest?
string input
The code is really simple. First I defined the functions.
package switchvsmap var selector = map[string]string{ "1": "one", "2": "two", "3": "three", "4": "four", "5": "five", "6": "six", "7": "seven", "8": "eight", "9": "nine", "0": "zero", } func SwitchCase(in string) string { var res string switch in { case "1": res = "one" case "2": res = "two" case "3": res = "three" case "4": res = "four" case "5": res = "five" case "6": res = "six" case "7": res = "seven" case "8": res = "eight" case "9": res = "nine" case "0": res = "zero" } return res } func MapCase(in string) string { res := selector[in] return res }
And created the test file.
package switchvsmap import ( "math/rand" "testing" ) const chars = "0123456789" var ( cases = make([]string, 10e7) ) func init() { for i := 0; i < 10e7; i++ { cases[i] = string(chars[rand.Intn(len(chars))]) } } func BenchmarkSwitchCase(b *testing.B) { for n := 0; n < b.N; n++ { SwitchCase(cases[n]) } } func BenchmarkMapCase(b *testing.B) { for n := 0; n < b.N; n++ { MapCase(cases[n]) } }
You can see I initialized a very big array, and filled it with random chars. That is to make tests unpredictable.
int input
I remade the tests using ints as input
var selectorInt = map[int]string{ 1: "one", 2: "two", 3: "three", 4: "four", 5: "five", 6: "six", 7: "seven", 8: "eight", 9: "nine", 0: "zero", } func SwitchCaseInt(in int) string { var res string switch in { case 1: res = "one" case 2: res = "two" case 3: res = "three" case 4: res = "four" case 5: res = "five" case 6: res = "six" case 7: res = "seven" case 8: res = "eight" case 9: res = "nine" case 0: res = "zero" } return res } func MapCaseInt(in int) string { res := selectorInt[in] return res }
I'm showing only the changes.
var ( casesInt = make([]int, 10e8) ) func init() { for i := 0; i < 10e8; i++ { casesInt[i] = rand.Intn(len(chars)) } } func BenchmarkSwitchCaseInt(b *testing.B) { for n := 0; n < b.N; n++ { SwitchCaseInt(casesInt[n]) } } func BenchmarkMapCaseInt(b *testing.B) { for n := 0; n < b.N; n++ { MapCaseInt(casesInt[n]) } }
And combined them in the same file.
Results
I used the command: go test -bench=. -benchtime 10000000x to run the benchmark, I need to define benchtime to not overflow my test data.
goos: linux goarch: amd64 pkg: mapvsswitch cpu: Intel(R) Core(TM) i5-4570T CPU @ 2.90GHz BenchmarkSwitchCase-4 10000000 20.02 ns/op BenchmarkMapCase-4 10000000 26.99 ns/op BenchmarkSwitchCaseInt-4 10000000 9.188 ns/op BenchmarkMapCaseInt-4 10000000 20.55 ns/op PASS ok mapvsswitch 13.841
So far the switch statement is faster, I was expecting that, but let's see how it behaves when we increase the input cases.