Commit 33e2b330 authored by Eric Myhre's avatar Eric Myhre

Port scaled marshal tests to new node interfaces.

Marshal is 25% faster.  Not bad.  (There's also a perf bug in the codec
code which I'm about to fix which will change the speedup to *double*.)

Unmarshal is a bit faster, but not as much improved as marshal.
This is unsurprisingly because we chose not to amortize allocations
as much as we could in map and list creation because the size penalty
seemed too steep to make it a worthy trade.  (This gives us *much*
better numbers to fuel further consideration of that trade, though.)
parent 5acd08dd
...@@ -31,13 +31,19 @@ func BenchmarkMapStrInt_25n_Iteration(b *testing.B) { ...@@ -31,13 +31,19 @@ func BenchmarkMapStrInt_25n_Iteration(b *testing.B) {
tests.SpecBenchmarkMapStrInt_25n_Iteration(b, Style__Map{}) tests.SpecBenchmarkMapStrInt_25n_Iteration(b, Style__Map{})
} }
func BenchmarkUnmarshalMapStrInt_3n(b *testing.B) { func BenchmarkSpec_Marshal_Map3StrInt(b *testing.B) {
tests.SpecBenchmarkUnmarshalMapStrInt_3n(b, Style__Map{}) tests.BenchmarkSpec_Marshal_Map3StrInt(b, Style__Map{})
}
func BenchmarkSpec_Marshal_Map3StrInt_CodecNull(b *testing.B) {
tests.BenchmarkSpec_Marshal_Map3StrInt_CodecNull(b, Style__Map{})
}
func BenchmarkSpec_Marshal_MapNStrMap3StrInt(b *testing.B) {
tests.BenchmarkSpec_Marshal_MapNStrMap3StrInt(b, Style__Map{})
} }
func BenchmarkMarshalMapStrInt_3n(b *testing.B) { func BenchmarkSpec_Unmarshal_Map3StrInt(b *testing.B) {
tests.SpecBenchmarkMarshalMapStrInt_3n(b, Style__Map{}) tests.BenchmarkSpec_Unmarshal_Map3StrInt(b, Style__Map{})
} }
func BenchmarkMarshalToNullMapStrInt_3n(b *testing.B) { func BenchmarkSpec_Unmarshal_MapNStrMap3StrInt(b *testing.B) {
tests.SpecBenchmarkMarshalToNullMapStrInt_3n(b, Style__Map{}) tests.BenchmarkSpec_Unmarshal_MapNStrMap3StrInt(b, Style__Map{})
} }
...@@ -2,6 +2,7 @@ package tests ...@@ -2,6 +2,7 @@ package tests
import ( import (
"bytes" "bytes"
"fmt"
"testing" "testing"
refmtjson "github.com/polydawn/refmt/json" refmtjson "github.com/polydawn/refmt/json"
...@@ -10,6 +11,7 @@ import ( ...@@ -10,6 +11,7 @@ import (
ipld "github.com/ipld/go-ipld-prime/_rsrch/nodesolution" ipld "github.com/ipld/go-ipld-prime/_rsrch/nodesolution"
"github.com/ipld/go-ipld-prime/_rsrch/nodesolution/codec" "github.com/ipld/go-ipld-prime/_rsrch/nodesolution/codec"
"github.com/ipld/go-ipld-prime/must" "github.com/ipld/go-ipld-prime/must"
"github.com/ipld/go-ipld-prime/tests/corpus"
) )
// All of the marshalling and unmarshalling benchmark specs use JSON. // All of the marshalling and unmarshalling benchmark specs use JSON.
...@@ -21,7 +23,7 @@ import ( ...@@ -21,7 +23,7 @@ import (
// - we can make direct comparisons to the standard library json marshalling // - we can make direct comparisons to the standard library json marshalling
// and unmarshalling, thus having a back-of-the-envelope baseline to compare. // and unmarshalling, thus having a back-of-the-envelope baseline to compare.
func SpecBenchmarkMarshalMapStrInt_3n(b *testing.B, ns ipld.NodeStyle) { func BenchmarkSpec_Marshal_Map3StrInt(b *testing.B, ns ipld.NodeStyle) {
nb := ns.NewBuilder() nb := ns.NewBuilder()
must.NotError(codec.Unmarshal(nb, refmtjson.NewDecoder(bytes.NewBufferString(`{"whee":1,"woot":2,"waga":3}`)))) must.NotError(codec.Unmarshal(nb, refmtjson.NewDecoder(bytes.NewBufferString(`{"whee":1,"woot":2,"waga":3}`))))
n := nb.Build() n := nb.Build()
...@@ -37,7 +39,7 @@ func SpecBenchmarkMarshalMapStrInt_3n(b *testing.B, ns ipld.NodeStyle) { ...@@ -37,7 +39,7 @@ func SpecBenchmarkMarshalMapStrInt_3n(b *testing.B, ns ipld.NodeStyle) {
} }
} }
func SpecBenchmarkMarshalToNullMapStrInt_3n(b *testing.B, ns ipld.NodeStyle) { func BenchmarkSpec_Marshal_Map3StrInt_CodecNull(b *testing.B, ns ipld.NodeStyle) {
nb := ns.NewBuilder() nb := ns.NewBuilder()
must.NotError(codec.Unmarshal(nb, refmtjson.NewDecoder(bytes.NewBufferString(`{"whee":1,"woot":2,"waga":3}`)))) must.NotError(codec.Unmarshal(nb, refmtjson.NewDecoder(bytes.NewBufferString(`{"whee":1,"woot":2,"waga":3}`))))
n := nb.Build() n := nb.Build()
...@@ -59,3 +61,28 @@ type nullTokenSink struct{} ...@@ -59,3 +61,28 @@ type nullTokenSink struct{}
func (nullTokenSink) Step(_ *tok.Token) (bool, error) { func (nullTokenSink) Step(_ *tok.Token) (bool, error) {
return false, nil return false, nil
} }
func BenchmarkSpec_Marshal_MapNStrMap3StrInt(b *testing.B, ns ipld.NodeStyle) {
for _, n := range []int{0, 1, 2, 4, 8, 16, 32} {
b.Run(fmt.Sprintf("n=%d", n), func(b *testing.B) {
msg := corpus.MapNStrMap3StrInt(n)
node := mustNodeFromJsonString(ns.NewBuilder(), msg)
b.ResetTimer()
var buf bytes.Buffer
var err error
for i := 0; i < b.N; i++ {
buf = bytes.Buffer{}
err = codec.Marshal(node, refmtjson.NewEncoder(&buf, refmtjson.EncodeOptions{}))
}
b.StopTimer()
if err != nil {
b.Fatalf("marshal errored: %s", err)
}
if buf.String() != msg {
b.Fatalf("marshal didn't match corpus")
}
})
}
}
...@@ -2,12 +2,14 @@ package tests ...@@ -2,12 +2,14 @@ package tests
import ( import (
"bytes" "bytes"
"fmt"
"testing" "testing"
refmtjson "github.com/polydawn/refmt/json" refmtjson "github.com/polydawn/refmt/json"
ipld "github.com/ipld/go-ipld-prime/_rsrch/nodesolution" ipld "github.com/ipld/go-ipld-prime/_rsrch/nodesolution"
"github.com/ipld/go-ipld-prime/_rsrch/nodesolution/codec" "github.com/ipld/go-ipld-prime/_rsrch/nodesolution/codec"
"github.com/ipld/go-ipld-prime/tests/corpus"
) )
// All of the marshalling and unmarshalling benchmark specs use JSON. // All of the marshalling and unmarshalling benchmark specs use JSON.
...@@ -19,7 +21,7 @@ import ( ...@@ -19,7 +21,7 @@ import (
// - we can make direct comparisons to the standard library json marshalling // - we can make direct comparisons to the standard library json marshalling
// and unmarshalling, thus having a back-of-the-envelope baseline to compare. // and unmarshalling, thus having a back-of-the-envelope baseline to compare.
func SpecBenchmarkUnmarshalMapStrInt_3n(b *testing.B, ns ipld.NodeStyle) { func BenchmarkSpec_Unmarshal_Map3StrInt(b *testing.B, ns ipld.NodeStyle) {
var err error var err error
for i := 0; i < b.N; i++ { for i := 0; i < b.N; i++ {
nb := ns.NewBuilder() nb := ns.NewBuilder()
...@@ -30,3 +32,31 @@ func SpecBenchmarkUnmarshalMapStrInt_3n(b *testing.B, ns ipld.NodeStyle) { ...@@ -30,3 +32,31 @@ func SpecBenchmarkUnmarshalMapStrInt_3n(b *testing.B, ns ipld.NodeStyle) {
panic(err) panic(err)
} }
} }
func BenchmarkSpec_Unmarshal_MapNStrMap3StrInt(b *testing.B, ns ipld.NodeStyle) {
for _, n := range []int{0, 1, 2, 4, 8, 16, 32} {
b.Run(fmt.Sprintf("n=%d", n), func(b *testing.B) {
msg := corpus.MapNStrMap3StrInt(n)
b.ResetTimer()
var node ipld.Node
var err error
nb := ns.NewBuilder()
for i := 0; i < b.N; i++ {
err = codec.Unmarshal(nb, refmtjson.NewDecoder(bytes.NewBufferString(msg)))
node = nb.Build()
nb.Reset()
}
b.StopTimer()
if err != nil {
b.Fatalf("unmarshal errored: %s", err)
}
var buf bytes.Buffer
codec.Marshal(node, refmtjson.NewEncoder(&buf, refmtjson.EncodeOptions{}))
if buf.String() != msg {
b.Fatalf("remarshal didn't match corpus")
}
})
}
}
package tests package tests
import (
"bytes"
refmtjson "github.com/polydawn/refmt/json"
ipld "github.com/ipld/go-ipld-prime/_rsrch/nodesolution"
"github.com/ipld/go-ipld-prime/_rsrch/nodesolution/codec"
)
// various benchmarks assign their final result here, // various benchmarks assign their final result here,
// in order to defuse the possibility of their work being elided. // in order to defuse the possibility of their work being elided.
var sink interface{} var sink interface{}
func mustNodeFromJsonString(nb ipld.NodeBuilder, str string) ipld.Node {
err := codec.Unmarshal(nb, refmtjson.NewDecoder(bytes.NewBufferString(str)))
if err != nil {
panic(err)
}
return nb.Build()
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment