Skip to content

perf(storage): reuse Usage range statistics across filter changes - #5517

Open
liuxiaocs7 wants to merge 1 commit into
apache:mainfrom
liuxiaocs7:perf/usage-range-statistics-cache
Open

liuxiaocs7 wants to merge 1 commit into
apache:mainfrom
liuxiaocs7:perf/usage-range-statistics-cache

Conversation

@liuxiaocs7

Copy link
Copy Markdown
Member

Summary

Changing only Usage activity search/status currently repeats complete range statistics. Keep one statistics projection in the existing Storage reader, keyed by its lifecycle-aware Usage revision and exact from/to. Reuse summary, provider/model/tool groups, pricing and provenance while reading the revision, activity count and page in one transaction. Publish cache misses after the outermost commit; clone every response before Host identity projection/freezing.

The deterministic facade regression drops repeated aggregate statements from 5 to 0. With 50,000 tool records, a search edit falls from 245.577 to 143.732 ms median on Node and 260.273 to 160.015 ms on Electron. This branch starts directly from main 0117d76c5688475e7467ee6db83057bf65edbabd; it complements #5514's pagination/count work and #5410's frontend work.

Fixes #5516
Refs #5038

Verification

  • Full production build, typecheck, lint and Knip for Desktop/UI passed. Tracked-file formatting and a clean-checkout ASF header audit passed. Whole-directory format/header commands flag only preexisting untracked research artifacts outside this PR.
  • Storage Usage 31/31 and Host Usage 6/6 passed on Node; the combined 37/37 passed on Electron. Full Storage: 1,413 passed, 8 skipped, with NODE_OPTIONS=--disable-warning=ExperimentalWarning.
  • Red/mutation evidence: the baseline repeats 5 aggregates after a filter edit; publishing before commit exposes a rolled-back tool name after revision reuse; removing the response clone leaks mutated statistics. Each corresponding regression failed against that faulty implementation.
  • Automated Standards and Spec reviews found 0 issues at e8960e1d59ae2ac223111ef0bab3f87a7559ab98. These do not replace independent human review.
  • Full npm test was attempted and is not green. Storage's child-stderr assertion rejects Node's SQLite experimental warning, and a Host implementation-child-patch case times out; both reproduce in the main checkout. Three other Host lifecycle failures and one Eval deadline failure passed focused reruns. Eval's Python tests passed separately on Python 3.12 (75 passed, 12 skipped); the default macOS Python 3.9 cannot import the existing union annotations. Baseline comparisons reuse installed third-party dependencies and source-identical dependency build artifacts.

Performance evidence

Cache behavior, reproducible measurements and integration notes

Reproduce

Build Core and Storage at the baseline and this PR commit, then run from this checkout:

MAKA_PERF_OUTPUT=/tmp/usage-statistics-node node scripts/perf/usage-statistics.mjs /path/to/built-baseline-checkout

On macOS, also exercise the shipped SQLite runtime:

ELECTRON_RUN_AS_NODE=1 MAKA_PERF_OUTPUT=/tmp/usage-statistics-electron node_modules/electron/dist/Electron.app/Contents/MacOS/Electron scripts/perf/usage-statistics.mjs /path/to/built-baseline-checkout

Both versions call the real readUsageScreen facade against the same persisted temporary database with separate reader connections. Each case alternates before/after order in one process, uses 3 warmups and 15 samples, and checks complete result equality excluding the opaque revision. Untimed preparation loads the original range before a timed search/status change; changing the range or committing a real tool update measures misses. Fixture writes, equality assertions and SQL probes are outside timing. The harness saves raw samples, median/p95, environment, revisions and executed SQL.

Fixtures contain 1k/10k/50k tool records or 50k mixed canonical/legacy/tool records, with bounded groups (20 models, 10 connections, 8 tools). These are synthetic local facade measurements; they exclude Host repair, wire serialization, IPC/network and rendering. No cold OS cache, physical row-visit or fixed-byte cache-size claim is made.

Results

Measured on 2026-09-20 against main 0117d76c5688475e7467ee6db83057bf65edbabd and this PR commit e8960e1d59ae2ac223111ef0bab3f87a7559ab98, with a clean tracked working tree. Machine: Apple M4 Pro, macOS/arm64, 24 GiB RAM. Node v24.14.0 / SQLite 3.51.2; Electron 43.4.1 (Node v24.18.1) / SQLite 3.53.1. Each cell is median / p95, with nearest-rank p95 over 15 samples. These local results are not production latency guarantees.

