Repository navigation
performance issue #256
Description
Activity
I haven't used ffjson in a long time so I might be wrong, but this is the only way I could get your code fast:
func BenchmarkFFJson(b *testing.B) { d := Demo{ A: 1, B: "asd", } buf := &fflib.Buffer{} for i := 0; i < b.N; i++ { if err := d.MarshalJSONBuf(buf); err != nil { panic(err) } _ = buf.Bytes() buf.Reset() } }
I also had to apply this patch to get ffjson down to 0 allocations: https://gist.github.com/erikdubbelboer/898d219bbc997ab1e9aeee2d64aafa04
It seems like ffjson isn't doing it's best to get hot path allocations down to 0. @pquerna let me know if you want me to make a pull request for this?The result:
BenchmarkEncodingJson-16 4652290 249 ns/op 64 B/op 2 allocs/op BenchmarkFFJson-16 13343437 90.7 ns/op 0 B/op 0 allocs/opHi @erikdubbelboer,
convert[]byteto string no longer requireSliceHeader, just*(*string)(unsafe.Pointer(&bs))is fine.After dig into this more, I compare ffjson/easyjson/jsoniter, it's surprising ffjson is the slowest, with highest allocs.
BenchmarkJsoncost/std-8 1000000 1052 ns/op 240 B/op 4 allocs/op BenchmarkJsoncost/jsoniter-8 1000000 1268 ns/op 272 B/op 5 allocs/op BenchmarkJsoncost/easyjson-8 2000000 629 ns/op 336 B/op 4 allocs/op BenchmarkJsoncost/ffjson-8 1000000 1044 ns/op 480 B/op 7 allocs/oprepo for this benchmark:
Correct but this is to convert a string to a
[]bytewhich does requireSliceHeaderas you need to set the capacity which a string doesn't have in it's header.I always use easyjson, that's why I said I haven't used ffjson in a long time.
if convert
[]byteto string,*(*[]byte)(unsafe.Pointer(&s))would be fine IMO.That will only work in cases where you never look at the capacity of the returned slice. If you do something that looks at the capacity it will fail horribly as it will use the memory after the string header as capacity and you have on idea what is stored there.
I got your point, thanks for your explanation.
Reacted by Erik Dubbelboer
go test -run ^NOTHING -bench Jsoncost$ -v
Then, I use ffjson to generate custom MarshalJSON for Demo struct, update
json.Marshal(d)toffjson.Marshal(d), run benchmark againIt seems ffjson is slower than encoding/json, is there anything I'm missing ?