mirror of
https://github.com/nlohmann/json.git
synced 2026-09-06 16:27:59 +00:00
Fix codegen regression in skip_whitespace() from #5490
Benchmarking found the get()/get_ignoring_pending_unget() split in skip_whitespace() made long whitespace runs (e.g. indentation in pretty-printed JSON) 1.75x-3.2x SLOWER instead of faster, reproducible with both Apple Clang and GCC. Root cause: rewriting the loop from a plain do-while into an initial get() followed by a while-loop defeated the compiler's ability to keep the input adapter's read/end pointers in registers across iterations; both compilers instead reloaded them from memory on every character. The function split itself was not the problem (it still fully inlines); the loop's control-flow shape was. The fix keeps the same two-function structure but restores a do-while shape (guarded by an if for the "first char not whitespace" case), which lets both compilers hoist the pointers back into registers, matching or beating pre-#5490 performance. Signed-off-by: Niels Lohmann <mail@nlohmann.me>
This commit is contained in:
@@ -9488,9 +9488,20 @@ scan_number_done:
|
||||
// nothing below calls unget()
|
||||
get();
|
||||
|
||||
while (current == ' ' || current == '\t' || current == '\n' || current == '\r')
|
||||
// this is written as an if-guarded do-while (rather than a plain
|
||||
// while loop) because that shape is what lets both GCC and Clang
|
||||
// keep the input adapter's read pointer in a register across
|
||||
// iterations; the equivalent while-loop measurably defeated that
|
||||
// optimization in testing, turning long whitespace runs (e.g. the
|
||||
// indentation of pretty-printed JSON) from a register-only loop
|
||||
// into one that reloads the pointer from memory every character
|
||||
if (current == ' ' || current == '\t' || current == '\n' || current == '\r')
|
||||
{
|
||||
get_ignoring_pending_unget();
|
||||
do
|
||||
{
|
||||
get_ignoring_pending_unget();
|
||||
}
|
||||
while (current == ' ' || current == '\t' || current == '\n' || current == '\r');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user