Last active
February 1, 2022 17:35
-
-
Save tommyo/849e9fb8db0310ea14ba2f07ab2c25f1 to your computer and use it in GitHub Desktop.
Benchmark Generics when running json.Marshal and json.Unmarshal with a nested unknown
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 benchmark | |
import ( | |
"encoding/json" | |
"testing" | |
) | |
var innerJson []byte = []byte(`{ "foo": "bar" }`) | |
var fullJson []byte = []byte(`{ "name": "foo", "value": { "foo": "bar" }}`) | |
var fin []byte | |
type Inner struct { | |
Foo string `json:"foo"` | |
} | |
type Wrapped struct { | |
Name string `json:"name"` | |
Value interface{} `json:"value"` | |
} | |
type UnWrapped struct { | |
Name string `json:"name"` | |
Value json.RawMessage `json:"value"` | |
} | |
type Generic[T any] struct { | |
Name string `json:"name"` | |
Value T `json:"value"` | |
} | |
func BenchmarkMarshalInner(b *testing.B) { | |
inner := Inner{"bar"} | |
var res []byte | |
b.ResetTimer() | |
for n := 0; n < b.N; n++ { | |
res, _ = json.Marshal(inner) | |
} | |
fin = res | |
} | |
func BenchmarkMarshalWrapped(b *testing.B) { | |
wrapped := Wrapped{ | |
Name: "foo", | |
Value: Inner{"bar"}, | |
} | |
var res []byte | |
b.ResetTimer() | |
for n := 0; n < b.N; n++ { | |
res, _ = json.Marshal(wrapped) | |
} | |
fin = res | |
} | |
func BenchmarkMarshalGeneric(b *testing.B) { | |
generic := Generic[Inner]{ | |
Name: "foo", | |
Value: Inner{"bar"}, | |
} | |
var res []byte | |
b.ResetTimer() | |
for n := 0; n < b.N; n++ { | |
res, _ = json.Marshal(generic) | |
} | |
fin = res | |
} | |
// Unmarshal the inner part only, as a baseline metric | |
func BenchmarkUnmarshalInner(b *testing.B) { | |
var inner Inner | |
b.ResetTimer() | |
for n := 0; n < b.N; n++ { | |
json.Unmarshal(innerJson, &inner) | |
} | |
} | |
// The Inner is a map[string]interface{}, not type aligned | |
func BenchmarkUnmarshalWrapped(b *testing.B) { | |
var wrapped Wrapped | |
b.ResetTimer() | |
for n := 0; n < b.N; n++ { | |
json.Unmarshal(fullJson, &wrapped) | |
} | |
} | |
// The inner is []byte, ready to be Unmarshalled | |
func BenchmarkUnmarshalUnwrapped(b *testing.B) { | |
var unwrapped UnWrapped | |
b.ResetTimer() | |
for n := 0; n < b.N; n++ { | |
json.Unmarshal(fullJson, &unwrapped) | |
} | |
} | |
// Inner is the proper type | |
func BenchmarkUnmarshalUnwrappedFull(b *testing.B) { | |
var unwrapped UnWrapped | |
var inner Inner | |
b.ResetTimer() | |
for n := 0; n < b.N; n++ { | |
json.Unmarshal(fullJson, &unwrapped) | |
json.Unmarshal(unwrapped.Value, &inner) | |
} | |
} | |
// Inner is the proper type | |
func BenchmarkUnmarshalGeneric(b *testing.B) { | |
var generic Generic[Inner] | |
b.ResetTimer() | |
for n := 0; n < b.N; n++ { | |
json.Unmarshal(fullJson, &generic) | |
} | |
} |
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
goos: darwin | |
goarch: amd64 | |
pkg: github.com/huffduff/go-indexeddb/benchmark | |
cpu: VirtualApple @ 2.50GHz | |
BenchmarkMarshalInner-8 8437233 140.0 ns/op 32 B/op 2 allocs/op | |
BenchmarkMarshalWrapped-8 4984962 240.4 ns/op 80 B/op 2 allocs/op | |
BenchmarkMarshalGeneric-8 5740166 206.3 ns/op 80 B/op 2 allocs/op | |
BenchmarkUnmarshalInner-8 2776051 427.7 ns/op 224 B/op 5 allocs/op | |
BenchmarkUnmarshalWrapped-8 1331446 889.6 ns/op 600 B/op 11 allocs/op | |
BenchmarkUnmarshalUnwrapped-8 1613664 752.5 ns/op 240 B/op 6 allocs/op | |
BenchmarkUnmarshalUnwrappedFull-8 968174 1203 ns/op 464 B/op 11 allocs/op | |
BenchmarkUnmarshalGeneric-8 1359284 881.4 ns/op 272 B/op 8 allocs/op | |
PASS | |
ok github.com/huffduff/go-indexeddb/benchmark 13.372s |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment