Refactor unit test and benchmark. Include hand rolled implementation.
This commit is contained in:
parent
ac30dcd125
commit
7707ff9660
12
README.md
12
README.md
@ -6,7 +6,7 @@
|
|||||||
|
|
||||||
running 2 tests
|
running 2 tests
|
||||||
test vec3::tests::test_vec3_to_json ... ignored
|
test vec3::tests::test_vec3_to_json ... ignored
|
||||||
test vec3::tests::bench_vec3_to_json ... bench: 181,463 ns/iter (+/- 52,876)
|
test vec3::tests::bench_vec3_to_json ... bench: 181,127 ns/iter (+/- 37,666)
|
||||||
|
|
||||||
test result: ok. 0 passed; 0 failed; 1 ignored; 1 measured; 0 filtered out
|
test result: ok. 0 passed; 0 failed; 1 ignored; 1 measured; 0 filtered out
|
||||||
|
|
||||||
@ -24,9 +24,11 @@ test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out
|
|||||||
goos: linux
|
goos: linux
|
||||||
goarch: amd64
|
goarch: amd64
|
||||||
pkg: xinu.tv/rustperf/src
|
pkg: xinu.tv/rustperf/src
|
||||||
BenchmarkVec3ToJSONStdlib-8 2755 481252 ns/op
|
BenchmarkVec3ToJSON/HandRolled-8 3042 338000 ns/op
|
||||||
BenchmarkVec3ToJSONIterator-8 2395 515586 ns/op
|
BenchmarkVec3ToJSON/stdlib-8 2754 459788 ns/op
|
||||||
BenchmarkVec3ToJSONGojay-8 1372 877632 ns/op
|
BenchmarkVec3ToJSON/ffjson-8 2697 457685 ns/op
|
||||||
|
BenchmarkVec3ToJSON/iterator-8 2542 483460 ns/op
|
||||||
|
BenchmarkVec3ToJSON/gojay-8 1303 905583 ns/op
|
||||||
PASS
|
PASS
|
||||||
ok xinu.tv/rustperf/src 4.947s
|
ok xinu.tv/rustperf/src 6.989s
|
||||||
```
|
```
|
||||||
|
|||||||
1
go.mod
1
go.mod
@ -5,4 +5,5 @@ go 1.13
|
|||||||
require (
|
require (
|
||||||
github.com/francoispqt/gojay v1.2.13
|
github.com/francoispqt/gojay v1.2.13
|
||||||
github.com/json-iterator/go v1.1.7
|
github.com/json-iterator/go v1.1.7
|
||||||
|
github.com/pquerna/ffjson v0.0.0-20190930134022-aa0246cd15f7
|
||||||
)
|
)
|
||||||
|
|||||||
2
go.sum
2
go.sum
@ -70,6 +70,8 @@ github.com/neelance/sourcemap v0.0.0-20151028013722-8c68805598ab/go.mod h1:Qr6/a
|
|||||||
github.com/openzipkin/zipkin-go v0.1.1/go.mod h1:NtoC/o8u3JlF1lSlyPNswIbeQH9bJTmOf0Erfk+hxe8=
|
github.com/openzipkin/zipkin-go v0.1.1/go.mod h1:NtoC/o8u3JlF1lSlyPNswIbeQH9bJTmOf0Erfk+hxe8=
|
||||||
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
|
github.com/pquerna/ffjson v0.0.0-20190930134022-aa0246cd15f7 h1:xoIK0ctDddBMnc74udxJYBqlo9Ylnsp1waqjLsnef20=
|
||||||
|
github.com/pquerna/ffjson v0.0.0-20190930134022-aa0246cd15f7/go.mod h1:YARuvh7BUWHNhzDq2OM5tzR2RiCcN2D7sapiKyCel/M=
|
||||||
github.com/prometheus/client_golang v0.8.0/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
|
github.com/prometheus/client_golang v0.8.0/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
|
||||||
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
|
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
|
||||||
github.com/prometheus/common v0.0.0-20180801064454-c7de2306084e/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
|
github.com/prometheus/common v0.0.0-20180801064454-c7de2306084e/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
|
||||||
|
|||||||
154
src/vec3_test.go
154
src/vec3_test.go
@ -3,12 +3,33 @@ package main
|
|||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"reflect"
|
"reflect"
|
||||||
|
"strconv"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/francoispqt/gojay"
|
"github.com/francoispqt/gojay"
|
||||||
jsoniter "github.com/json-iterator/go"
|
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 {
|
type Vec3 struct {
|
||||||
X float32 `json:"x"`
|
X float32 `json:"x"`
|
||||||
Y float32 `json:"y"`
|
Y float32 `json:"y"`
|
||||||
@ -37,20 +58,50 @@ func (vs Vec3Slice) IsNil() bool {
|
|||||||
return vs == nil
|
return vs == nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestVec3ToJSONStdlib(t *testing.T) {
|
func TestVec3ToJSON(t *testing.T) {
|
||||||
vecs := []Vec3{{X: 1.0, Y: 2.0, Z: 3.0}}
|
vecs := []Vec3{
|
||||||
|
{X: 1.0, Y: 2.0, Z: 3.0},
|
||||||
|
{X: 4.5, Y: 5.0, Z: 6.0},
|
||||||
|
}
|
||||||
|
|
||||||
got, err := json.Marshal(vecs)
|
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 {
|
if err != nil {
|
||||||
t.Fatalf("Failed to marshal: %v", err)
|
t.Fatalf("Failed to marshal: %v", err)
|
||||||
}
|
}
|
||||||
want := []byte(`[{"x":1,"y":2,"z":3}]`)
|
want := []byte(`[{"x":1,"y":2,"z":3},{"x":4.5,"y":5,"z":6}]`)
|
||||||
if !reflect.DeepEqual(want, got) {
|
if !reflect.DeepEqual(want, got) {
|
||||||
t.Fatalf("got != want\nGot: %s\nWant: %s", got, want)
|
t.Fatalf("got != want\nGot: %s\nWant: %s", got, want)
|
||||||
}
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
func BenchmarkVec3ToJSON(b *testing.B) {
|
||||||
func BenchmarkVec3ToJSONStdlib(b *testing.B) {
|
|
||||||
var vecs []Vec3
|
var vecs []Vec3
|
||||||
|
|
||||||
for i := 0; i < 1000; i++ {
|
for i := 0; i < 1000; i++ {
|
||||||
@ -60,74 +111,37 @@ func BenchmarkVec3ToJSONStdlib(b *testing.B) {
|
|||||||
Z: 255. * float32(i) / 1000.,
|
Z: 255. * float32(i) / 1000.,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
b.ResetTimer()
|
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)
|
||||||
|
}},
|
||||||
|
} {
|
||||||
|
b.Run(ts.name, func(b *testing.B) {
|
||||||
for i := 0; i < b.N; i++ {
|
for i := 0; i < b.N; i++ {
|
||||||
if _, err := json.Marshal(vecs); err != nil {
|
if _, err := ts.f(vecs); err != nil {
|
||||||
b.Fatalf("Failed to marshal: %v", err)
|
b.Fatalf("Failed to marshal: %v", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
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.,
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
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)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user