Skip to content

feat(xmtp_db): disk-latency benchmark for fresh-DB creation#3824

Open
mkysel wants to merge 2 commits into
mainfrom
bench/db-init-disk-latency
Open

feat(xmtp_db): disk-latency benchmark for fresh-DB creation#3824
mkysel wants to merge 2 commits into
mainfrom
bench/db-init-disk-latency

Conversation

@mkysel

@mkysel mkysel commented Jul 6, 2026

Copy link
Copy Markdown
Contributor

What

Adds an on-demand benchmark that measures libxmtp's fresh-DB creation (the ~63 Diesel migrations run by EncryptedMessageStore::newinit()) as a function of injected per-op disk / fsync latency, to model network-attached storage (e.g. AWS EFS) and quantify how per-account client init scales with it.

Two pieces:

  • crates/xmtp_db/src/latency_vfs.rs — a WAL-compatible SQLite VFS shim (in the style of SQLite's vfstrace.c). It wraps the platform default VFS, delegates every VFS/file method to it, and only adds a configurable thread::sleep on xSync/xWrite/xRead, plus per-op counters. Scoped by filename so only the target DB (and its -wal/-shm/-journal siblings) is slowed. Because SQLCipher is a codec layered above the pager, real I/O still flows through this VFS, so the numbers are representative of the encrypted store. Gated behind a new bench feature, native-only.
  • crates/xmtp_db/benches/db_init_latency.rs — a Criterion bench sweeping injected latency {0,1,5,10} ms/op over a fresh persistent encrypted store, in two scenarios (fsync_latency = xSync only; write_sync_latency = xWrite+xSync).

Run

cargo bench -p xmtp_db --features bench --bench db_init_latency

Result / motivation

A fresh store does ~768 writes but only ~6 fsyncs, so write-op round-trips — not fsync — dominate on high-latency storage:

per-op delay fsync_latency write_sync_latency
0 ms 25 ms 26 ms
1 ms 37 ms 1.36 s
5 ms 77 ms 5.58 s
10 ms 141 ms 10.56 s

At ~5 ms/op this reproduces the ~4 s Fargate/EFS agent-init cost tracked in Linear CON-245. Takeaway for that work: the lever is getting the 768 migration writes off the per-account hot path (pre-migrated template DB), not reducing fsyncs.

Scope / notes

  • No production code changed — the VFS is compiled and registered only under the bench feature.
  • A full-client (Client::create) variant was intentionally left out: it needs a live local backend, and its DB portion is exactly what this DB-layer bench already isolates.
  • Draft: adds criterion as an xmtp_db dev-dep, so cargo hakari generate / a full just lint pass may be needed before marking ready.

Note

Add disk-latency benchmark for EncryptedMessageStore initialization in xmtp_db

  • Adds a Criterion benchmark target db_init_latency (gated by a new bench feature) that measures EncryptedMessageStore creation time across configurable per-op I/O delays (0, 1, 5, 10ms).
  • Implements a custom SQLite VFS wrapper in latency_vfs.rs that intercepts xRead, xWrite, and xSync, injects nanosecond-level delays, counts ops, and scopes injection to files matching a configurable token.
  • The benchmark runs two sweep scenarios (fsync-only and write+sync) and prints one-time I/O op counts as a diagnostic before timed measurements.
  • Risk: calling register() replaces the process-wide default SQLite VFS; this is only reachable under the bench feature on native targets.

Changes since #3824 opened

  • Instrumented latency_vfs module with per-operation timing tracking across all SQLite VFS operations [f4f7096]
  • Added environment variable configuration for benchmark database file base directory [f4f7096]

Macroscope summarized bc55db9.

@claude

claude Bot commented Jul 6, 2026

Copy link
Copy Markdown

Claude encountered an error —— View job


PR Review in Progress

Review Date: 2026-07-07 18:00 UTC

Tasks

  • Read and analyze new benchmark code
  • Read and analyze VFS implementation
  • Review for code quality and potential issues
  • Post final review feedback

@codecov

codecov Bot commented Jul 6, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 84.72%. Comparing base (b86545d) to head (170bc2c).
⚠️ Report is 1 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #3824      +/-   ##
==========================================
+ Coverage   84.70%   84.72%   +0.01%     
==========================================
  Files         409      409              
  Lines       60901    60901              
==========================================
+ Hits        51588    51597       +9     
+ Misses       9313     9304       -9     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@mkysel mkysel marked this pull request as ready for review July 7, 2026 16:33
@mkysel mkysel requested a review from a team as a code owner July 7, 2026 16:33
Add a WAL-compatible SQLite VFS shim (`latency_vfs`, behind a new `bench`
feature, native-only) that wraps the platform default VFS and injects a
configurable per-op delay on xSync/xWrite/xRead, plus op counters. Add a
Criterion bench (`db_init_latency`) that sweeps injected latency over
`EncryptedMessageStore` creation — the ~63 Diesel migrations — to model
network-attached storage (e.g. EFS) and quantify how per-account libxmtp
init scales with disk latency.

Measured: a fresh store does ~768 writes but only ~6 fsyncs, so write-op
round-trips — not fsync — dominate on high-latency storage (write+sync
10ms/op -> ~10.5s vs fsync-only -> ~140ms). Reproduces the ~4s Fargate/EFS
agent-init cost tracked in CON-245.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@mkysel mkysel force-pushed the bench/db-init-disk-latency branch from 170bc2c to bc55db9 Compare July 7, 2026 16:33
macroscopeapp[bot]
macroscopeapp Bot previously approved these changes Jul 7, 2026
@macroscopeapp

macroscopeapp Bot commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Approved

This PR adds benchmark infrastructure behind a feature flag (bench) that is not compiled in production builds. The new latency_vfs module and benchmark are explicitly for testing purposes only, with no impact on runtime behavior.

You can customize Macroscope's approvability policy. Learn more.

Extend the latency VFS to time each delegated real call per op type
(open/sync/truncate/write/close/…) and expose op_times(), so a fresh-store
creation can be attributed to op types on real storage where the injected
model can't. Add an XMTP_BENCH_DIR override so the bench/tests can target a
real mount (Archil/EFS/EBS) at zero injected latency, plus two #[cfg(test)]
diagnostics: per-migration write attribution and per-op-type timing.

On a real Archil mount, metadata + fsync dominate (sync/open/delete/shm/
truncate ~78%), not the 768 writes (~18%) — the opposite of the EFS model.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@macroscopeapp macroscopeapp Bot dismissed their stale review July 7, 2026 17:52

Dismissing prior approval to re-evaluate f4f7096

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