Skip to content

Commit aeb0e0e

Browse files
committed
parser.c: Optimize json_parse_digits
We can use `ctz` builtin to get the number of consecutive digits. ``` == Parsing float parsing (2251051 bytes) ruby 3.4.6 (2025-09-16 revision dbd83256b1) +YJIT +PRISM [arm64-darwin24] Warming up -------------------------------------- after 25.000 i/100ms Calculating ------------------------------------- after 231.963 (± 0.0%) i/s (4.31 ms/i) - 1.175k in 5.065467s Comparison: before: 215.3 i/s after: 232.0 i/s - 1.08x faster ```
1 parent acbf40b commit aeb0e0e

File tree

1 file changed

+11
-4
lines changed

1 file changed

+11
-4
lines changed

ext/json/ext/parser/parser.c

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1094,20 +1094,27 @@ static inline int json_parse_digits(JSON_ParserState *state, uint64_t *accumulat
10941094
// From: https://github.com/simdjson/simdjson/blob/32b301893c13d058095a07d9868edaaa42ee07aa/include/simdjson/generic/numberparsing.h#L333
10951095
// Branchless version of: http://0x80.pl/articles/swar-digits-validate.html
10961096
uint64_t match = (next_8bytes & 0xF0F0F0F0F0F0F0F0) | (((next_8bytes + 0x0606060606060606) & 0xF0F0F0F0F0F0F0F0) >> 4);
1097+
size_t consecutive_digits = trailing_zeros64(match ^ 0x3333333333333333) / CHAR_BIT;
10971098

1098-
if (match == 0x3333333333333333) { // 8 consecutive digits
1099+
if (consecutive_digits == 8) {
10991100
*accumulator = (*accumulator * 100000000) + decode_8digits_unrolled(next_8bytes);
11001101
state->cursor += 8;
11011102
continue;
11021103
}
11031104

1104-
if ((match & 0xFFFFFFFF) == 0x33333333) { // 4 consecutive digits
1105+
if (consecutive_digits >= 4) {
11051106
*accumulator = (*accumulator * 10000) + decode_4digits_unrolled((uint32_t)next_8bytes);
11061107
state->cursor += 4;
1107-
break;
1108+
consecutive_digits -= 4;
1109+
}
1110+
1111+
while (consecutive_digits) {
1112+
*accumulator = *accumulator * 10 + (*state->cursor - '0');
1113+
consecutive_digits--;
1114+
state->cursor++;
11081115
}
11091116

1110-
break;
1117+
return (int)(state->cursor - start);
11111118
}
11121119
#endif
11131120

0 commit comments

Comments
 (0)