-
-
Notifications
You must be signed in to change notification settings - Fork 6.8k
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
Performance in miloyip/nativejson-benchmark #202
Comments
Thanks for the results! I'll check them with OSX. Here are some thoughts:
|
It might be interesting to compare performance of using the default std::map with using std::unordered_map, and the boost flat equivalents. |
I think unordered map would be a good alternative for users doing mainly sequential access and just parse/dump type access. I definitely think there is value in doing that. Boost however... definitely not. I think we are better off avoiding external dependencies - especially a behemoth like Boost. Or do you just mean implementing something like Boost, but without actually using Boost. @nlohmann, with regard to floating point - I also think it is worthwhile, both for parsing and dumping - but it is going to bloat the code considerably. The two things that I consider most important about the library are that it remains single header and that it retains its ease of use. Performance to me seems a distant third - anyone who wants raw performance over ease of use is probably going to go for rapidJSON or one of the c libraries anyway. |
I just mean testing it in the benchmark to see what the perfromance differences are, since the class has the ability to specify the class used for objects. It could give insight into the performance differences and those could be documented for users that need the performance. |
Ah, I thought that issue had been resolved. |
Not really. The first fix would break the allocator stuff. (And there is another issue that this part is also flawed...) |
I adjusted the code to make a test with
|
Could be lots of hash collisions. I would expect better performance on lookups, but not much change elsewhere. The flat containers from boost might only help in the memory usage and output, insertion may be worse. |
I have done some profiling and optimizations on
It seems that some C++ standard library are improving their routines in these few years. So it may just get improved in the future. We have faced a locale issue in the past, where the JSON is written as incorrect JSON number format. Doing For the object stoarge/query issue, we have made some discussion Tencent/rapidjson#102. However, we did not come to an conclusion for this. |
Here is the results of testing 1.1.0, 2.0.0 and my proposed changes to 2.0.0 under miloyip/nativejson-benchmark Results.zip.
Here is my (possibly naive) interpretation:
Parse
Our lexer looks to be pretty good and parsing of strings is about as good as it could be. Some further improvements could be made in number parsing by incorporating custom floating point parsing into the proposed
get_integer()
in lieu ofstrtof()
/strtod()
/strtold()
but this would greatly increase code complexity and the improvements would likely be marginal at best.Looking at the other libraries results (especially the ones with fast parsing) it looks like allocations are what is killing us. The other thing that might be killing us is the use of map. This is not ideal for parsing a large unordered file because the tree will be continually re-balanced. The benefit of using a map is lookup, but that isn't really tested in this benchmark as the timed access is all sequential.
Note that I'm not saying we should be moving away from map, because our library is really designed around using the json object to store data, not merely to parse/dump json files. We probably just have to accept that our parse is always going to be slower.
Stringify
The proposed change to
snprintf()
for floating point stringifying highlights just how badstringstream
s are for this. There may be further improvements by reducing our reliance onstringstream
s elsewhere but this would come at the expense of c++ style. I did try usingsnprintf()
for integers, and even a very efficient custom function I've used before on microcontrollers, but didn't achieve any significant improvement so perhaps the issue is only manifest for floating point numbers.The other thing here is that use of map is probably not as fast for sequential dumping as other container types. I think this is just a price we have to pay.
Time
This test simply iterates through the document while collecting statistics about number of strings, numbers, objects, arrays etc. Any difference between library versions is an anomaly as there are no significant differences (only the bitfield overhead for the proposed changes). Because this test is sequential we are at a disadvantage using maps.
The bottom line seems to be that a choice must be made - do we optimize for rapid parsing/dumping/sequential access at the expense of lookup, or do we optimize for lookup and accept that parsing/dumping/sequential access will always be a little slower (but not that much).
@nlohmann, if you are able to run similar tests under Linux/OSX that would help to make sure this isn't just a VS2015 issue.
The text was updated successfully, but these errors were encountered: