Memory & disk footprint (preliminary)

How much machine does Aito need? On a 10M-row linked-invoice database, the v2 engine stores the same state in 3,258 MB on disk β€” 2.3Γ— less than the v1 engine β€” and holds its working set in 597 MB of JVM heap, 3.8Γ— less than v1 in the configuration measured below.

Read the disk figure as the durable one. It is a property of the on-disk format: the priors A/B measured it as bit-identical with the link-target priors on and off, because those caches are never persisted. The heap figure is the one that decides how many tenants fit on a box, but it moves with configuration, so it is stated here with that configuration attached rather than as a headline ratio. The configuration, and what the served default costs, are in the provenance note under the table.

The measurement

Both engines were pointed at the same optimized 10M-row state, same corpus, same build, each given a 4 GB heap:

Footprintv2 (rep2)v1 (rep1)v1 Γ· v2
On disk3,258 MB7,617 MB2.3Γ—
Memory-mapped3,288 MB7,617 MB2.3Γ—
JVM heap, after GC597 MB2,276 MB3.8Γ—
Off-heap (manually managed)157 MB151 MB1.0Γ—

Provenance. booktest InvoicePerf mem-optimized-10M-rep2 (v2) and mem-optimized-10M (v1) Β· same corpus, same optimized state, same build Β· heap is the live figure after a forced collection, not the JVM's reserved size Β· single dev machine, hardware unspecified. Every cell is a build-time metric token resolved from those committed snapshots β€” including the v1 Γ· v2 column, which is computed from the two totals rather than written down, so a refreshed snapshot cannot leave a stale ratio behind. Nothing here is hand-typed.

Configuration of the v2 heap figure: live heap in a separate server process, read after System.gc(); linked-table priors disabled; production enables them, which the same case measures at about 2.5% more heap. The v1 column: live heap in a separate server process, read after System.gc().

Why the heap stays flat

The off-heap row is the tell. Off-heap is near-identical between the engines because it is a fixed working area rather than a per-row structure β€” so it does not move with the corpus. Heap, mapped and disk all do. That is the shape you would predict from the design, and it is what makes the heap figure a property of the architecture rather than a lucky measurement:

  • Memory-mapped, zero-allocation reads β€” a lookup reads straight out of the mapped column file, not a heap-materialized structure. The operating system's page cache, not the JVM heap, holds the dataset.
  • Compact on disk β€” a binary columnar format with adaptive byte widths, so the linkage and column layout stay smaller than a naΓ―ve fixed-width layout. Mapped and on-disk track each other because the mapped set is essentially the state's own files.
  • Cheaper to build β€” rebuilding a table's optimized state streams through the columnar writer rather than materializing the whole table on the heap.

Put together: v2 keeps the dataset in mapped column files and reserves the heap for query-sized aggregates, so the heap does not grow with the corpus the way a row-oriented engine's does.

What this does not yet say

It is one scale, not a curve. The table above is measured at 10M rows only. The claim that heap stays flat as the corpus grows rests on the mechanism plus this single point β€” not on a measured slope. A footprint ladder across 1k / 10k / 100k / 1M / 10M for both engines is the obvious next measurement, and until it exists, read the gap in the table as "the gap at 10M" rather than "the gap at any size."

It is the read path. These figures are a server answering queries from an optimized state. Peak memory during ingest and optimize is a different measurement with a different profile, and is not on this page.

The v2 column has one production default switched off, and the cost of that is now measured. Linked-table priors are enabled by default in a served database and disabled in the benchmark arm that produced this column. They are caches that live as long as the database object, so they can only add heap β€” and re-running the same case with them enabled, at the same pinned -Xmx, adds a little over two per cent. The engine ratio therefore moves by a rounding step rather than collapsing, and the on-disk and memory-mapped columns are unaffected because priors are never persisted. What this column still is not: a ladder (see above), or a measurement under write load.

Hardware is unspecified. Single dev machine. The ratio between the two columns is the durable signal; the absolute megabytes depend on the box.

A note on this section's history, kept deliberately. Earlier drafts carried "~2.6Γ— smaller / ~6Γ— less memory" ratios that were not backed by a committed measurement β€” they traced to a since-removed seed file and a blog draft β€” and were pulled rather than published as if generated. The table above is the replacement, and the hand-typed pair was wrong in both directions β€” see the v1 Γ· v2 column for what the snapshots actually say. Those cells are now computed from the two totals for the same reason: a ratio written into prose cannot be re-derived when the measurement is refreshed.