-
Notifications
You must be signed in to change notification settings - Fork 437
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
Simple test case is producing allocations, is this intended? #222
Comments
DOH: Just noticed, a merge just went in that fixes |
Interesting 🤔 This change was part of the code to actually reduce allocations #208 |
Huh, no idea why that fixed things, but you're right, your last released update fixes one of my 4 allocations, the other 3 can be addressed by: For this line of code: The problem is that variable sized allocations can never live on the stack, the standard go pattern for this is:
In your case you could do:
Similarly for: |
PS: Ugh, I missed pIdxFlags, which when changed similarly via :
Brings the allocation count to 0 in my test, all in giving a 10% ish speed bump. |
@xsandr since you were the person who made the previous change, can you help with a review here? Thank you! |
On a semi-related note, for ease of use I wrap the EachKeys function with a helper to do field bindings and costlessly marshal directly to a struct: One side affect of the EachKey interface having a lambda/closure style is that the user provided function cant be inlined, I'd be curious how much difference it would make if rather than invoking a user lamba function per iteration it instead returned a single array of results and let the user iterate. ie
the current EachKey implementation could then call the above one so that external users can still use the lambda function style pattern. I'm sad to report that I cant achieve nearly the same performance as I can with jsoniterator, although with the fixes EachKey having zero allocations is really nice. (ie jsoniterator is roughly 2X faster for my simple benchmark)
See: https://github.com/Villenny/jsonparserHelper-go for my helper module. Note how parser generation is its own step prior to use, this means that you can create the parser once at program init time, so it doesnt matter if it has allocations, which means that you can build lookup maps in it to achieve O(1) mappings. I didnt go so far as to reflect the struct to populate the parser, but that would be fairly easy. IMHO, although its more technically correct to use arrays of keys, storing paths as a single string would allow path lookups in a map trivially, and play nicer with go's escape analysis. Simplest use case for my helper is:
|
I'm not sure if I'm doing something wrong, but I was surprised this produced allocations:
This is happening inside the jsonparser.EachKey function:
The text was updated successfully, but these errors were encountered: