Skip to content

Feat tape#32

Open
SunDoge wants to merge 5 commits into
masterfrom
feat-tape
Open

Feat tape#32
SunDoge wants to merge 5 commits into
masterfrom
feat-tape

Conversation

@SunDoge

@SunDoge SunDoge commented Jul 8, 2026

Copy link
Copy Markdown
Owner

No description provided.

huangdeng and others added 5 commits July 8, 2026 12:17
Performance: add fat LTO + codegen-units=1 on release/bench profiles,
inline the tape accessors and deserialize_value, and dispatch on the raw
tape tag byte instead of an Option<TapeType> round-trip. Large-100KB
struct path ~24% faster, value path ~12% faster; value path now beats
serde_json::Value on large inputs.

Add opt-in `native` feature (off by default) that compiles the bundled
simdjson C++ with -march=native; ship .cargo/config.toml.example for the
matching Rust target-cpu=native, gitignoring the local copy so published
builds stay portable.

Breaking: replace the single tape::Error::TapeCorrupted { message } with
typed variants (OutOfBounds, UnknownTapeType, UnexpectedTapeType,
StringOutOfBounds, MissingValueWord, InvalidUtf8) carrying positions and
lengths. serde::Error::TapeCorrupted is removed; tape failures now
surface transparently as serde::Error::Tape { source: tape::Error }.
Use ensure! for same-type checks in tape.rs; .build().into() across the
serde boundary. Also fixes stale serde_support doctest paths.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Perf-profiled the Large struct deserialization path and attacked the two
biggest user-space hotspots:

- get_string called str::from_utf8 on every string node (~11% of CPU),
  re-validating UTF-8 that simdjson already checked during stage2. Replace
  with from_utf8_unchecked under a documented SAFETY invariant: a tape is
  only reachable after parser_parse returned success, which means the
  string_buf is valid UTF-8.
- Vec fields deserialized with no size hint, so serde grew them element by
  element (~27% in malloc/realloc). Add TapeRef::scope_count reading the
  24-bit element count simdjson packs into the opening bracket tape word,
  and surface it via TapeSeqAccess::size_hint so serde preallocates with
  Vec::with_capacity (capped by serde's cautious hint).

Large-100KB struct: 183 us -> 137 us (-25%), now beating simd-json (176 us)
and serde_json (187 us). Medium-2KB: 840 ns -> 638 ns. from_utf8 is gone
from the profile; _int_malloc and grow_one dropped sharply.

Also add simd-json as a dev-dependency bench competitor (struct path only,
three sizes) and a throwaway examples/perf_sample.rs for perf-record
sampling of the hot loop.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant