Repository navigation
ci(bench): measure the incremental benchmark as a production bundle - #2379
Conversation
The benchmark imported db's source through tsx, so it measured development-mode code: unmangled private members, NODE_ENV checks and development-only branches that every production app strips. A new runner, scripts/bench/production.mjs, bundles the benchmark against the built db and db-ivm dist with esbuild, minified, with process.env.NODE_ENV set to production, as the size scenarios do. It refuses a dist older than its package's sources. CI builds both packages on each side and runs the bundle. Co-authored-by: Isaac <no-reply@databricks.com>
|
|
No actionable comments were generated in the recent review. Walkthrough
Merge Risk:
|
|
Size Change: 0 B Total Size: 199 kB ℹ️ View Unchanged
|
Incremental update benchmarkComparing Overall median write time vs base: 1.08× · cold hydrate time: 1.06× (geometric mean of per-case ratios; lower is faster). Writes: 1 regression(s), 0 improvement(s) (threshold: ±20% and >0.05ms). Cold hydrate: 0 regression(s), 1 improvement(s) (threshold: ±50% and >5ms). CI regression gate: PASS. Query geometric means: >+30% writes or >+50% cold. A case also fails when every repetition exceeds the entire base range by >+50% and the metric's absolute floor. Per-case flags are noisy on shared runners. Read the geometric means first. Writes
Cold hydrate
Each row aggregates that query's scale/index/write-mode configurations; per-configuration tables below. 100 rows/collection | source indexes: none | synced writes — geomean 1.35×, cold 1.24×
100 rows/collection | source indexes: none | optimistic writes — geomean 1.24×, cold 1.03×, 1 change(s)
100 rows/collection | source indexes: manual | synced writes — geomean 0.97×, cold 1.11×
100 rows/collection | source indexes: manual | optimistic writes — geomean 1.15×, cold 1.22×
1,000 rows/collection | source indexes: none | synced writes — geomean 1.04×, cold 1.07×
1,000 rows/collection | source indexes: none | optimistic writes — geomean 1.07×, cold 1.13×
1,000 rows/collection | source indexes: manual | synced writes — geomean 1.03×, cold 1.24×
1,000 rows/collection | source indexes: manual | optimistic writes — geomean 1.06×, cold 1.08×
10,000 rows/collection | source indexes: none | synced writes — geomean 0.99×, cold 1.03×
10,000 rows/collection | source indexes: none | optimistic writes — geomean 1.03×, cold 0.98×
10,000 rows/collection | source indexes: manual | synced writes — geomean 1.05×, cold 0.80×, 1 change(s)
10,000 rows/collection | source indexes: manual | optimistic writes — geomean 1.04×, cold 0.93×
Runner: node v24.8.0, linux 7.0.0-1017-azure, AMD EPYC 9V45 96-Core Processor. Timings on shared CI runners are noisy; treat small deltas as indicative only. |
More templates
@tanstack/angular-db
@tanstack/browser-db-sqlite-persistence
@tanstack/capacitor-db-sqlite-persistence
@tanstack/cloudflare-durable-objects-db-sqlite-persistence
@tanstack/convex-db-collection
@tanstack/db
@tanstack/db-ivm
@tanstack/db-sqlite-persistence-core
@tanstack/electric-db-collection
@tanstack/electron-db-sqlite-persistence
@tanstack/expo-db-sqlite-persistence
@tanstack/node-db-sqlite-persistence
@tanstack/offline-transactions
@tanstack/powersync-db-collection
@tanstack/preact-db
@tanstack/query-db-collection
@tanstack/react-db
@tanstack/react-native-db-sqlite-persistence
@tanstack/react-router-with-db
@tanstack/rxdb-db-collection
@tanstack/solid-db
@tanstack/svelte-db
@tanstack/tauri-db-sqlite-persistence
@tanstack/trailbase-db-collection
@tanstack/vue-db
commit: |
Review fixes for the production benchmark runner: - The runner fails when esbuild's metafile lists any packages/*/src input. Before, a second import of db source bundled a development copy of db beside its dist without notice (a planted import of packages/db/src/collection/index.js ran to exit 0; it now fails and names the source files). - The bundle carries an inline source map, and the runner enables source maps before it imports the bundle, so a failed assertion names its line in incremental-update.ts. The bundle directory uses the real temp path, because macOS's /var symlink offset the map's relative paths. - Both freshness checks run before the bundle directory is created. - The base step also takes the freshness helper from the PR head, so both sides run the same runner code. Co-authored-by: Isaac <no-reply@databricks.com>
…ade #2374) Conflicts resolved as the standing rule says: main's tooling, with this branch's oracle changes reapplied. - package.json, packages/db/package.json: main's dependency versions, plus the @tanstack/oracles and @tanstack/eslint-plugin-oracles previews. fast-check stays at ^4.10.2 here and in db-adapter-conformance. - packages/db-ivm/vite.config.ts: main's publishableModuleOutput build output, plus the stripOracleProbes() plugin. - electric-sdk-delivery-oracle: main's resume-checkpoint check and model, plus this branch's owns entry. - solid-db row-materialization-oracle: main's keyed visibility histories, plus this branch's case route. - pnpm-lock.yaml: resolved from the public registry by a temporary CI job (run 42653737079, which also checked a frozen install), because the local registry proxy does not yet carry #2374's versions. Co-authored-by: Isaac <no-reply@databricks.com>
🎯 Changes
The incremental update benchmark now measures TanStack DB as a production app runs it. Before this change, the benchmark imported db's source through
tsx. It therefore measured development-mode code that every production build removes:process.env.NODE_ENVchecks, development-only branches, and private members without their mangled names.scripts/bench/production.mjs, bundles a benchmark with esbuild against the builtdistof db and db-ivm. The bundle is minified, andprocess.env.NODE_ENVis set toproduction. These are the settings that the size scenarios inscripts/size-compare.mjsuse.distthat is older than its package's sources. It also fails if the bundle includes any module from a package'ssrc, so a benchmark cannot measure a development copy of a package beside itsdist.incremental-update.ts.tscrun does not change.The maintainer asked for this change on 2026-11-09. The trigger was #2378: it flagged 5 writes in 100-row configurations. Those writes ran development-only state probes that a production bundle removes.
Verification
packages/db/distand 28 files frompackages/db-ivm/dist. It has no inputs fromsrc, and the output contains noNODE_ENVreads.scripts/bench/incremental-update.ts:1:7.node --test scripts/bench/inputs-changed.test.mjs scripts/bench/compare-incremental-update.test.mjs: 22 of 22 pass.Limits
node_moduleswithout a bundler run code that this benchmark does not measure.✅ Checklist
pnpm test. I ran the benchmark's own tests and the bundled benchmark.🚀 Release Impact
This pull request and its description were written by Isaac.
Summary by CodeRabbit