Runtime and fixture Operation Before (ms) After (ms)
Node, 1,000 tools Matching search 5.808 / 6.213 4.335 / 4.558
Node, 10,000 tools Matching search 55.441 / 62.354 36.147 / 38.073
Node, 50,000 tools Matching search 245.577 / 296.783 143.732 / 191.835
Node, 50,000 tools No-match search 234.871 / 277.539 113.099 / 181.333
Node, 50,000 tools Status change 150.392 / 216.640 62.357 / 75.253
Node, 50,000 tools Range change (miss) 197.629 / 208.490 199.070 / 216.563
Node, 50,000 tools Revision change (miss) 191.947 / 205.062 194.262 / 219.701
Node, 50,000 mixed Matching search 342.239 / 394.036 160.298 / 177.748
Node, 50,000 mixed No-match search 268.992 / 312.845 105.039 / 138.595
Node, 50,000 mixed Status change 226.461 / 234.271 52.979 / 77.121
Node, 50,000 mixed Range change (miss) 300.930 / 340.411 294.346 / 343.591
Node, 50,000 mixed Revision change (miss) 294.417 / 342.441 292.485 / 324.094
Electron, 1,000 tools Matching search 6.242 / 11.027 4.796 / 6.593
Electron, 10,000 tools Matching search 57.178 / 62.593 37.864 / 45.240
Electron, 50,000 tools Matching search 260.273 / 290.907 160.015 / 196.316
Electron, 50,000 tools No-match search 237.611 / 301.183 155.324 / 162.436
Electron, 50,000 tools Status change 156.098 / 173.165 66.140 / 95.861
Electron, 50,000 tools Range change (miss) 212.076 / 226.465 208.804 / 250.361
Electron, 50,000 tools Revision change (miss) 207.731 / 225.815 205.941 / 242.104
Electron, 50,000 mixed Matching search 371.686 / 403.365 186.346 / 198.543
Electron, 50,000 mixed No-match search 286.805 / 343.087 99.376 / 184.096
Electron, 50,000 mixed Status change 249.276 / 263.124 58.585 / 77.759
Electron, 50,000 mixed Range change (miss) 308.200 / 419.422 306.434 / 345.697
Electron, 50,000 mixed Revision change (miss) 312.039 / 377.019 319.205 / 472.248

All search SQL probes report 5 aggregate statements before, 0 after: the model summary, three breakdown queries and unreadable-checkpoint SUM are skipped on a hit, along with pricing/provenance reads. This counts statements, not physical row visits. Both range-boundary and data-revision changes still recompute statistics; their timings show the remaining miss cost. Miss tail latency is variable: the Electron mixed-source revision-change p95 is 377.019 ms before and 472.248 ms after in this 15-sample run, so these results do not establish a miss-tail improvement.

Correctness and limits

The cache retains one count-bounded complete statistics projection, not an activity page or history array. Search and status do not participate in the statistics key. A range/revision miss still runs the original SQL; data/pricing/repair changes and reader close/reopen invalidate reuse. Storage group/pricing capacity failures are not cached. Public-facade tests cover rollback with counter reuse, response mutation/freezing, inclusive/empty ranges, corrections/deletion, pricing, projection repair, capacity recovery, concurrent WAL commits and separate roots. A real Host test verifies frozen replies and replacement-coordinator revisions.

Continuous Usage writes change the global revision and may prevent cache hits. First-range aggregation, exact activity counts and substring searches retain their range-sized costs; this PR leaves main's activity SQL intact. The cache is count-bounded rather than separately byte-bounded, and existing Host response-size checks still apply.

Composition with other Usage PRs

#5514 at 9bdfd1f51398f86edb2e2511c1d8ba1f4009fa82 and this PR each build independently from main. A trial merge has one conflicted file, usage-screen.ts, because #5514 reuses totals where this PR extracts the statistics. The resolution keeps this cache, calculates unfiltered activity total as statistics.summary.totalRequests + sum(statistics.byTool.calls), and retains #5514's bounded page queries and zero-count shortcut. That combined implementation passed 40/40 Usage tests on both Node and Electron in a disposable checkout. No PR1 changes are included here.

#5410 at a09e1b7625b8427425a962dd98a1a9cbc0755de8 applies cleanly to this branch and the PR1/PR2 trial merge. That is a patch-compatibility check, not a test run of the three-PR combination.

AI use

Select exactly one:

  • No generative tool made a substantive contribution
  • Generative tooling made a substantive contribution

Tool(s) and scope: Codex implemented the reader cache, regression tests and benchmark, drafted the issue/PR evidence, and performed automated reviews. The commit includes Generated-by: Codex; retain the trailer when squashing.

Checklist

  • Tests cover the change and fail without it
  • Lint, format, typecheck and the affected suites pass locally

Usage-specific checks pass; the full local test gate has the baseline/environment failures listed above.

Does this PR entail a change in behavior?

  • Yes — described under Summary above
  • No

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

effort/L Under 1000 readable lines

Projects

None yet

Development

Successfully merging this pull request may close these issues.

perf(storage): Usage filter changes rebuild unchanged range statistics

1 participant