Skip to content

perf(zero-rust): store a row's columns by its table's layout - #172

Merged
tmm merged 2 commits into
mainfrom
rust-row-layout
Nov 11, 2026
Merged

tmm merged 2 commits into
mainfrom
rust-row-layout

Conversation

@tmm

@tmm tmm commented Nov 11, 2026

Copy link
Copy Markdown
Member

Large views, as the Space goal asks: store a row's columns by its table's layout instead of a per-row copy of every column name.

  • A json::Object keeps its keys apart from its values (Arc<Keys> + Arc<[Value]>), and the rows of a table share one key list, their layout. This is the Rust counterpart of Swift keying rows by column index and of JS hidden classes.
  • The parser follows a recent object's keys while the next object has the same ones, comparing raw key bytes, so a synced row allocates neither its key strings nor their list. On a mismatch it switches to a recent layout with the same keys so far, so tables that share a first column (id) still share.
  • The poke handler and mutators put rows in their table's layout (Layouts, shared by a branch and its forks).
  • Comparators and filters remember where their column was (get_hinted), and check the key there before using it.

Public API is unchanged: Object and OrderedMap keep their methods, and the new ones are pub(crate).

Numbers (medians of 3 interleaved runs on one 8-core Xeon orb)

Rust before Rust after Swift (same machine) JS
memory, 100k rows + view 181 MB 83 MB 127 MB 239 MB
materialize 10k rows 678 µs 565 µs 863 µs 2.06 ms
materialize 100k rows 20.9 ms 10.5 ms 16.8 ms 30.1 ms
100k rows as structs 48.3 ms 23.8 ms 37.4 ms
poke of 1000 rows 7.74 ms 5.01 ms 10.8 ms
first sync, issue list 17.0 ms 15.3 ms 42.9 ms
poke of 1 row 11.4 µs 12.4 µs 49.1 µs
optimistic update 15.3 µs 15.9 µs 39.5 µs 274 µs

At 100k rows, the cost per row compared with 10k went from 3.1× to 1.9×, about Swift's 2.0× on the same machine. It doesn't scale linearly yet.

Caveat: swift/BENCHMARKS.md's Linux column has Swift 2–3× faster than it ran here (7.07 ms for 100k rows), while JS ran exactly as fast as documented. Against that column, Rust is behind Swift at 100k rows (10.5 vs 7.07 ms) and level on structs (23.8 vs 24.8 ms). It's written up in rust/BENCHMARKS.md.

Small costs: a 1-row poke is about 1 µs slower, because sharing a row's layout compares its column names. pk = N, an optimistic update and a round trip are 3–4% slower. A table's layout is one stored row per table. Locally inserted rows whose column order differs from the server's switch the layout back and forth: results stay correct, and those rows share less.

Checks

  • Conformance: 63,453 cases, 0 failures, 2,255 under documented exceptions (unchanged).
  • Locally: fmt, clippy -D warnings, workspace tests, docs with -D warnings, and MSRV 1.88 all pass.
  • New unit test: parsed objects with equal keys share them. It covers shorter, longer and reordered objects, a repeated key, an escaped key equal to a raw one, and integer-like keys.

Adds a zero-rust patch changeset. Releasing it needs tmm.

Amp-Thread-ID: https://ampcode.com/threads/T-01a1c6b9-fc99-73a1-bf70-e71fd484042c

ampagent and others added 2 commits November 11, 2026 22:45
A json::Object keeps its keys apart from its values, in a list that the
rows of a table share (their layout), as Swift keys rows by column index
and JS engines share hidden classes. The parser follows a recent object's
keys while the next object has the same ones, so a synced row allocates
neither its keys nor their list; the poke handler and mutators put rows
in their table's layout. Comparators and filters remember where their
column was, so they find it without searching the names.

Conformance is unchanged: 63,453 cases, 0 failures.

Amp-Thread-ID: https://ampcode.com/threads/T-01a1c6b9-fc99-73a1-bf70-e71fd484042c
Co-authored-by: tmm <tmm@tmm.dev>
Rust, Swift, and JS measured on one machine, with a zero-rust patch
changeset.

Amp-Thread-ID: https://ampcode.com/threads/T-01a1c6b9-fc99-73a1-bf70-e71fd484042c
Co-authored-by: tmm <tmm@tmm.dev>
@tmm
tmm merged commit c5317d6 into main Nov 11, 2026
18 checks passed
@tmm
tmm deleted the rust-row-layout branch November 11, 2026 22:58
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.

2 participants