Files
simdjson-simdjson/include/simdjson
Francisco Geiman Thiesen 42c047a927 builder: position-as-local writer for reflection serializer (#2708)
The dominant cost in the reflection serializer was the strict-aliasing
reload pattern: every char* write through `string_builder::buffer.get()`
forced the compiler to assume `string_builder::position` and `::capacity`
may have been clobbered, so it reloaded both members from memory after
each byte. perf annotate showed `ldr [position]` and `ldr [capacity]`
taking 15-20% of CITM serialization time.

This change refactors the reflection atom path to use an internal
`writer` struct (buffer pointer + position + capacity + back-ref to
string_builder). The writer lives as a stack-local in the top-level
append() entry point, threaded through the inlined atom() chain via
`writer&`. After SROA, the three fields are register-resident across
the entire serialization. The `pos` is never round-tripped through
memory between writes — it's a local size_t.

This mirrors the pattern Glaze uses (passing `B&& b, auto&& ix` through
every helper). The simdjson-specific bit is keeping the public
string_builder API intact: only the internal atom() family is
refactored to take `writer&`. The top-level append(string_builder&, T)
constructs a writer on the stack, threads it through atom(), then
syncs the local position back at the end.

For string fields specifically, the escape path is also inlined
through the writer — the existing `write_string_escaped(input, out)`
helper already takes a destination pointer and returns bytes-written,
so it composes cleanly with `w.ptr + w.pos`. Without this, sync/
reload around each string write was a real cost on Twitter (-7%).

Performance
===========

TRUE A/B in single docker invocation, 7 alternating rounds, byte-
identical output, all static_reflection_comprehensive_tests pass.
Build: clang-p2996 21.0.0git, -O3 -DNDEBUG, aarch64 Linux.

CITM Catalog (496 682 bytes):
  baseline (master): 4356 MB/s
  patched:           6776 MB/s   +55.5%
  Glaze:             4860 MB/s   simdjson now 39.4% AHEAD of Glaze

Twitter (81 927 bytes):
  baseline (master): 6437 MB/s
  patched:           6452 MB/s   +0.2% (break-even)
  Twitter is string-heavy; the writer's gain over the existing
  member-based path is small here, but it no longer regresses.

Default initial capacity is unchanged at 1024.
2026-05-07 13:28:03 -04:00
..
2026-01-21 10:13:50 -05:00
2026-01-21 10:13:50 -05:00
2026-01-21 10:13:50 -05:00
2026-01-21 10:13:50 -05:00
2026-01-21 10:13:50 -05:00
2026-01-21 10:13:50 -05:00
2026-01-21 10:13:50 -05:00
2026-01-21 10:13:50 -05:00
2026-01-21 10:13:50 -05:00
2023-07-16 19:18:58 -07:00
2026-04-11 14:16:43 -04:00
2026-01-21 10:13:50 -05:00
2026-04-30 21:59:36 -04:00
2026-04-30 21:59:36 -04:00
2023-07-16 19:18:58 -07:00
2023-07-16 19:18:58 -07:00
2023-07-16 19:18:58 -07:00
2025-07-14 15:55:00 -04:00
2023-07-14 20:05:05 -07:00
2023-07-16 19:18:58 -07:00
2026-01-21 10:13:50 -05:00
2026-04-03 15:26:12 -04:00
2024-02-23 16:50:55 -05:00
2023-07-16 19:18:58 -07:00