Last active
December 15, 2022 20:18
-
-
Save mwittig/75aa4e1591f5fab163875cb8923065c2 to your computer and use it in GitHub Desktop.
Benchmark TypeSwitch vs. Reflect vs fmt.Sprintf performance compare two value for type equality
This file contains 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 reflectperf | |
import ( | |
"fmt" | |
"reflect" | |
"testing" | |
) | |
// Note, switchTest produces a different result for nil, nil then reflectTest and sprintfTypeTest. | |
// However, this case is not part of the tests performed. | |
// Results: | |
// goos: darwin | |
// goarch: arm64 | |
// Benchmark_TypeSwitch | |
// Benchmark_TypeSwitch-10 61980268 19.23 ns/op | |
// Benchmark_Reflect | |
// Benchmark_Reflect-10 35567805 33.60 ns/op | |
// Benchmark_Sprintf | |
// Benchmark_Sprintf-10 35686405 33.63 ns/op | |
// PASS | |
type InstallCommand struct{} | |
type ActivateCommand struct{} | |
type PersonalizeCommand struct{} | |
type ServiceCommand interface { | |
isServiceCommandType() | |
} | |
func (sc *InstallCommand) isServiceCommandType() {} | |
func (sc *ActivateCommand) isServiceCommandType() {} | |
func (sc *PersonalizeCommand) isServiceCommandType() {} | |
func switchTest(serviceCommands []ServiceCommand, serviceCommand ServiceCommand) int { | |
for _, cmd := range serviceCommands { | |
switch cmd.(type) { | |
case *InstallCommand: | |
if _, ok := serviceCommand.(*InstallCommand); ok { | |
return 1 | |
} | |
case *ActivateCommand: | |
if _, ok := serviceCommand.(*ActivateCommand); ok { | |
return 1 | |
} | |
case *PersonalizeCommand: | |
if _, ok := serviceCommand.(*PersonalizeCommand); ok { | |
return 1 | |
} | |
default: | |
return 0 // serviceCommands contains unhandled service command or nil | |
} | |
} | |
return 0 // serviceCommands is empty | |
} | |
func reflectTest(serviceCommands []ServiceCommand, serviceCommand ServiceCommand) int { | |
for _, cmd := range serviceCommands { | |
if reflect.TypeOf(cmd) == reflect.TypeOf(serviceCommand) { | |
return 1 | |
} | |
} | |
return 0 // serviceCommands is empty | |
} | |
func sprintfTypeTest(serviceCommands []ServiceCommand, serviceCommand ServiceCommand) int { | |
for _, cmd := range serviceCommands { | |
if fmt.Sprintf("%T", cmd) == fmt.Sprintf("%T", serviceCommand) { | |
return 1 | |
} | |
} | |
return 0 // serviceCommands is empty | |
} | |
var ( | |
serviceCommands = []ServiceCommand{&InstallCommand{}, &ActivateCommand{}, &PersonalizeCommand{}} | |
) | |
func makeArgList() []ServiceCommand { | |
return []ServiceCommand{&InstallCommand{}, &ActivateCommand{}, &PersonalizeCommand{}, nil} | |
} | |
func Benchmark_TypeSwitch(b *testing.B) { | |
sum := 0 | |
list := makeArgList() | |
b.ResetTimer() | |
for i := 0; i < b.N; i++ { | |
for _, val := range list { | |
sum = sum + switchTest(serviceCommands, val) | |
} | |
} | |
} | |
func Benchmark_Reflect(b *testing.B) { | |
sum := 0 | |
list := makeArgList() | |
b.ResetTimer() | |
for i := 0; i < b.N; i++ { | |
for _, val := range list { | |
sum = sum + reflectTest(serviceCommands, val) | |
} | |
} | |
} | |
func Benchmark_Sprintf(b *testing.B) { | |
sum := 0 | |
list := makeArgList() | |
b.ResetTimer() | |
for i := 0; i < b.N; i++ { | |
for _, val := range list { | |
sum = sum + reflectTest(serviceCommands, val) | |
} | |
} | |
} | |
func Test_Benchmark(t *testing.T) { | |
list := makeArgList() | |
sumReflect := 0 | |
sumSwitch := 0 | |
sumSprintf := 0 | |
for _, val := range list { | |
sumReflect = sumReflect + reflectTest(serviceCommands, val) | |
} | |
for _, val := range list { | |
sumSwitch = sumSwitch + switchTest(serviceCommands, val) | |
} | |
for _, val := range list { | |
sumSprintf = sumSprintf + sprintfTypeTest(serviceCommands, val) | |
} | |
if sumReflect != sumSwitch || sumReflect != sumSprintf { | |
t.Errorf("summed test values don't match sumSwitch=%d sumReflect=%d sumSprintf=%d", sumSwitch, sumReflect, sumSprintf) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment