Navigation Menu

Skip to content

Instantly share code, notes, and snippets.

@benhoyt
Created September 23, 2021 00:12
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save benhoyt/24dd927cba49b0620575fd06f1185f66 to your computer and use it in GitHub Desktop.
Save benhoyt/24dd927cba49b0620575fd06f1185f66 to your computer and use it in GitHub Desktop.
Benchmark of three ways to do optional fields in Go structs
package client
func IntPtr(n int) *int { return &n }
type FooArgsPtr struct {
UserID *int
User string
GroupID *int
Group string
}
type FooArgsBool struct {
ChangeUser bool
UserID int
User string
ChangeGroup bool
GroupID int
Group string
}
func Int(n int) OptionalInt { return OptionalInt{IsSet: true, Value: n} }
type OptionalInt struct {
IsSet bool
Value int
}
type FooArgsOptional struct {
UserID OptionalInt
User string
GroupID OptionalInt
Group string
}
/* On my machine, I get the following results. I was surprised that pointers are faster here!
cpu: Intel(R) Core(TM) i7-6700HQ CPU @ 2.60GHz
BenchmarkPtr-8 332021145 3.408 ns/op
BenchmarkBool-8 327414150 3.652 ns/op
BenchmarkOptional-8 326028478 3.662 ns/op
*/
package main_test
import (
"testing"
"optionaltest/client"
)
var (
sumPtr int
sumBool int
sumOptional int
)
//go:noinline
func FooPtr(args *client.FooArgsPtr) {
if args.UserID != nil {
sumPtr += *args.UserID
}
if args.GroupID != nil {
sumPtr += *args.GroupID
}
}
//go:noinline
func FooBool(args *client.FooArgsBool) {
if args.ChangeUser {
sumBool += args.UserID
}
if args.ChangeGroup {
sumBool += args.GroupID
}
}
//go:noinline
func FooOptional(args *client.FooArgsOptional) {
if args.UserID.IsSet {
sumOptional += args.UserID.Value
}
if args.GroupID.IsSet {
sumOptional += args.GroupID.Value
}
}
func BenchmarkPtr(b *testing.B) {
sumPtr = 0
for i := 0; i < b.N; i++ {
uid := 100
args := &client.FooArgsPtr{
UserID: &uid,
GroupID: client.IntPtr(200),
}
FooPtr(args)
}
}
func BenchmarkBool(b *testing.B) {
sumBool = 0
for i := 0; i < b.N; i++ {
uid := 100
args := &client.FooArgsBool{
ChangeUser: true,
UserID: uid,
ChangeGroup: true,
GroupID: 200,
}
FooBool(args)
}
}
func BenchmarkOptional(b *testing.B) {
sumOptional = 0
for i := 0; i < b.N; i++ {
uid := 100
args := &client.FooArgsOptional{
UserID: client.Int(uid),
GroupID: client.Int(200),
}
FooOptional(args)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment