mirror of
https://github.com/nlohmann/json.git
synced 2026-10-22 22:08:55 +00:00
A streambuf without a get area - std::cin synchronized with stdio, or a custom unbuffered streambuf - hands out every character from uflow(). #5828 made this path slower than before it (CITM from an unbuffered streambuf: 889M -> 1205M instructions on macOS with JSON_DISABLE_STREAM_BULK_SCAN as the reference), because every character went through the generic refill code of get_character(). Once the adapter has seen that there is no get area, it calls uflow() directly (the get area is known to be exhausted, which is all sbumpc() checks) and copies the character into the token carried by the adapter. The carried token is now a small buffer class that appends with a compare and a store (a std::vector<char>::push_back from this function needed a stack protector canary and a spill on Linux). A get area that appears later is picked up again; a new test serves the first characters without one. Instructions, unbuffered streambuf, relative to the previous commit (develop; JSON_DISABLE_STREAM_BULK_SCAN) on macOS, 5 parses: CITM 1246M -> 960M (1205M; 889M), twitter 556M -> 451M (535M; 410M), canada 2236M -> 1847M (2188M; 1824M); std::cin synchronized with stdio, one parse: CITM 784M -> 727M (776M; 713M), twitter 312M -> 292M (309M; 283M), canada 1142M -> 1067M (1135M; 1062M). Linux Ir (GCC / Clang), one parse: CITM 218.9M / 298.5M -> 185.6M / 219.9M (207.5M / 284.2M; 160.0M / 211.3M), twitter 99.2M / 127.6M -> 87.0M / 98.6M (95.3M / 122.8M; 78.7M / 91.3M), canada 425.7M / 475.1M -> 380.4M / 372.2M (411.7M / 463.4M; 365.9M / 378.8M). Unbuffered input stays slower than with JSON_DISABLE_STREAM_BULK_SCAN: macOS +8 % (CITM) / +10 % (twitter) / +1 % (canada), GCC +16 % / +11 % / +4 %, Clang +4 % / +8 % / -2 % (canada) - every character is still a call plus the virtual uflow(). Signed-off-by: Niels Lohmann <mail@nlohmann.me>