Refactor unit test and benchmark. Include hand rolled implementation.
This commit is contained in:
170
src/vec3_test.go
170
src/vec3_test.go
@@ -3,12 +3,33 @@ package main
|
||||
import (
|
||||
"encoding/json"
|
||||
"reflect"
|
||||
"strconv"
|
||||
"testing"
|
||||
|
||||
"github.com/francoispqt/gojay"
|
||||
jsoniter "github.com/json-iterator/go"
|
||||
"github.com/pquerna/ffjson/ffjson"
|
||||
)
|
||||
|
||||
func HandRolled(vs []Vec3) ([]byte, error) {
|
||||
buf := []byte("[")
|
||||
for i, v := range vs {
|
||||
if i > 0 {
|
||||
buf = append(buf, []byte(`,{"x":`)...)
|
||||
} else {
|
||||
buf = append(buf, []byte(`{"x":`)...)
|
||||
}
|
||||
buf = strconv.AppendFloat(buf, float64(v.X), 'f', -1, 32)
|
||||
buf = append(buf, []byte(`,"y":`)...)
|
||||
buf = strconv.AppendFloat(buf, float64(v.Y), 'f', -1, 32)
|
||||
buf = append(buf, []byte(`,"z":`)...)
|
||||
buf = strconv.AppendFloat(buf, float64(v.Z), 'f', -1, 32)
|
||||
buf = append(buf, []byte("}")...)
|
||||
}
|
||||
buf = append(buf, ']')
|
||||
return buf, nil
|
||||
}
|
||||
|
||||
type Vec3 struct {
|
||||
X float32 `json:"x"`
|
||||
Y float32 `json:"y"`
|
||||
@@ -37,20 +58,50 @@ func (vs Vec3Slice) IsNil() bool {
|
||||
return vs == nil
|
||||
}
|
||||
|
||||
func TestVec3ToJSONStdlib(t *testing.T) {
|
||||
vecs := []Vec3{{X: 1.0, Y: 2.0, Z: 3.0}}
|
||||
|
||||
got, err := json.Marshal(vecs)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to marshal: %v", err)
|
||||
func TestVec3ToJSON(t *testing.T) {
|
||||
vecs := []Vec3{
|
||||
{X: 1.0, Y: 2.0, Z: 3.0},
|
||||
{X: 4.5, Y: 5.0, Z: 6.0},
|
||||
}
|
||||
want := []byte(`[{"x":1,"y":2,"z":3}]`)
|
||||
if !reflect.DeepEqual(want, got) {
|
||||
t.Fatalf("got != want\nGot: %s\nWant: %s", got, want)
|
||||
|
||||
for _, ts := range []struct {
|
||||
name string
|
||||
f func([]Vec3) ([]byte, error)
|
||||
}{
|
||||
{"HandRolled", HandRolled},
|
||||
{"stdlib", func(vs []Vec3) ([]byte, error) {
|
||||
return json.Marshal(vs)
|
||||
}},
|
||||
{"ffjson", func(vs []Vec3) ([]byte, error) {
|
||||
return ffjson.Marshal(vecs)
|
||||
}},
|
||||
{"iterator", func(vs []Vec3) ([]byte, error) {
|
||||
var js = jsoniter.ConfigCompatibleWithStandardLibrary
|
||||
return js.Marshal(vecs)
|
||||
}},
|
||||
{"gojay", func(vs []Vec3) ([]byte, error) {
|
||||
var vecs Vec3Slice
|
||||
for _, v := range vs {
|
||||
v := v
|
||||
vecs = append(vecs, &v)
|
||||
}
|
||||
|
||||
return gojay.Marshal(&vecs)
|
||||
}},
|
||||
} {
|
||||
t.Run(ts.name, func(t *testing.T) {
|
||||
got, err := ts.f(vecs)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to marshal: %v", err)
|
||||
}
|
||||
want := []byte(`[{"x":1,"y":2,"z":3},{"x":4.5,"y":5,"z":6}]`)
|
||||
if !reflect.DeepEqual(want, got) {
|
||||
t.Fatalf("got != want\nGot: %s\nWant: %s", got, want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkVec3ToJSONStdlib(b *testing.B) {
|
||||
func BenchmarkVec3ToJSON(b *testing.B) {
|
||||
var vecs []Vec3
|
||||
|
||||
for i := 0; i < 1000; i++ {
|
||||
@@ -60,74 +111,37 @@ func BenchmarkVec3ToJSONStdlib(b *testing.B) {
|
||||
Z: 255. * float32(i) / 1000.,
|
||||
})
|
||||
}
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
if _, err := json.Marshal(vecs); err != nil {
|
||||
b.Fatalf("Failed to marshal: %v", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
for _, ts := range []struct {
|
||||
name string
|
||||
f func([]Vec3) ([]byte, error)
|
||||
}{
|
||||
{"HandRolled", HandRolled},
|
||||
{"stdlib", func(vs []Vec3) ([]byte, error) {
|
||||
return json.Marshal(vs)
|
||||
}},
|
||||
{"ffjson", func(vs []Vec3) ([]byte, error) {
|
||||
return ffjson.Marshal(vecs)
|
||||
}},
|
||||
{"iterator", func(vs []Vec3) ([]byte, error) {
|
||||
var js = jsoniter.ConfigCompatibleWithStandardLibrary
|
||||
return js.Marshal(vecs)
|
||||
}},
|
||||
{"gojay", func(vs []Vec3) ([]byte, error) {
|
||||
var vecs Vec3Slice
|
||||
for _, v := range vs {
|
||||
v := v
|
||||
vecs = append(vecs, &v)
|
||||
}
|
||||
|
||||
func TestVec3ToJSONIterator(t *testing.T) {
|
||||
vecs := []Vec3{{X: 1.0, Y: 2.0, Z: 3.0}}
|
||||
|
||||
var json = jsoniter.ConfigCompatibleWithStandardLibrary
|
||||
got, err := json.Marshal(vecs)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to marshal: %v", err)
|
||||
}
|
||||
want := []byte(`[{"x":1,"y":2,"z":3}]`)
|
||||
if !reflect.DeepEqual(want, got) {
|
||||
t.Fatalf("got != want\nGot: %s\nWant: %s", got, want)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkVec3ToJSONIterator(b *testing.B) {
|
||||
var vecs []Vec3
|
||||
|
||||
for i := 0; i < 1000; i++ {
|
||||
vecs = append(vecs, Vec3{
|
||||
X: 255. * float32(i) / 1000.,
|
||||
Y: 255. * float32(i) / 1000.,
|
||||
Z: 255. * float32(i) / 1000.,
|
||||
return gojay.Marshal(&vecs)
|
||||
}},
|
||||
} {
|
||||
b.Run(ts.name, func(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
if _, err := ts.f(vecs); err != nil {
|
||||
b.Fatalf("Failed to marshal: %v", err)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
var json = jsoniter.ConfigCompatibleWithStandardLibrary
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
if _, err := json.Marshal(vecs); err != nil {
|
||||
b.Fatalf("Failed to marshal: %v", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestVec3ToJSONGojay(t *testing.T) {
|
||||
vecs := Vec3Slice{{X: 1.0, Y: 2.0, Z: 3.0}}
|
||||
|
||||
got, err := gojay.Marshal(&vecs)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to marshal: %v", err)
|
||||
}
|
||||
want := []byte(`[{"x":1,"y":2,"z":3}]`)
|
||||
if !reflect.DeepEqual(want, got) {
|
||||
t.Fatalf("got != want\nGot: %s\nWant: %s", got, want)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkVec3ToJSONGojay(b *testing.B) {
|
||||
vecs := Vec3Slice{}
|
||||
|
||||
for i := 0; i < 1000; i++ {
|
||||
vecs = append(vecs, &Vec3{
|
||||
X: 255. * float32(i) / 1000.,
|
||||
Y: 255. * float32(i) / 1000.,
|
||||
Z: 255. * float32(i) / 1000.,
|
||||
})
|
||||
}
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
if _, err := gojay.Marshal(&vecs); err != nil {
|
||||
b.Fatalf("Failed to marshal: %v", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user