mirror of
https://github.com/nlohmann/json.git
synced 2026-10-25 07:18:55 +00:00
Dump of float tokens of 16 or 17 digits without an exponent (SIMD targets, little-endian), in batches of up to 256 floats ahead of the walk, one loop per step: - the digits (16 bytes at a time) and the token's last four digits; - locate_token(): Eisel-Lemire's product gives the double x, and x's position relative to the token is exact in a 64-bit fixed-point number (56 bits after the point of the token's last digit), with the radius of its interval; - token_digits_1/2(), one loop per kind (g): the multiple of 10^g nearest to x if it is in the interval, else the multiple of 10^(g - 1) nearest to x, the digits that dump() (Zmij) writes. Exact ties between two candidates (like 754570942.33984373, whose double is ...33984375) are left to the full conversion; - the output is the token with its last four digits replaced; a rounding that carries further goes to the writer of Zmij's results. The batch storage is on the heap (allocated by the first conversion), and a pair of floats like [x, y] in a read-only document is written without a frame. Reading: get<double>() converts such tokens with a lean Eisel-Lemire (coordinate_float()). Output is byte-identical to the previous writer: 10^9 generated tokens in one array and 3 * 10^8 in arrays of 1 to 9 elements on Apple M1, 2.5 * 10^8 and 10^8 on x86-64 (all exponents, subnormals, 15-18 digits, exact binary fractions and ties, near-short decimals); get<double>() equals json::parse on 5 * 10^7 values. compare.py --download, Apple M1 Max, clang 21, 30 rounds, two runs (and two with aligned code: -falign-loops=64 -mllvm -align-all-functions=6); json_view, and the factor of yyjson 0.13.0 over it: - canada dump 3636 -> 1623 us (0.47x -> 1.06x; aligned 1.05x) - canada traverse 2287 -> 1817 us (0.85x -> 1.07x; aligned 0.99x) - canada patch 4628 -> 2735 us (0.80x -> 1.36x) - canada update 4763 -> 2911 us (0.78x -> 1.28x) Linux x86-64 (Haswell VPS, GCC 13, one run): canada dump 0.53x -> 0.72x, traverse 0.89x -> 0.95x, patch 1.01x -> 1.17x, update 0.96x -> 1.13x. Open: canada traverse in the aligned build (0.99x) and canada dump on x86-64 (0.72x) are still behind yyjson. Canada parse and select are about 2 % slower in bench_view in both builds, with identical parser code (likely layout; the corpus parse row is not slower). In the plain build only, rpc, status, and twitter dump are 2-4 % slower (0-6 % faster in the aligned build). Signed-off-by: Niels Lohmann <mail@nlohmann.me>