Stack-based unmarshaler (#546)
* Benchmark script * Rewrite unmarshaler using the stack Instead of tracking the build chain using `target`s, use the stack instead. Working and most benchmarks look good, but regression on structs unmarshalling. ~60% slower on ReferenceFile/struct. * Shortcut to check if last node of iterator * Remove unecessary pointer allocation * Skip over unused keys without marking them as seen * Add some tests * Fix mktemp on macos
This commit is contained in:
@@ -31,13 +31,14 @@ var bench_inputs = []struct {
|
||||
|
||||
func TestUnmarshalDatasetCode(t *testing.T) {
|
||||
for _, tc := range bench_inputs {
|
||||
buf := fixture(t, tc.name)
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
buf := fixture(t, tc.name)
|
||||
|
||||
var v interface{}
|
||||
check(t, toml.Unmarshal(buf, &v))
|
||||
require.NoError(t, toml.Unmarshal(buf, &v))
|
||||
|
||||
b, err := json.Marshal(v)
|
||||
check(t, err)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, len(b), tc.jsonLen)
|
||||
})
|
||||
}
|
||||
@@ -45,14 +46,14 @@ func TestUnmarshalDatasetCode(t *testing.T) {
|
||||
|
||||
func BenchmarkUnmarshalDataset(b *testing.B) {
|
||||
for _, tc := range bench_inputs {
|
||||
buf := fixture(b, tc.name)
|
||||
b.Run(tc.name, func(b *testing.B) {
|
||||
buf := fixture(b, tc.name)
|
||||
b.SetBytes(int64(len(buf)))
|
||||
b.ReportAllocs()
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
var v interface{}
|
||||
check(b, toml.Unmarshal(buf, &v))
|
||||
require.NoError(b, toml.Unmarshal(buf, &v))
|
||||
}
|
||||
})
|
||||
}
|
||||
@@ -60,22 +61,20 @@ func BenchmarkUnmarshalDataset(b *testing.B) {
|
||||
|
||||
// fixture returns the uncompressed contents of path.
|
||||
func fixture(tb testing.TB, path string) []byte {
|
||||
f, err := os.Open(filepath.Join("testdata", path+".toml.gz"))
|
||||
check(tb, err)
|
||||
tb.Helper()
|
||||
|
||||
file := path + ".toml.gz"
|
||||
f, err := os.Open(filepath.Join("testdata", file))
|
||||
if os.IsNotExist(err) {
|
||||
tb.Skip("benchmark fixture not found:", file)
|
||||
}
|
||||
require.NoError(tb, err)
|
||||
defer f.Close()
|
||||
|
||||
gz, err := gzip.NewReader(f)
|
||||
check(tb, err)
|
||||
require.NoError(tb, err)
|
||||
|
||||
buf, err := ioutil.ReadAll(gz)
|
||||
check(tb, err)
|
||||
|
||||
require.NoError(tb, err)
|
||||
return buf
|
||||
}
|
||||
|
||||
func check(tb testing.TB, err error) {
|
||||
if err != nil {
|
||||
tb.Helper()
|
||||
tb.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,6 +9,18 @@ import (
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestUnmarshalSimple(t *testing.T) {
|
||||
doc := []byte(`A = "hello"`)
|
||||
d := struct {
|
||||
A string
|
||||
}{}
|
||||
|
||||
err := toml.Unmarshal(doc, &d)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkUnmarshalSimple(b *testing.B) {
|
||||
doc := []byte(`A = "hello"`)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user