New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
encoding/json: unnecessary allocation in (*scanner).error #10335
Comments
Thanks! A few things:
|
Thanks, I don't think that code is fit for contribution though. I will provide a benchmark to reproduce the issue as soon as I can isolate it. |
The benchmark is pretty trivial, but reproducing the allocations seems to require unmarshalling into a struct. I wasn't able to reproduce using an empty interface. I went to http://www.json.org/example.html got a large sample of a JSON object, pasted it into https://mholt.github.io/json-to-go/ to generate a struct. Then the benchmark is simply:
I wish I had more time to work on this and properly contribute a fix, but I unfortunately don't. Apologies, this is the best I can do right now. |
No worries, and thanks, this is useful as-is. |
Here's a smaller, self-contained benchmark for whoever looks at this. (Not me.) The newline in the byte slice is important. func BenchmarkIssue10335(b *testing.B) {
b.ReportAllocs()
var s struct{}
j := []byte(`{"a":{
}}`)
for n := 0; n < b.N; n++ {
if err := Unmarshal(j, &s); err != nil {
b.Fatal(err)
}
}
} With the hack above:
|
FWIW, I did a little experimentation with this yesterday and found that this input should also showcase the problem:
The newline in the input isn't the significant part, it's the fact that the two closing braces have no whitespace between them. |
Thanks, @potocnyj. You're right. To reproduce, you need both whitespace (newline or space as you have it) as well as the two closing braces next to each other. |
I retracted my change. |
@josharian |
CL https://golang.org/cl/9074 mentions this issue. |
CL https://golang.org/cl/33276 mentions this issue. |
I've got a long running process where
pprof --alloc_objects
reported this:The
encoding/json.(*scanner).error
surprised me and I went digging thinking the process was handling lots of invalid JSON. What I think is going on is the scanner allocates several temporary objects for every JSON value even when the JSON is valid just in case the input stream ends on the next step.stateEndTop
is calling(*scanner).error
which does:and
quoteChar
does:I made a really nasty hack to get rid of the allocations in the common case. I present it in shame:
The text was updated successfully, but these errors were encountered: