mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-12 14:16:12 +00:00
docs(bench): record the boot profile and the runtime results
The profile section in docs/contributing/benchmarks.md says how to run scripts/bench/boot-profile.ts, what the profile of the v1.44 runtime found (the worker graph as one 753 ms block, a live heap of about 165 MB of which the query compiler holds 50 and the catalogs 33) and what changed. scripts/bench/results/v1.45.0-*.md hold the before and after numbers per area, from back-to-back runs on the same machine. The size baselines take the lowered numbers.
This commit is contained in:
1 parent
83661319d2
commit
a451a114a2
16 files changed
+6636
-10
No files matched your search
@@ -68,6 +68,42 @@ The output is `<label>.json` (every number, plus the commit, Node and Postgres v
|
||||
|
||||
Run on a quiet machine; a parallel build or test run moves latency by tens of percent and leaves the statement counts alone. Compare statement counts across machines, latency only across runs on the same machine. A local number is only valid under the production heap ceiling, which the script sets.
|
||||
|
||||
## Boot and idle-memory profile
|
||||
|
||||
`scripts/bench/boot-profile.ts` profiles a production start the way production runs it: `next start` on the build, every role (web and worker), the production heap ceiling (`--max-old-space-size=792`, the heap Node derives in the 1.5 GB container), against the seeded benchmark database.
|
||||
|
||||
```sh
|
||||
pnpm dlx tsx scripts/bench/boot-profile.ts --idle-seconds 300 --out scripts/bench/results/<label>-boot
|
||||
```
|
||||
|
||||
It records:
|
||||
|
||||
- the time to the first answer from `/api/health` and to the worker's `startup` line;
|
||||
- every `event_loop_stall` the process logs, with the uptime, startup phase, boot step and work in flight it names;
|
||||
- every `runtime.heap.sampled` line, and every full collection from `--trace-gc` (used heap before, live heap after);
|
||||
- a CPU profile of the start: the main thread's busy stretches over 50 ms without an idle sample, each with its self time per source module, resolved through the chunk source maps (`profile-analyze.ts`);
|
||||
- one heap snapshot after the idle wait, taken with `--heapsnapshot-signal` (after a full collection, so it is the live heap), summarised by node type, constructor, largest strings and the largest retained subtrees with a retaining path, and the number of parsed locale catalogs.
|
||||
|
||||
The worker runs for the whole idle wait, and its boot passes fold and consolidate the seeded account (old dense readings into their `stats:` rows), roughly halving its row count. Reseed before the next request benchmark, or its numbers describe a different account.
|
||||
|
||||
The raw `.cpuprofile` and `.heapsnapshot` go to a temporary directory and are deleted after the summary unless `--keep` is given. Only run it against the benchmark database: a snapshot holds whatever the process decrypted. `--no-snapshot` and `--no-cpu-prof` skip either part. The profiler itself costs memory, so read RSS from this run as an upper bound.
|
||||
|
||||
### What the profile found (v1.44 runtime, October 2026)
|
||||
|
||||
On the seeded account, idle, with the worker running and no requests (`results/v1.45.0-before-boot.md`):
|
||||
|
||||
- **The boot stall is module evaluation.** The longest busy stretch of the main thread was 753 ms, 0.7 s into the start: the instrumentation hook importing the worker, whose five registrars pulled practically all of `src/lib` into one synchronous evaluation (`register-maintenance.ts` alone 280 ms inclusive), followed by the first `/api/health` request compiling its route. The event-loop monitor started after the key and time-zone checks, and a 250 ms tick measures a block by how late the next tick fires, so it reported less than the block or nothing. The beta's 718 ms and 671 ms stalls are this block on a slower machine.
|
||||
- **The live heap is about 165 MB, not 400.** Full collections brought the heap back to 162 to 172 MB every 15 to 20 s while idle; the used heap between them reached 190 MB. What a heap line shows above the live heap is garbage awaiting the next full collection, plus, on a server with users, the server caches (13 caches of up to 2,000 entries with stale windows of up to an hour). The beta's 400 MB plateau is therefore not a baseline the process cannot shed; it is what the heap grows to under a large limit before a collection, plus caches.
|
||||
- **What the live heap holds.** Of 172 MB: the query compiler about 50 MB (the engine object 34 MB, its WebAssembly base64 source twice at 4.4 MB, its chunk source twice at 5.6 MB); the locale catalogs about 33 MB (32 parsed catalog objects, eight locales in each of four server bundles, 14 MB, plus the eight-locale chunk source twice at 9.7 MB); module source strings over 50 KB about 44 MB in total (the catalog chunks included); compiled code 19 MB.
|
||||
|
||||
### What changed (v1.45.0)
|
||||
|
||||
- The event-loop monitor starts first in `register()`, and a stall line names the boot step, startup phase and work in flight (`src/lib/boot/boot-steps.ts`, one `boot.steps` line per boot with each step's duration).
|
||||
- The worker's registrars are imported one at a time after `boss.start()`, with a turn of the event loop between them.
|
||||
- The server reads a locale catalog from `messages/<locale>.json` on first use and keeps one parsed copy per process (`src/lib/i18n/server-catalogs.ts`); the seven matchers that index every locale build their index on first use.
|
||||
|
||||
Result on the same machine (`results/v1.45.0-boot.md`): the worker graph loads in stretches of at most 246 ms instead of one of 753 ms (the longest application stretch left is the query compiler's start, 336 ms, unchanged); the live heap after five idle minutes went from 162 to 172 MB to 142 to 153 MB; two parsed catalogs (1.6 MB) instead of 32 (14.1 MB), and no catalog chunk sources.
|
||||
|
||||
## Statement budgets in the integration suite
|
||||
|
||||
`tests/integration/query-budget-hot-routes.test.ts` seeds a small account (four months of the main types with overlapping sources, sleep, glucose, a medication, workouts and mood), and counts the statements of one request per hot route on a cache miss: `/api/auth/me`, the dashboard summary and snapshot, the pulse series over 30, 365 and 3650 days, the day view, insights health status, correlations, and a 500-row batch ingest.
|
||||
|
||||
@@ -25,6 +25,9 @@
|
||||
* The raw `.cpuprofile` and `.heapsnapshot` are written to a temporary
|
||||
* directory and deleted after the summary unless `--keep` is given.
|
||||
*
|
||||
* The worker's boot passes fold the seeded account while it idles; reseed
|
||||
* before running `run.ts` again.
|
||||
*
|
||||
* Output: `<out>.json` and `<out>.md`.
|
||||
*/
|
||||
import { execSync, spawn } from "node:child_process";
|
||||
@@ -285,8 +288,11 @@ async function main(): Promise<void> {
|
||||
stallMaxMs: Math.max(0, ...stalls.map((s) => Number(s.lag_ms ?? 0))),
|
||||
};
|
||||
mkdirSync(dirname(OUT), { recursive: true });
|
||||
// Paths in frame and retainer names are made relative to the checkout.
|
||||
// Paths in frame and retainer names are made relative to the checkout,
|
||||
// before anything shortens them.
|
||||
const relative = (text: string) => text.split(`${process.cwd()}/`).join("");
|
||||
if (heap) heap = JSON.parse(relative(JSON.stringify(heap))) as typeof heap;
|
||||
tasks = JSON.parse(relative(JSON.stringify(tasks))) as typeof tasks;
|
||||
writeFileSync(
|
||||
`${OUT}.json`,
|
||||
relative(
|
||||
|
||||
@@ -0,0 +1,254 @@
|
||||
{
|
||||
"meta": {
|
||||
"label": "v1.45.0-before",
|
||||
"commit": "1915f9152",
|
||||
"date": "2026-10-22T05:51:47.626Z",
|
||||
"node": "v22.23.2",
|
||||
"postgres": "16.15",
|
||||
"cpus": 14,
|
||||
"loadAverage": [
|
||||
29.9,
|
||||
21.9,
|
||||
18.9
|
||||
],
|
||||
"measurements": 1265561,
|
||||
"iterations": 20,
|
||||
"warmup": 3,
|
||||
"heapMb": 792,
|
||||
"idleStatementsPerSecond": 0,
|
||||
"batch5k": {
|
||||
"totalMs": 1730,
|
||||
"totalStatements": 534
|
||||
}
|
||||
},
|
||||
"results": [
|
||||
{
|
||||
"name": "/api/auth/me",
|
||||
"mode": "cold",
|
||||
"request": "GET /api/auth/me",
|
||||
"n": 20,
|
||||
"p50Ms": 9.2,
|
||||
"p95Ms": 11.6,
|
||||
"maxMs": 13.3,
|
||||
"statementsMedian": 19,
|
||||
"statementsMax": 19,
|
||||
"failures": 0
|
||||
},
|
||||
{
|
||||
"name": "/api/auth/me",
|
||||
"mode": "warm",
|
||||
"request": "GET /api/auth/me",
|
||||
"n": 20,
|
||||
"p50Ms": 8.6,
|
||||
"p95Ms": 10.5,
|
||||
"maxMs": 13,
|
||||
"statementsMedian": 19,
|
||||
"statementsMax": 19,
|
||||
"failures": 0
|
||||
},
|
||||
{
|
||||
"name": "dashboard summary",
|
||||
"mode": "cold",
|
||||
"request": "GET /api/dashboard/summary",
|
||||
"n": 20,
|
||||
"p50Ms": 170.2,
|
||||
"p95Ms": 220.5,
|
||||
"maxMs": 228.3,
|
||||
"statementsMedian": 31,
|
||||
"statementsMax": 34,
|
||||
"failures": 0
|
||||
},
|
||||
{
|
||||
"name": "dashboard summary",
|
||||
"mode": "warm",
|
||||
"request": "GET /api/dashboard/summary",
|
||||
"n": 20,
|
||||
"p50Ms": 6,
|
||||
"p95Ms": 6.7,
|
||||
"maxMs": 6.8,
|
||||
"statementsMedian": 7,
|
||||
"statementsMax": 7,
|
||||
"failures": 0
|
||||
},
|
||||
{
|
||||
"name": "dashboard snapshot",
|
||||
"mode": "cold",
|
||||
"request": "GET /api/dashboard/snapshot",
|
||||
"n": 20,
|
||||
"p50Ms": 1481.8,
|
||||
"p95Ms": 1526.2,
|
||||
"maxMs": 1530,
|
||||
"statementsMedian": 158,
|
||||
"statementsMax": 161,
|
||||
"failures": 0
|
||||
},
|
||||
{
|
||||
"name": "dashboard snapshot",
|
||||
"mode": "warm",
|
||||
"request": "GET /api/dashboard/snapshot",
|
||||
"n": 20,
|
||||
"p50Ms": 7,
|
||||
"p95Ms": 7.9,
|
||||
"maxMs": 10.2,
|
||||
"statementsMedian": 13,
|
||||
"statementsMax": 13,
|
||||
"failures": 0
|
||||
},
|
||||
{
|
||||
"name": "series pulse 30 d",
|
||||
"mode": "cold",
|
||||
"request": "GET /api/measurements/series?kind=pulse&days=30",
|
||||
"n": 20,
|
||||
"p50Ms": 24.4,
|
||||
"p95Ms": 30.8,
|
||||
"maxMs": 31.1,
|
||||
"statementsMedian": 8,
|
||||
"statementsMax": 8,
|
||||
"failures": 0
|
||||
},
|
||||
{
|
||||
"name": "series pulse 30 d",
|
||||
"mode": "warm",
|
||||
"request": "GET /api/measurements/series?kind=pulse&days=30",
|
||||
"n": 20,
|
||||
"p50Ms": 20.5,
|
||||
"p95Ms": 29.4,
|
||||
"maxMs": 30.2,
|
||||
"statementsMedian": 8,
|
||||
"statementsMax": 9,
|
||||
"failures": 0
|
||||
},
|
||||
{
|
||||
"name": "series pulse 365 d",
|
||||
"mode": "cold",
|
||||
"request": "GET /api/measurements/series?kind=pulse&days=365",
|
||||
"n": 20,
|
||||
"p50Ms": 184.1,
|
||||
"p95Ms": 192.6,
|
||||
"maxMs": 201.1,
|
||||
"statementsMedian": 8,
|
||||
"statementsMax": 8,
|
||||
"failures": 0
|
||||
},
|
||||
{
|
||||
"name": "series pulse 365 d",
|
||||
"mode": "warm",
|
||||
"request": "GET /api/measurements/series?kind=pulse&days=365",
|
||||
"n": 20,
|
||||
"p50Ms": 178.1,
|
||||
"p95Ms": 186.5,
|
||||
"maxMs": 187.6,
|
||||
"statementsMedian": 8,
|
||||
"statementsMax": 8,
|
||||
"failures": 0
|
||||
},
|
||||
{
|
||||
"name": "series pulse 3650 d",
|
||||
"mode": "cold",
|
||||
"request": "GET /api/measurements/series?kind=pulse&days=3650",
|
||||
"n": 20,
|
||||
"p50Ms": 1627,
|
||||
"p95Ms": 1664.5,
|
||||
"maxMs": 1675.7,
|
||||
"statementsMedian": 8,
|
||||
"statementsMax": 9,
|
||||
"failures": 0
|
||||
},
|
||||
{
|
||||
"name": "series pulse 3650 d",
|
||||
"mode": "warm",
|
||||
"request": "GET /api/measurements/series?kind=pulse&days=3650",
|
||||
"n": 20,
|
||||
"p50Ms": 2090.9,
|
||||
"p95Ms": 2435.4,
|
||||
"maxMs": 2529.7,
|
||||
"statementsMedian": 8,
|
||||
"statementsMax": 9,
|
||||
"failures": 0
|
||||
},
|
||||
{
|
||||
"name": "day view",
|
||||
"mode": "cold",
|
||||
"request": "GET /api/day/2026-10-21",
|
||||
"n": 20,
|
||||
"p50Ms": 76.7,
|
||||
"p95Ms": 93.6,
|
||||
"maxMs": 116.2,
|
||||
"statementsMedian": 49,
|
||||
"statementsMax": 49,
|
||||
"failures": 0
|
||||
},
|
||||
{
|
||||
"name": "day view",
|
||||
"mode": "warm",
|
||||
"request": "GET /api/day/2026-10-21",
|
||||
"n": 20,
|
||||
"p50Ms": 62.8,
|
||||
"p95Ms": 72,
|
||||
"maxMs": 73.5,
|
||||
"statementsMedian": 48,
|
||||
"statementsMax": 48,
|
||||
"failures": 0
|
||||
},
|
||||
{
|
||||
"name": "insights health status",
|
||||
"mode": "cold",
|
||||
"request": "GET /api/insights/health-status",
|
||||
"n": 20,
|
||||
"p50Ms": 244.7,
|
||||
"p95Ms": 401.2,
|
||||
"maxMs": 404.1,
|
||||
"statementsMedian": 68,
|
||||
"statementsMax": 69,
|
||||
"failures": 0
|
||||
},
|
||||
{
|
||||
"name": "insights health status",
|
||||
"mode": "warm",
|
||||
"request": "GET /api/insights/health-status",
|
||||
"n": 20,
|
||||
"p50Ms": 238.9,
|
||||
"p95Ms": 399.1,
|
||||
"maxMs": 476.6,
|
||||
"statementsMedian": 68,
|
||||
"statementsMax": 68,
|
||||
"failures": 0
|
||||
},
|
||||
{
|
||||
"name": "insights correlations",
|
||||
"mode": "cold",
|
||||
"request": "GET /api/insights/correlations",
|
||||
"n": 20,
|
||||
"p50Ms": 105.6,
|
||||
"p95Ms": 326.9,
|
||||
"maxMs": 349.7,
|
||||
"statementsMedian": 49,
|
||||
"statementsMax": 52,
|
||||
"failures": 0
|
||||
},
|
||||
{
|
||||
"name": "insights correlations",
|
||||
"mode": "warm",
|
||||
"request": "GET /api/insights/correlations",
|
||||
"n": 20,
|
||||
"p50Ms": 11.3,
|
||||
"p95Ms": 16.6,
|
||||
"maxMs": 20.3,
|
||||
"statementsMedian": 8,
|
||||
"statementsMax": 8,
|
||||
"failures": 0
|
||||
},
|
||||
{
|
||||
"name": "batch ingest 5k (per 500)",
|
||||
"mode": "write",
|
||||
"request": "POST /api/measurements/batch ×10",
|
||||
"n": 10,
|
||||
"p50Ms": 166.1,
|
||||
"p95Ms": 220.3,
|
||||
"maxMs": 220.3,
|
||||
"statementsMedian": 53,
|
||||
"statementsMax": 56,
|
||||
"failures": 0
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
# Benchmark v1.45.0-before
|
||||
|
||||
Commit 1915f9152 (the v1.44 runtime this branch starts from), 2026-10-22T05:51:47.626Z. 1265561 measurement rows on the bench account, 20 measured requests per row after 3 warm-up requests, one at a time. Server: production build, web process, heap ceiling 792 MB. Postgres 16.15, 14 cores, load average 29.9,21.9,18.9 at the end. Idle background: 0 statements/s.
|
||||
|
||||
| Request | Mode | n | p50 ms | p95 ms | max ms | statements (median) | statements (max) |
|
||||
| --- | --- | ---: | ---: | ---: | ---: | ---: | ---: |
|
||||
| /api/auth/me | cold | 20 | 9.2 | 11.6 | 13.3 | 19 | 19 |
|
||||
| /api/auth/me | warm | 20 | 8.6 | 10.5 | 13 | 19 | 19 |
|
||||
| dashboard summary | cold | 20 | 170.2 | 220.5 | 228.3 | 31 | 34 |
|
||||
| dashboard summary | warm | 20 | 6 | 6.7 | 6.8 | 7 | 7 |
|
||||
| dashboard snapshot | cold | 20 | 1481.8 | 1526.2 | 1530 | 158 | 161 |
|
||||
| dashboard snapshot | warm | 20 | 7 | 7.9 | 10.2 | 13 | 13 |
|
||||
| series pulse 30 d | cold | 20 | 24.4 | 30.8 | 31.1 | 8 | 8 |
|
||||
| series pulse 30 d | warm | 20 | 20.5 | 29.4 | 30.2 | 8 | 9 |
|
||||
| series pulse 365 d | cold | 20 | 184.1 | 192.6 | 201.1 | 8 | 8 |
|
||||
| series pulse 365 d | warm | 20 | 178.1 | 186.5 | 187.6 | 8 | 8 |
|
||||
| series pulse 3650 d | cold | 20 | 1627 | 1664.5 | 1675.7 | 8 | 9 |
|
||||
| series pulse 3650 d | warm | 20 | 2090.9 | 2435.4 | 2529.7 | 8 | 9 |
|
||||
| day view | cold | 20 | 76.7 | 93.6 | 116.2 | 49 | 49 |
|
||||
| day view | warm | 20 | 62.8 | 72 | 73.5 | 48 | 48 |
|
||||
| insights health status | cold | 20 | 244.7 | 401.2 | 404.1 | 68 | 69 |
|
||||
| insights health status | warm | 20 | 238.9 | 399.1 | 476.6 | 68 | 68 |
|
||||
| insights correlations | cold | 20 | 105.6 | 326.9 | 349.7 | 49 | 52 |
|
||||
| insights correlations | warm | 20 | 11.3 | 16.6 | 20.3 | 8 | 8 |
|
||||
| batch ingest 5k (per 500) | write | 10 | 166.1 | 220.3 | 220.3 | 53 | 56 |
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,804 @@
|
||||
# Boot profile v1.45.0-boot-final
|
||||
|
||||
Commit a57fa8335, 2026-10-22T06:58:52.591Z. Production build, every role, heap ceiling 792 MB, 300 s idle. 14 cores, load average 5.6,6.4,11.1 at the end.
|
||||
|
||||
- first answer from /api/health: 1325 ms; background role ready: 3217 ms
|
||||
- event-loop stalls logged: 0, max 0 ms
|
||||
|
||||
## Stalls
|
||||
|
||||
|
||||
## Heap samples
|
||||
|
||||
| at s | used MB | old | large obj | code | external | array buffers | rss |
|
||||
| ---: | ---: | ---: | ---: | ---: | ---: | ---: | ---: |
|
||||
| 6 | 225 | 158 | 54 | 4 | 11 | 0 | 500 |
|
||||
| 306 | 158 | 96 | 53 | 5 | 11 | 0 | 788 |
|
||||
|
||||
## Full collections (mark-compact)
|
||||
|
||||
98 mark-compacts during the run. Used heap before the collection, and what survived it (the live heap):
|
||||
|
||||
| at s | before MB | after MB |
|
||||
| ---: | ---: | ---: |
|
||||
| 0 | 21.5 | 17.5 |
|
||||
| 8 | 203.8 | 146.5 |
|
||||
| 24 | 236.5 | 142.5 |
|
||||
| 41 | 223.8 | 144.9 |
|
||||
| 60 | 225.8 | 147.5 |
|
||||
| 85 | 224.4 | 147.7 |
|
||||
| 124 | 225.4 | 151.2 |
|
||||
| 167 | 176.7 | 151 |
|
||||
| 209 | 230.1 | 150.4 |
|
||||
| 242 | 197.9 | 151.5 |
|
||||
| 273 | 224.8 | 152.2 |
|
||||
| 302 | 177.9 | 152.5 |
|
||||
| 312 | 170.5 | 152.9 |
|
||||
| 327 | 170.6 | 152 |
|
||||
| 338 | 169.7 | 151.8 |
|
||||
|
||||
## Main-thread busy stretches over 50 ms without an idle sample, first two minutes
|
||||
|
||||
### at 5 ms, 396 ms
|
||||
|
||||
| self time by module | ms |
|
||||
| --- | ---: |
|
||||
| (native) | 230.2 |
|
||||
| node:internal/modules/cjs/loader | 57.8 |
|
||||
| npm:next | 52.3 |
|
||||
| node:internal/bootstrap/realm | 29.3 |
|
||||
| node:internal/deps/undici/undici | 8.9 |
|
||||
| node:internal/modules/esm/loader | 4.5 |
|
||||
| node:fs | 3 |
|
||||
| node:internal/net | 2.5 |
|
||||
| node:internal/bootstrap/switches/is_main_thread | 2 |
|
||||
| node:os | 1.8 |
|
||||
|
||||
| inclusive, application modules | ms |
|
||||
| --- | ---: |
|
||||
|
||||
### at 472 ms, 336 ms
|
||||
|
||||
| self time by module | ms |
|
||||
| --- | ---: |
|
||||
| (native) | 121.3 |
|
||||
| wasm://wasm/00d1cb12 | 43 |
|
||||
| node:internal/modules/cjs/loader | 40.5 |
|
||||
| npm:next | 31.7 |
|
||||
| npm:@prisma/client | 23.8 |
|
||||
| turbopack:///[turbopack]/nodejs/runtime/build-base.ts | 23.4 |
|
||||
| node:internal/modules/esm/utils | 17.3 |
|
||||
| npm:zod | 5.9 |
|
||||
| turbopack:///[turbopack]/shared/runtime/runtime-utils.ts | 3 |
|
||||
| node:vm | 1.7 |
|
||||
|
||||
| inclusive, application modules | ms |
|
||||
| --- | ---: |
|
||||
| src/instrumentation.ts | 95.8 |
|
||||
| src/lib/db-session.ts | 47.3 |
|
||||
| src/lib/process-type.ts | 27.1 |
|
||||
| src/lib/boot/startup-state.ts | 25.5 |
|
||||
| src/lib/boot/boot-steps.ts | 25.5 |
|
||||
| src/lib/logging/background.ts | 25.5 |
|
||||
| src/lib/logging/redact.ts | 13 |
|
||||
| src/lib/logging/context.ts | 11 |
|
||||
| src/lib/validations/measurement.ts | 10 |
|
||||
| src/generated/prisma/internal/class.ts | 4.7 |
|
||||
|
||||
### at 811 ms, 225 ms
|
||||
|
||||
| self time by module | ms |
|
||||
| --- | ---: |
|
||||
| node:internal/modules/cjs/loader | 52.3 |
|
||||
| (native) | 48.2 |
|
||||
| turbopack:///[turbopack]/nodejs/runtime/build-base.ts | 37 |
|
||||
| npm:next | 22.2 |
|
||||
| npm:zod | 12.5 |
|
||||
| node:internal/modules/esm/utils | 8.7 |
|
||||
| turbopack:///[turbopack]/shared/runtime/async-module.ts | 5.6 |
|
||||
| node:fs | 4.5 |
|
||||
| node:internal/async_hooks | 3 |
|
||||
| node:internal/modules/esm/translators | 2.6 |
|
||||
|
||||
| inclusive, application modules | ms |
|
||||
| --- | ---: |
|
||||
| src/app/api/health/route.ts | 62 |
|
||||
| src/lib/api-errors.ts | 25.9 |
|
||||
| src/lib/auth/secure-cookie.ts | 14.9 |
|
||||
| src/lib/logging/background.ts | 13.4 |
|
||||
| src/lib/sharing/acting-session.ts | 12.8 |
|
||||
| src/lib/validations/measurement.ts | 11.9 |
|
||||
| src/lib/db-session.ts | 11.3 |
|
||||
| src/lib/export/environment-backup.ts | 11.3 |
|
||||
| src/lib/export/full-backup-payload.ts | 11.3 |
|
||||
| src/lib/jobs/job-failures.ts | 11.3 |
|
||||
|
||||
### at 1063 ms, 246 ms
|
||||
|
||||
| self time by module | ms |
|
||||
| --- | ---: |
|
||||
| (native) | 64.7 |
|
||||
| turbopack:///[turbopack]/nodejs/runtime/build-base.ts | 47.2 |
|
||||
| node:internal/modules/cjs/loader | 31.6 |
|
||||
| npm:luxon | 18 |
|
||||
| turbopack:///[turbopack]/shared/runtime/async-module.ts | 15.3 |
|
||||
| npm:yaml | 15 |
|
||||
| npm:zod | 10.2 |
|
||||
| src/lib/i18n/server-catalogs.ts | 8.2 |
|
||||
| turbopack:///[turbopack]/shared/runtime/runtime-utils.ts | 4.5 |
|
||||
| npm:cron-parser | 4 |
|
||||
|
||||
| inclusive, application modules | ms |
|
||||
| --- | ---: |
|
||||
| src/lib/jobs/reminder-worker.ts | 137.6 |
|
||||
| src/lib/jobs/reminder/google-health-sync.ts | 78 |
|
||||
| src/lib/whoop/sync.ts | 65.9 |
|
||||
| src/instrumentation.ts | 53.8 |
|
||||
| src/lib/insights/bucket-series.ts | 47.1 |
|
||||
| src/lib/whoop/oauth-descriptor.ts | 47.1 |
|
||||
| src/lib/whoop/sync-core.ts | 47.1 |
|
||||
| src/lib/whoop/sync-body.ts | 47.1 |
|
||||
| src/lib/import/unzip-export-xml.ts | 35.3 |
|
||||
| src/lib/jobs/integration-status-null-probe.ts | 35.3 |
|
||||
|
||||
### at 1363 ms, 68 ms
|
||||
|
||||
| self time by module | ms |
|
||||
| --- | ---: |
|
||||
| node:internal/modules/cjs/loader | 29.2 |
|
||||
| turbopack:///[turbopack]/nodejs/runtime/build-base.ts | 6.7 |
|
||||
| (native) | 5.9 |
|
||||
| turbopack:///[turbopack]/shared/runtime/runtime-utils.ts | 4.5 |
|
||||
| src/lib/daily/today-overview.ts | 4.1 |
|
||||
| node:fs | 3 |
|
||||
| turbopack:///[turbopack]/shared/runtime/async-module.ts | 3 |
|
||||
| node:internal/streams/writable | 1.5 |
|
||||
| src/lib/jobs/reminder/insights-handlers.ts | 1.5 |
|
||||
| npm:next | 1.5 |
|
||||
|
||||
| inclusive, application modules | ms |
|
||||
| --- | ---: |
|
||||
| src/lib/jobs/reminder-worker.ts | 62.5 |
|
||||
| src/lib/jobs/reminder/insights-handlers.ts | 24.4 |
|
||||
| src/lib/ai/prompts/arrival-reaction.ts | 12.8 |
|
||||
| src/lib/daily/score-steady.ts | 11.3 |
|
||||
| src/lib/dashboard/bands.ts | 7.1 |
|
||||
| src/lib/dashboard/snapshot-read.ts | 5.8 |
|
||||
| src/lib/jobs/data-arrival.ts | 4.5 |
|
||||
| src/lib/daily/today-overview.ts | 4.1 |
|
||||
| src/lib/daily/priority-item-key.ts | 4.1 |
|
||||
| src/lib/ai/prompts/status-batch.ts | 3 |
|
||||
|
||||
### at 1545 ms, 57 ms
|
||||
|
||||
| self time by module | ms |
|
||||
| --- | ---: |
|
||||
| node:internal/modules/cjs/loader | 25.3 |
|
||||
| (native) | 12.9 |
|
||||
| turbopack:///[turbopack]/nodejs/runtime/build-base.ts | 7.2 |
|
||||
| node:fs | 4.2 |
|
||||
| node:buffer | 1.5 |
|
||||
| npm:zod | 1.5 |
|
||||
| src/lib/jobs/pr-detection.ts | 1.5 |
|
||||
| turbopack:///[turbopack]/shared/runtime/async-module.ts | 1.5 |
|
||||
| src/lib/jobs/measurement-maintenance.ts | 1.3 |
|
||||
|
||||
| inclusive, application modules | ms |
|
||||
| --- | ---: |
|
||||
| src/lib/jobs/reminder-worker.ts | 55.3 |
|
||||
| src/lib/jobs/reminder/ops-handlers.ts | 13 |
|
||||
| src/lib/export/restore-backup.ts | 3 |
|
||||
| src/lib/medications/ingredients/label-extract.ts | 3 |
|
||||
| src/lib/environment/service.ts | 1.5 |
|
||||
| src/lib/export/backup-blob.ts | 1.5 |
|
||||
| src/lib/jobs/pr-detection.ts | 1.5 |
|
||||
| src/lib/jobs/document-content-index-backfill.ts | 1.5 |
|
||||
| src/lib/labs/ocr-extract.ts | 1.5 |
|
||||
| src/lib/jobs/reminder/backup-handlers.ts | 1.5 |
|
||||
|
||||
### at 1820 ms, 114 ms
|
||||
|
||||
| self time by module | ms |
|
||||
| --- | ---: |
|
||||
| src/lib/tz/zone-offset.ts | 36 |
|
||||
| npm:@prisma/client | 18.2 |
|
||||
| src/lib/validations/source-priority.ts | 18.1 |
|
||||
| (native) | 13.1 |
|
||||
| src/lib/personal-records/pr-detection-worker.ts | 7.2 |
|
||||
| node:buffer | 4.1 |
|
||||
| src/lib/analytics/source-priority.ts | 3.7 |
|
||||
| npm:zod | 2.3 |
|
||||
| npm:pg | 2 |
|
||||
| src/lib/tz/format.ts | 1.9 |
|
||||
|
||||
| inclusive, application modules | ms |
|
||||
| --- | ---: |
|
||||
| src/lib/personal-records/pr-detection-worker.ts | 73.3 |
|
||||
| src/lib/tz/format.ts | 40.7 |
|
||||
| src/lib/measurements/consolidation-tz.ts | 40.7 |
|
||||
| src/lib/tz/zone-offset.ts | 38.8 |
|
||||
| src/lib/measurements/consolidation-base.ts | 38.1 |
|
||||
| src/lib/analytics/source-priority.ts | 28.1 |
|
||||
| src/lib/validations/source-priority.ts | 20.4 |
|
||||
| src/lib/tz/intl-cache.ts | 1.5 |
|
||||
|
||||
### at 2407 ms, 50 ms
|
||||
|
||||
| self time by module | ms |
|
||||
| --- | ---: |
|
||||
| (native) | 18.9 |
|
||||
| src/lib/validations/source-priority.ts | 14.1 |
|
||||
| src/lib/analytics/source-priority.ts | 3.7 |
|
||||
| src/lib/personal-records/pr-detection-worker.ts | 3 |
|
||||
| npm:next | 1.8 |
|
||||
| npm:%40prisma | 1.5 |
|
||||
| src/lib/tz/format.ts | 1.5 |
|
||||
| node:internal/async_local_storage/async_hooks | 1.5 |
|
||||
| npm:pg | 1.5 |
|
||||
| npm:@prisma/client | 1.3 |
|
||||
|
||||
| inclusive, application modules | ms |
|
||||
| --- | ---: |
|
||||
| src/lib/personal-records/pr-detection-worker.ts | 26.6 |
|
||||
| src/lib/analytics/source-priority.ts | 19.3 |
|
||||
| src/lib/validations/source-priority.ts | 14.1 |
|
||||
| src/lib/tz/format.ts | 3 |
|
||||
| src/lib/measurements/consolidation-tz.ts | 3 |
|
||||
| src/lib/measurements/consolidation-base.ts | 2.8 |
|
||||
| src/lib/tz/zone-offset.ts | 1.5 |
|
||||
|
||||
### at 18192 ms, 59 ms
|
||||
|
||||
| self time by module | ms |
|
||||
| --- | ---: |
|
||||
| (native) | 15.5 |
|
||||
| npm:@prisma/client | 13.9 |
|
||||
| src/lib/validations/source-priority.ts | 11.8 |
|
||||
| npm:pg | 3.6 |
|
||||
| node:events | 3 |
|
||||
| node:buffer | 2.5 |
|
||||
| src/lib/measurements/consolidation-base.ts | 1.5 |
|
||||
| src/lib/personal-records/pr-detection-worker.ts | 1.5 |
|
||||
| node:internal/async_hooks | 1.5 |
|
||||
| npm:pg-types | 1.4 |
|
||||
|
||||
| inclusive, application modules | ms |
|
||||
| --- | ---: |
|
||||
| src/lib/personal-records/pr-detection-worker.ts | 18.9 |
|
||||
| src/lib/analytics/source-priority.ts | 12.9 |
|
||||
| src/lib/validations/source-priority.ts | 11.8 |
|
||||
| src/lib/measurements/consolidation-base.ts | 4.5 |
|
||||
| src/lib/tz/zone-offset.ts | 2.6 |
|
||||
| src/lib/tz/format.ts | 2.6 |
|
||||
| src/lib/measurements/consolidation-tz.ts | 2.6 |
|
||||
|
||||
### at 19914 ms, 65 ms
|
||||
|
||||
| self time by module | ms |
|
||||
| --- | ---: |
|
||||
| src/lib/validations/source-priority.ts | 18.1 |
|
||||
| (native) | 12.3 |
|
||||
| npm:@prisma/client | 11.6 |
|
||||
| npm:next | 5.9 |
|
||||
| src/lib/personal-records/pr-detection-worker.ts | 3 |
|
||||
| src/lib/tz/format.ts | 3 |
|
||||
| npm:pg | 2.6 |
|
||||
| npm:pg-protocol | 2.5 |
|
||||
| node:internal/async_hooks | 1.5 |
|
||||
| src/lib/analytics/source-priority.ts | 1.5 |
|
||||
|
||||
| inclusive, application modules | ms |
|
||||
| --- | ---: |
|
||||
| src/lib/personal-records/pr-detection-worker.ts | 29.8 |
|
||||
| src/lib/analytics/source-priority.ts | 22.6 |
|
||||
| src/lib/validations/source-priority.ts | 18.1 |
|
||||
| src/lib/tz/format.ts | 5.8 |
|
||||
| src/lib/measurements/consolidation-tz.ts | 5.8 |
|
||||
| src/lib/tz/zone-offset.ts | 2.8 |
|
||||
| src/lib/measurements/consolidation-base.ts | 2.8 |
|
||||
|
||||
### at 20296 ms, 55 ms
|
||||
|
||||
| self time by module | ms |
|
||||
| --- | ---: |
|
||||
| (native) | 22.4 |
|
||||
| npm:@prisma/client | 14.8 |
|
||||
| node:buffer | 3 |
|
||||
| npm:zod | 3 |
|
||||
| src/lib/measurements/consolidation-base.ts | 3 |
|
||||
| src/lib/tz/format.ts | 1.5 |
|
||||
| node:internal/stream_base_commons | 1.5 |
|
||||
| src/lib/analytics/source-priority.ts | 1.5 |
|
||||
| src/lib/personal-records/pr-detection-worker.ts | 1.5 |
|
||||
| npm:pg-protocol | 1.3 |
|
||||
|
||||
| inclusive, application modules | ms |
|
||||
| --- | ---: |
|
||||
| src/lib/personal-records/pr-detection-worker.ts | 10.5 |
|
||||
| src/lib/analytics/source-priority.ts | 6 |
|
||||
| src/lib/validations/source-priority.ts | 3 |
|
||||
| src/lib/measurements/consolidation-base.ts | 3 |
|
||||
| src/lib/tz/format.ts | 1.5 |
|
||||
| src/lib/measurements/consolidation-tz.ts | 1.5 |
|
||||
|
||||
### at 30289 ms, 69 ms
|
||||
|
||||
| self time by module | ms |
|
||||
| --- | ---: |
|
||||
| src/lib/validations/source-priority.ts | 18.3 |
|
||||
| (native) | 12.9 |
|
||||
| npm:@prisma/client | 8.8 |
|
||||
| node:buffer | 6.8 |
|
||||
| src/lib/personal-records/pr-detection-worker.ts | 4.5 |
|
||||
| src/lib/tz/format.ts | 4 |
|
||||
| npm:pg-protocol | 3 |
|
||||
| npm:zod | 3 |
|
||||
| node:timers | 1.5 |
|
||||
| node:internal/async_hooks | 1.5 |
|
||||
|
||||
| inclusive, application modules | ms |
|
||||
| --- | ---: |
|
||||
| src/lib/personal-records/pr-detection-worker.ts | 33 |
|
||||
| src/lib/analytics/source-priority.ts | 24.3 |
|
||||
| src/lib/validations/source-priority.ts | 21.3 |
|
||||
| src/lib/tz/format.ts | 5.6 |
|
||||
| src/lib/measurements/consolidation-tz.ts | 5.6 |
|
||||
| src/lib/measurements/consolidation-base.ts | 2.6 |
|
||||
| src/lib/tz/zone-offset.ts | 1.5 |
|
||||
|
||||
### at 31004 ms, 68 ms
|
||||
|
||||
| self time by module | ms |
|
||||
| --- | ---: |
|
||||
| (native) | 17.8 |
|
||||
| src/lib/validations/source-priority.ts | 14.9 |
|
||||
| npm:@prisma/client | 7.6 |
|
||||
| npm:next | 4.5 |
|
||||
| node:internal/async_hooks | 4.5 |
|
||||
| npm:pg-protocol | 4.1 |
|
||||
| npm:pg | 3 |
|
||||
| src/lib/tz/zone-offset.ts | 3 |
|
||||
| node:buffer | 2.7 |
|
||||
| src/lib/analytics/source-priority.ts | 1.5 |
|
||||
|
||||
| inclusive, application modules | ms |
|
||||
| --- | ---: |
|
||||
| src/lib/personal-records/pr-detection-worker.ts | 26.4 |
|
||||
| src/lib/analytics/source-priority.ts | 19 |
|
||||
| src/lib/validations/source-priority.ts | 16.2 |
|
||||
| src/lib/measurements/consolidation-base.ts | 6.1 |
|
||||
| src/lib/tz/format.ts | 5.8 |
|
||||
| src/lib/measurements/consolidation-tz.ts | 5.8 |
|
||||
| src/lib/tz/zone-offset.ts | 4.5 |
|
||||
|
||||
### at 35350 ms, 65 ms
|
||||
|
||||
| self time by module | ms |
|
||||
| --- | ---: |
|
||||
| src/lib/validations/source-priority.ts | 17 |
|
||||
| npm:@prisma/client | 11.8 |
|
||||
| (native) | 8.6 |
|
||||
| node:buffer | 6.5 |
|
||||
| src/lib/tz/format.ts | 4.5 |
|
||||
| npm:pg-protocol | 3 |
|
||||
| src/lib/personal-records/pr-detection-worker.ts | 3 |
|
||||
| npm:%40prisma | 1.6 |
|
||||
| npm:pg | 1.5 |
|
||||
| src/lib/analytics/source-priority.ts | 1.5 |
|
||||
|
||||
| inclusive, application modules | ms |
|
||||
| --- | ---: |
|
||||
| src/lib/personal-records/pr-detection-worker.ts | 26 |
|
||||
| src/lib/analytics/source-priority.ts | 20 |
|
||||
| src/lib/validations/source-priority.ts | 17 |
|
||||
| src/lib/tz/format.ts | 4.5 |
|
||||
| src/lib/measurements/consolidation-tz.ts | 4.5 |
|
||||
| src/lib/measurements/consolidation-base.ts | 3 |
|
||||
|
||||
### at 36452 ms, 57 ms
|
||||
|
||||
| self time by module | ms |
|
||||
| --- | ---: |
|
||||
| (native) | 20 |
|
||||
| src/lib/validations/source-priority.ts | 16 |
|
||||
| npm:@prisma/client | 7.3 |
|
||||
| node:internal/per_context/primordials | 2.8 |
|
||||
| npm:%40prisma | 1.5 |
|
||||
| npm:next | 1.5 |
|
||||
| src/lib/tz/zone-offset.ts | 1.5 |
|
||||
| node:internal/async_hooks | 1.5 |
|
||||
| node:internal/streams/readable | 1.5 |
|
||||
| npm:pg-protocol | 1.2 |
|
||||
|
||||
| inclusive, application modules | ms |
|
||||
| --- | ---: |
|
||||
| src/lib/personal-records/pr-detection-worker.ts | 21.2 |
|
||||
| src/lib/validations/source-priority.ts | 16 |
|
||||
| src/lib/analytics/source-priority.ts | 16 |
|
||||
| src/lib/tz/format.ts | 2.5 |
|
||||
| src/lib/measurements/consolidation-tz.ts | 2.5 |
|
||||
| src/lib/measurements/consolidation-base.ts | 2.5 |
|
||||
| src/lib/tz/zone-offset.ts | 1.5 |
|
||||
|
||||
### at 38744 ms, 56 ms
|
||||
|
||||
| self time by module | ms |
|
||||
| --- | ---: |
|
||||
| src/lib/validations/source-priority.ts | 13.3 |
|
||||
| (native) | 9.9 |
|
||||
| npm:@prisma/client | 9.2 |
|
||||
| node:buffer | 4.7 |
|
||||
| npm:pg-protocol | 4.3 |
|
||||
| node:events | 1.9 |
|
||||
| npm:pg | 1.6 |
|
||||
| npm:%40prisma | 1.5 |
|
||||
| npm:next | 1.5 |
|
||||
| src/lib/tz/format.ts | 1.5 |
|
||||
|
||||
| inclusive, application modules | ms |
|
||||
| --- | ---: |
|
||||
| src/lib/personal-records/pr-detection-worker.ts | 21.8 |
|
||||
| src/lib/analytics/source-priority.ts | 16 |
|
||||
| src/lib/validations/source-priority.ts | 13.3 |
|
||||
| src/lib/measurements/consolidation-base.ts | 4.3 |
|
||||
| src/lib/tz/format.ts | 3 |
|
||||
| src/lib/measurements/consolidation-tz.ts | 3 |
|
||||
| src/lib/tz/zone-offset.ts | 1.4 |
|
||||
|
||||
### at 42458 ms, 50 ms
|
||||
|
||||
| self time by module | ms |
|
||||
| --- | ---: |
|
||||
| npm:@prisma/client | 13.5 |
|
||||
| src/lib/validations/source-priority.ts | 10.1 |
|
||||
| (native) | 7.6 |
|
||||
| npm:pg-protocol | 3.2 |
|
||||
| node:events | 3 |
|
||||
| src/lib/personal-records/pr-detection-worker.ts | 3 |
|
||||
| src/lib/tz/format.ts | 3 |
|
||||
| npm:pg | 2.8 |
|
||||
| node:internal/async_hooks | 1.5 |
|
||||
| npm:%40prisma | 1.4 |
|
||||
|
||||
| inclusive, application modules | ms |
|
||||
| --- | ---: |
|
||||
| src/lib/personal-records/pr-detection-worker.ts | 17.3 |
|
||||
| src/lib/analytics/source-priority.ts | 12.7 |
|
||||
| src/lib/validations/source-priority.ts | 10.1 |
|
||||
| src/lib/tz/format.ts | 3 |
|
||||
| src/lib/measurements/consolidation-tz.ts | 3 |
|
||||
| src/lib/measurements/consolidation-base.ts | 1.5 |
|
||||
| src/lib/jobs/job-lock.ts | 1.3 |
|
||||
| src/lib/jobs/long-pass.ts | 1.3 |
|
||||
| src/lib/jobs/run-job.ts | 1.3 |
|
||||
| src/lib/jobs/job-observer.ts | 1.3 |
|
||||
|
||||
### at 45451 ms, 63 ms
|
||||
|
||||
| self time by module | ms |
|
||||
| --- | ---: |
|
||||
| src/lib/validations/source-priority.ts | 15.8 |
|
||||
| npm:@prisma/client | 10.5 |
|
||||
| (native) | 8.4 |
|
||||
| src/lib/tz/format.ts | 5.3 |
|
||||
| node:internal/async_local_storage/async_hooks | 4.4 |
|
||||
| node:buffer | 3 |
|
||||
| npm:pg | 3 |
|
||||
| src/lib/personal-records/pr-detection-worker.ts | 3 |
|
||||
| npm:zod | 3 |
|
||||
| npm:%40prisma | 1.5 |
|
||||
|
||||
| inclusive, application modules | ms |
|
||||
| --- | ---: |
|
||||
| src/lib/personal-records/pr-detection-worker.ts | 31.7 |
|
||||
| src/lib/analytics/source-priority.ts | 21.8 |
|
||||
| src/lib/validations/source-priority.ts | 18.8 |
|
||||
| src/lib/measurements/consolidation-base.ts | 5.3 |
|
||||
| src/lib/tz/format.ts | 5.3 |
|
||||
| src/lib/measurements/consolidation-tz.ts | 5.3 |
|
||||
|
||||
### at 56854 ms, 66 ms
|
||||
|
||||
| self time by module | ms |
|
||||
| --- | ---: |
|
||||
| src/lib/validations/source-priority.ts | 15 |
|
||||
| npm:@prisma/client | 13.7 |
|
||||
| (native) | 6.6 |
|
||||
| node:buffer | 6.6 |
|
||||
| npm:next | 6 |
|
||||
| npm:pg | 4.5 |
|
||||
| src/lib/personal-records/pr-detection-worker.ts | 4.1 |
|
||||
| src/lib/tz/format.ts | 3.1 |
|
||||
| node:internal/process/task_queues | 1.5 |
|
||||
| node:internal/async_hooks | 1.5 |
|
||||
|
||||
| inclusive, application modules | ms |
|
||||
| --- | ---: |
|
||||
| src/lib/personal-records/pr-detection-worker.ts | 25.3 |
|
||||
| src/lib/analytics/source-priority.ts | 18.1 |
|
||||
| src/lib/validations/source-priority.ts | 16.5 |
|
||||
| src/lib/tz/format.ts | 3.1 |
|
||||
| src/lib/measurements/consolidation-tz.ts | 3.1 |
|
||||
| src/lib/measurements/consolidation-base.ts | 3.1 |
|
||||
|
||||
### at 56923 ms, 52 ms
|
||||
|
||||
| self time by module | ms |
|
||||
| --- | ---: |
|
||||
| (native) | 20 |
|
||||
| npm:@prisma/client | 10.1 |
|
||||
| node:buffer | 3.7 |
|
||||
| npm:pg | 3 |
|
||||
| src/lib/tz/format.ts | 2.6 |
|
||||
| npm:pg-protocol | 2.6 |
|
||||
| src/lib/analytics/source-priority.ts | 2.6 |
|
||||
| src/lib/personal-records/pr-detection-worker.ts | 1.5 |
|
||||
| src/lib/tz/zone-offset.ts | 1.5 |
|
||||
| npm:pg-types | 1.5 |
|
||||
|
||||
| inclusive, application modules | ms |
|
||||
| --- | ---: |
|
||||
| src/lib/personal-records/pr-detection-worker.ts | 9.3 |
|
||||
| src/lib/analytics/source-priority.ts | 5.3 |
|
||||
| src/lib/tz/format.ts | 4.1 |
|
||||
| src/lib/measurements/consolidation-tz.ts | 4.1 |
|
||||
| src/lib/measurements/consolidation-base.ts | 2.6 |
|
||||
| src/lib/tz/zone-offset.ts | 1.5 |
|
||||
| src/lib/validations/source-priority.ts | 1.1 |
|
||||
|
||||
### at 59508 ms, 56 ms
|
||||
|
||||
| self time by module | ms |
|
||||
| --- | ---: |
|
||||
| npm:@prisma/client | 15.7 |
|
||||
| src/lib/validations/source-priority.ts | 9.7 |
|
||||
| node:buffer | 7 |
|
||||
| (native) | 6.1 |
|
||||
| npm:pg-protocol | 4.5 |
|
||||
| npm:next | 4.1 |
|
||||
| src/lib/tz/format.ts | 3 |
|
||||
| src/lib/analytics/source-priority.ts | 3 |
|
||||
| node:internal/async_hooks | 1.5 |
|
||||
| src/lib/measurements/consolidation-base.ts | 1.5 |
|
||||
|
||||
| inclusive, application modules | ms |
|
||||
| --- | ---: |
|
||||
| src/lib/personal-records/pr-detection-worker.ts | 21.7 |
|
||||
| src/lib/analytics/source-priority.ts | 15.8 |
|
||||
| src/lib/validations/source-priority.ts | 9.7 |
|
||||
| src/lib/tz/format.ts | 5.9 |
|
||||
| src/lib/measurements/consolidation-tz.ts | 5.9 |
|
||||
| src/lib/measurements/consolidation-base.ts | 5.9 |
|
||||
| src/lib/tz/zone-offset.ts | 2.9 |
|
||||
|
||||
### at 61315 ms, 62 ms
|
||||
|
||||
| self time by module | ms |
|
||||
| --- | ---: |
|
||||
| src/lib/validations/source-priority.ts | 20.1 |
|
||||
| npm:@prisma/client | 14.1 |
|
||||
| (native) | 8.2 |
|
||||
| npm:pg | 4.5 |
|
||||
| node:buffer | 3.1 |
|
||||
| src/lib/personal-records/pr-detection-worker.ts | 3 |
|
||||
| src/lib/measurements/consolidation-base.ts | 3 |
|
||||
| npm:pg-protocol | 1.5 |
|
||||
| npm:next | 1.5 |
|
||||
| src/lib/analytics/source-priority.ts | 1.4 |
|
||||
|
||||
| inclusive, application modules | ms |
|
||||
| --- | ---: |
|
||||
| src/lib/personal-records/pr-detection-worker.ts | 30.3 |
|
||||
| src/lib/analytics/source-priority.ts | 22.8 |
|
||||
| src/lib/validations/source-priority.ts | 21.4 |
|
||||
| src/lib/measurements/consolidation-base.ts | 4.5 |
|
||||
| src/lib/tz/zone-offset.ts | 1.5 |
|
||||
| src/lib/tz/format.ts | 1.5 |
|
||||
| src/lib/measurements/consolidation-tz.ts | 1.5 |
|
||||
|
||||
### at 72986 ms, 57 ms
|
||||
|
||||
| self time by module | ms |
|
||||
| --- | ---: |
|
||||
| src/lib/validations/source-priority.ts | 19.1 |
|
||||
| npm:@prisma/client | 10.2 |
|
||||
| (native) | 6.6 |
|
||||
| npm:pg-protocol | 5.5 |
|
||||
| npm:next | 3 |
|
||||
| src/lib/analytics/source-priority.ts | 3 |
|
||||
| npm:pg | 2.5 |
|
||||
| src/lib/personal-records/pr-detection-worker.ts | 1.5 |
|
||||
| node:internal/async_local_storage/async_hooks | 1.5 |
|
||||
| src/lib/tz/format.ts | 1.5 |
|
||||
|
||||
| inclusive, application modules | ms |
|
||||
| --- | ---: |
|
||||
| src/lib/personal-records/pr-detection-worker.ts | 29.6 |
|
||||
| src/lib/analytics/source-priority.ts | 23.5 |
|
||||
| src/lib/validations/source-priority.ts | 19.1 |
|
||||
| src/lib/measurements/consolidation-base.ts | 4.6 |
|
||||
| src/lib/tz/format.ts | 4.5 |
|
||||
| src/lib/measurements/consolidation-tz.ts | 4.5 |
|
||||
| src/lib/tz/zone-offset.ts | 3 |
|
||||
|
||||
### at 73523 ms, 51 ms
|
||||
|
||||
| self time by module | ms |
|
||||
| --- | ---: |
|
||||
| src/lib/validations/source-priority.ts | 12 |
|
||||
| npm:next | 8.9 |
|
||||
| npm:@prisma/client | 6 |
|
||||
| (native) | 4.5 |
|
||||
| src/lib/analytics/source-priority.ts | 4.2 |
|
||||
| node:buffer | 4 |
|
||||
| npm:pg | 2.1 |
|
||||
| npm:pg-protocol | 1.5 |
|
||||
| src/lib/personal-records/pr-detection-worker.ts | 1.5 |
|
||||
| src/lib/tz/zone-offset.ts | 1.5 |
|
||||
|
||||
| inclusive, application modules | ms |
|
||||
| --- | ---: |
|
||||
| src/lib/personal-records/pr-detection-worker.ts | 27.8 |
|
||||
| src/lib/analytics/source-priority.ts | 17.7 |
|
||||
| src/lib/validations/source-priority.ts | 13.5 |
|
||||
| src/lib/measurements/consolidation-base.ts | 8.6 |
|
||||
| src/lib/tz/format.ts | 7.1 |
|
||||
| src/lib/measurements/consolidation-tz.ts | 7.1 |
|
||||
| src/lib/tz/zone-offset.ts | 6 |
|
||||
|
||||
### at 75393 ms, 100 ms
|
||||
|
||||
| self time by module | ms |
|
||||
| --- | ---: |
|
||||
| (native) | 32.6 |
|
||||
| npm:@prisma/client | 17.2 |
|
||||
| src/lib/validations/source-priority.ts | 14.6 |
|
||||
| npm:next | 7.5 |
|
||||
| src/lib/personal-records/pr-detection-worker.ts | 6.1 |
|
||||
| src/lib/tz/zone-offset.ts | 5.6 |
|
||||
| npm:pg-protocol | 4.1 |
|
||||
| npm:pg | 2.5 |
|
||||
| src/lib/tz/format.ts | 2.3 |
|
||||
| node:internal/async_local_storage/async_hooks | 1.5 |
|
||||
|
||||
| inclusive, application modules | ms |
|
||||
| --- | ---: |
|
||||
| src/lib/personal-records/pr-detection-worker.ts | 34.6 |
|
||||
| src/lib/analytics/source-priority.ts | 24.3 |
|
||||
| src/lib/validations/source-priority.ts | 16.1 |
|
||||
| src/lib/tz/format.ts | 10.9 |
|
||||
| src/lib/measurements/consolidation-tz.ts | 10.9 |
|
||||
| src/lib/tz/zone-offset.ts | 8.6 |
|
||||
| src/lib/measurements/consolidation-base.ts | 5.7 |
|
||||
|
||||
### at 78085 ms, 54 ms
|
||||
|
||||
| self time by module | ms |
|
||||
| --- | ---: |
|
||||
| src/lib/tz/zone-offset.ts | 26.6 |
|
||||
| src/lib/validations/source-priority.ts | 13.5 |
|
||||
| npm:@prisma/client | 4.2 |
|
||||
| (native) | 4.1 |
|
||||
| node:internal/async_local_storage/async_hooks | 1.5 |
|
||||
| src/lib/tz/format.ts | 1.5 |
|
||||
| src/lib/tz/intl-cache.ts | 1.5 |
|
||||
| npm:pg | 1.1 |
|
||||
|
||||
| inclusive, application modules | ms |
|
||||
| --- | ---: |
|
||||
| src/lib/personal-records/pr-detection-worker.ts | 44.7 |
|
||||
| src/lib/tz/format.ts | 29.6 |
|
||||
| src/lib/measurements/consolidation-tz.ts | 29.6 |
|
||||
| src/lib/measurements/consolidation-base.ts | 29.6 |
|
||||
| src/lib/tz/zone-offset.ts | 28.1 |
|
||||
| src/lib/analytics/source-priority.ts | 15 |
|
||||
| src/lib/validations/source-priority.ts | 13.5 |
|
||||
| src/lib/tz/intl-cache.ts | 1.5 |
|
||||
|
||||
## Self time by module until the worker is ready
|
||||
|
||||
| module | ms |
|
||||
| --- | ---: |
|
||||
| (native) | 853 |
|
||||
| npm:@prisma/client | 295.9 |
|
||||
| node:internal/modules/cjs/loader | 248.7 |
|
||||
| src/lib/validations/source-priority.ts | 210.3 |
|
||||
| npm:next | 188.4 |
|
||||
| turbopack:///[turbopack]/nodejs/runtime/build-base.ts | 121.5 |
|
||||
| src/lib/tz/zone-offset.ts | 83.2 |
|
||||
| wasm://wasm/00d1cb12 | 81.4 |
|
||||
| npm:pg | 78.5 |
|
||||
| node:buffer | 59.1 |
|
||||
| src/lib/tz/format.ts | 55 |
|
||||
| npm:zod | 50.7 |
|
||||
| src/lib/personal-records/pr-detection-worker.ts | 48 |
|
||||
| npm:pg-protocol | 37 |
|
||||
| node:internal/bootstrap/realm | 32 |
|
||||
| src/lib/analytics/source-priority.ts | 31.7 |
|
||||
| turbopack:///[turbopack]/shared/runtime/async-module.ts | 27.7 |
|
||||
| node:internal/modules/esm/utils | 26 |
|
||||
| npm:luxon | 22.1 |
|
||||
| node:internal/async_hooks | 21.7 |
|
||||
| node:internal/async_local_storage/async_hooks | 21.2 |
|
||||
| node:fs | 18.8 |
|
||||
| npm:pg-boss | 18.3 |
|
||||
| npm:pg-pool | 18.1 |
|
||||
| npm:yaml | 15 |
|
||||
|
||||
## Heap snapshot after 300 s idle (live heap after a full GC)
|
||||
|
||||
159.5 MB in 1302659 nodes; module source strings over 50 KB: 39.8 MB.
|
||||
|
||||
- parsed locale catalogs: 2 objects, 1.6 MB retained
|
||||
|
||||
| node type | MB |
|
||||
| --- | ---: |
|
||||
| string | 67.5 |
|
||||
| array | 26.6 |
|
||||
| code | 19.2 |
|
||||
| object | 15.9 |
|
||||
| hidden | 9.2 |
|
||||
| native | 8 |
|
||||
| object shape | 5.9 |
|
||||
| closure | 5.2 |
|
||||
| concatenated string | 1.3 |
|
||||
| number | 0.5 |
|
||||
| sliced string | 0.2 |
|
||||
| regexp | 0.2 |
|
||||
| synthetic | 0 |
|
||||
| symbol | 0 |
|
||||
| bigint | 0 |
|
||||
|
||||
| constructor | MB | count |
|
||||
| --- | ---: | ---: |
|
||||
| array:(object elements) | 20.8 | 25651 |
|
||||
| object:Object | 11.4 | 293893 |
|
||||
| native:system / JSArrayBufferData | 7.5 | 170 |
|
||||
| array:(object properties) | 3.3 | 6517 |
|
||||
| array: | 2.5 | 10169 |
|
||||
| closure: | 1.6 | 29121 |
|
||||
| object:system / Context | 1.6 | 28886 |
|
||||
| closure:native_bind | 1 | 20804 |
|
||||
| object:Array | 0.6 | 20938 |
|
||||
| object:Date1 | 0.5 | 5332 |
|
||||
| object:a | 0.4 | 4438 |
|
||||
| native:Node / histogram | 0.4 | 1 |
|
||||
| object:d | 0.3 | 4425 |
|
||||
| closure:get | 0.3 | 4732 |
|
||||
| object:Set | 0.2 | 5670 |
|
||||
| object:Module | 0.2 | 1963 |
|
||||
| closure:set | 0.2 | 3428 |
|
||||
| closure:n | 0.1 | 1572 |
|
||||
| closure:i | 0.1 | 1578 |
|
||||
| object:Promise | 0.1 | 1341 |
|
||||
|
||||
| largest retained subtrees | MB | retaining path |
|
||||
| --- | ---: | --- |
|
||||
| object:yr | 34.6 | [1] > [10] > 22 > extension > global > prisma > [1] > _engine |
|
||||
| object:system / Context | 7.4 | Node / PrincipalRealm > base_object_list > Node / BaseObjectList > [25] > Node / ModuleWrap > native_to_javascript > ModuleWrap > 2 > [4] > context |
|
||||
| object:Promise | 5.9 | Object > executor > e > #r > gr > transactions > Map > table > > 6 > closing |
|
||||
| object:Module | 5.6 | [1] > [10] > 99 > process > getBuiltinModule > getBuiltinModule > context > system / Context > $Module > Module > _cache > |
|
||||
| code:.next/server/chu | 5.6 | Module > _cache > Object > .next/server/chunks/_1kwfnjg._.js > Module > exports > Array > [1] > > shared > script |
|
||||
| code:.next/server/chu | 5.6 | global > prisma > [1] > t > _engineConfig > Object > compilerWasm > Object > getRuntime > getRuntime > shared > script |
|
||||
| object:Generator | 4.4 | [6] > principal_realm > Node / PrincipalRealm > base_object_list > Node / BaseObjectList > [26] > Node / ModuleWrap > native_to_javascript > ModuleWrap > 2 > [4 |
|
||||
| string:AGFzbQEAAAABtgRLYAN/f38Bf2ACf38Bf2ACf38AYAF/AGADf39/AGAEf39/ | 4.4 | [1] > [21] > 60025 |
|
||||
| object:Object | 3.4 | system / Context > $Module > Module > _cache > Object > .next/server/chunks/[turbopack]_runtime.js > Module > export |
|
||||
| object:global | 2.6 | [1] > [10] > 22 > extension |
|
||||
|
||||
| largest strings | MB |
|
||||
| --- | ---: |
|
||||
| module.exports=[234494,A=>{"use strict";var e,C,g,I,Q=Object.defineProperty,B={},s={$:()=> | 5.6 |
|
||||
| module.exports=[17856,A=>{"use strict";var e,C,g,I,Q=Object.defineProperty,B={},s={$:()=>i | 5.6 |
|
||||
| module.exports=[17856,A=>{"use strict";var e,C,g,I,Q=Object.defineProperty,B={},s={$:()=>i | 5.6 |
|
||||
| const wasm = "AGFzbQEAAAABtgRLYAN/f38Bf2ACf38Bf2ACf38AYAF/AGADf39/AGAEf39/fwBgBX9/f39/AGAB | 4.4 |
|
||||
| AGFzbQEAAAABtgRLYAN/f38Bf2ACf38Bf2ACf38AYAF/AGADf39/AGAEf39/fwBgBX9/f39/AGABfwF/YAZ/f39/f3 | 4.4 |
|
||||
| lliADOAUngIEAACgKwAgBgAAoSsAIAcAAKErACAIAACiKwAgCQAAoysAIAoAAKQrACALAAClKwAgDAAApisAIA0AAK | 1.9 |
|
||||
| (()=>{var e,t,r={"./dist/build/webpack/alias/react-dom-server.js"(e,t,r){"use strict";var | 1.3 |
|
||||
| module.exports=[842865,(e,t,r)=>{let i=e.r(522734);t.exports=function(e){return e?/-----BE | 1.2 |
|
||||
| module.exports=[842865,(e,t,r)=>{let i=e.r(522734);t.exports=function(e){return e?/-----BE | 1.2 |
|
||||
| module.exports=[799092,(e,t,n)=>{"use strict";Object.defineProperty(n,"__esModule",{value: | 1.1 |
|
||||
| // v1.4.34 web-freeze. Schema is locked additive-only until iOS launch // + v1.5.0 marker. | 1.1 |
|
||||
| module.exports=[971743,(A,e,t)=>{"use strict";let r=A.r(57328),{addAbortListener:s}=A.r(68 | 1.1 |
|
||||
| module.exports=[835717,(A,e,t)=>{"use strict";let r=A.r(57328),{addAbortListener:s}=A.r(68 | 1 |
|
||||
| module.exports=[767189,e=>e.a(async(t,a)=>{try{var n=e.i(64105),r=e.i(563616),i=t([n]);[n] | 0.8 |
|
||||
| module.exports=[594108,806176,674750,98746,t=>{"use strict";var i;let r;function n(t){retu | 0.7 |
|
||||
@@ -0,0 +1,28 @@
|
||||
# v1.45.0: boot and idle memory
|
||||
|
||||
`scripts/bench/boot-profile.ts`, production build, every role, heap ceiling
|
||||
792 MB, against the seeded account, 300 s idle. `v1.45.0-before-boot` is the
|
||||
v1.44 runtime, `v1.45.0-boot-after` the branch after the boot changes and
|
||||
before the lazy match indexes, `v1.45.0-boot-final` the final tree.
|
||||
|
||||
| | before | final |
|
||||
| --- | ---: | ---: |
|
||||
| longest main-thread busy stretch, application code | 753 ms (worker graph, one block) | 336 ms (query compiler start, 324 ms before as well) |
|
||||
| longest stretch loading the worker graph | 753 ms | 246 ms (one registrar) |
|
||||
| live heap after full collections, idle | 162 to 172 MB | 142 to 153 MB |
|
||||
| heap snapshot after 300 s idle | 172.3 MB | 159.5 MB |
|
||||
| parsed locale catalogs in the heap | 32 objects, 14.1 MB | 2 objects, 1.6 MB |
|
||||
| catalog chunk sources in the heap | 2 x 9.7 MB | none |
|
||||
| module source strings over 50 KB | 44.2 MB | 39.8 MB |
|
||||
| event-loop stalls logged (500 ms threshold) | 0 (monitor started late) | 0 (monitor first) |
|
||||
|
||||
Time to the first health answer and to a ready worker moved with the host's
|
||||
load (1.6 s / 5.4 s before at load 9, 1.3 s / 3.2 s after at load 6) and is
|
||||
not claimed as a result.
|
||||
|
||||
The rest of the 150 MB is the runtime itself: the query compiler (about
|
||||
50 MB: its engine object, its WebAssembly source and chunk, twice), compiled
|
||||
code (19 MB) and the remaining module sources. The used heap between full
|
||||
collections stayed under 240 MB in both runs; the beta's 400 MB plateau is
|
||||
garbage awaiting a collection under a larger limit plus the server caches of
|
||||
real users, not a baseline the process cannot shed.
|
||||
@@ -0,0 +1,22 @@
|
||||
# v1.45.0: request fan-out
|
||||
|
||||
Same runs as `v1.45.0-read-path.md`.
|
||||
|
||||
| request | statements before | statements after | p50 ms before / after |
|
||||
| --- | ---: | ---: | ---: |
|
||||
| /api/auth/me | 19 | 14 | 9 / 8 |
|
||||
| day view, cold | 49 | 48 | 77 / 68 |
|
||||
|
||||
- `/api/auth/me` read the AppSettings singleton six times (MFA policy,
|
||||
Assistant switches, module availability, provider presence, AI usage
|
||||
bounds, reasoning controls); one memoised read per request now serves all
|
||||
six (`src/lib/settings/operator-row.ts`). On the small budget fixture it
|
||||
went from 18 to 13 statements. The remaining reads are the session, the
|
||||
grant, cycle profile, onboarding, consent, coach usage and five user reads
|
||||
with different column sets.
|
||||
- The day view's record sections run six at a time instead of about
|
||||
twenty-five at once, so one day never holds more than a third of the pool.
|
||||
The statement count is the same; what changes is the peak of connections.
|
||||
- Keyset pagination for `/api/measurements` was not done: a cursor needs a
|
||||
new request parameter and a response field, a contract change for the
|
||||
native client.
|
||||
@@ -0,0 +1,254 @@
|
||||
{
|
||||
"meta": {
|
||||
"label": "v1.45.0-final",
|
||||
"commit": "a57fa8335",
|
||||
"date": "2026-10-22T06:52:09.539Z",
|
||||
"node": "v22.23.2",
|
||||
"postgres": "16.15",
|
||||
"cpus": 14,
|
||||
"loadAverage": [
|
||||
6.8,
|
||||
8.9,
|
||||
14.5
|
||||
],
|
||||
"measurements": 1265561,
|
||||
"iterations": 20,
|
||||
"warmup": 3,
|
||||
"heapMb": 792,
|
||||
"idleStatementsPerSecond": 0,
|
||||
"batch5k": {
|
||||
"totalMs": 4448,
|
||||
"totalStatements": 504
|
||||
}
|
||||
},
|
||||
"results": [
|
||||
{
|
||||
"name": "/api/auth/me",
|
||||
"mode": "cold",
|
||||
"request": "GET /api/auth/me",
|
||||
"n": 20,
|
||||
"p50Ms": 8.3,
|
||||
"p95Ms": 27.2,
|
||||
"maxMs": 221,
|
||||
"statementsMedian": 14,
|
||||
"statementsMax": 14,
|
||||
"failures": 0
|
||||
},
|
||||
{
|
||||
"name": "/api/auth/me",
|
||||
"mode": "warm",
|
||||
"request": "GET /api/auth/me",
|
||||
"n": 20,
|
||||
"p50Ms": 7.9,
|
||||
"p95Ms": 10.1,
|
||||
"maxMs": 17.1,
|
||||
"statementsMedian": 14,
|
||||
"statementsMax": 17,
|
||||
"failures": 0
|
||||
},
|
||||
{
|
||||
"name": "dashboard summary",
|
||||
"mode": "cold",
|
||||
"request": "GET /api/dashboard/summary",
|
||||
"n": 20,
|
||||
"p50Ms": 86.6,
|
||||
"p95Ms": 100.8,
|
||||
"maxMs": 126.8,
|
||||
"statementsMedian": 30,
|
||||
"statementsMax": 31,
|
||||
"failures": 0
|
||||
},
|
||||
{
|
||||
"name": "dashboard summary",
|
||||
"mode": "warm",
|
||||
"request": "GET /api/dashboard/summary",
|
||||
"n": 20,
|
||||
"p50Ms": 9.2,
|
||||
"p95Ms": 17.1,
|
||||
"maxMs": 18.4,
|
||||
"statementsMedian": 6,
|
||||
"statementsMax": 6,
|
||||
"failures": 0
|
||||
},
|
||||
{
|
||||
"name": "dashboard snapshot",
|
||||
"mode": "cold",
|
||||
"request": "GET /api/dashboard/snapshot",
|
||||
"n": 20,
|
||||
"p50Ms": 545.3,
|
||||
"p95Ms": 592.5,
|
||||
"maxMs": 606.3,
|
||||
"statementsMedian": 153,
|
||||
"statementsMax": 156,
|
||||
"failures": 0
|
||||
},
|
||||
{
|
||||
"name": "dashboard snapshot",
|
||||
"mode": "warm",
|
||||
"request": "GET /api/dashboard/snapshot",
|
||||
"n": 20,
|
||||
"p50Ms": 8.1,
|
||||
"p95Ms": 17.9,
|
||||
"maxMs": 21.9,
|
||||
"statementsMedian": 10,
|
||||
"statementsMax": 10,
|
||||
"failures": 0
|
||||
},
|
||||
{
|
||||
"name": "series pulse 30 d",
|
||||
"mode": "cold",
|
||||
"request": "GET /api/measurements/series?kind=pulse&days=30",
|
||||
"n": 20,
|
||||
"p50Ms": 18.7,
|
||||
"p95Ms": 27.2,
|
||||
"maxMs": 36.1,
|
||||
"statementsMedian": 8,
|
||||
"statementsMax": 8,
|
||||
"failures": 0
|
||||
},
|
||||
{
|
||||
"name": "series pulse 30 d",
|
||||
"mode": "warm",
|
||||
"request": "GET /api/measurements/series?kind=pulse&days=30",
|
||||
"n": 20,
|
||||
"p50Ms": 15.9,
|
||||
"p95Ms": 21.8,
|
||||
"maxMs": 26,
|
||||
"statementsMedian": 8,
|
||||
"statementsMax": 8,
|
||||
"failures": 0
|
||||
},
|
||||
{
|
||||
"name": "series pulse 365 d",
|
||||
"mode": "cold",
|
||||
"request": "GET /api/measurements/series?kind=pulse&days=365",
|
||||
"n": 20,
|
||||
"p50Ms": 40.7,
|
||||
"p95Ms": 55.6,
|
||||
"maxMs": 56.2,
|
||||
"statementsMedian": 7,
|
||||
"statementsMax": 8,
|
||||
"failures": 0
|
||||
},
|
||||
{
|
||||
"name": "series pulse 365 d",
|
||||
"mode": "warm",
|
||||
"request": "GET /api/measurements/series?kind=pulse&days=365",
|
||||
"n": 20,
|
||||
"p50Ms": 38.3,
|
||||
"p95Ms": 59.6,
|
||||
"maxMs": 88.6,
|
||||
"statementsMedian": 7,
|
||||
"statementsMax": 7,
|
||||
"failures": 0
|
||||
},
|
||||
{
|
||||
"name": "series pulse 3650 d",
|
||||
"mode": "cold",
|
||||
"request": "GET /api/measurements/series?kind=pulse&days=3650",
|
||||
"n": 20,
|
||||
"p50Ms": 334.9,
|
||||
"p95Ms": 348.5,
|
||||
"maxMs": 351.2,
|
||||
"statementsMedian": 7,
|
||||
"statementsMax": 7,
|
||||
"failures": 0
|
||||
},
|
||||
{
|
||||
"name": "series pulse 3650 d",
|
||||
"mode": "warm",
|
||||
"request": "GET /api/measurements/series?kind=pulse&days=3650",
|
||||
"n": 20,
|
||||
"p50Ms": 328.1,
|
||||
"p95Ms": 346,
|
||||
"maxMs": 348.9,
|
||||
"statementsMedian": 7,
|
||||
"statementsMax": 8,
|
||||
"failures": 0
|
||||
},
|
||||
{
|
||||
"name": "day view",
|
||||
"mode": "cold",
|
||||
"request": "GET /api/day/2026-10-21",
|
||||
"n": 20,
|
||||
"p50Ms": 68.4,
|
||||
"p95Ms": 102.6,
|
||||
"maxMs": 104.7,
|
||||
"statementsMedian": 48,
|
||||
"statementsMax": 49,
|
||||
"failures": 0
|
||||
},
|
||||
{
|
||||
"name": "day view",
|
||||
"mode": "warm",
|
||||
"request": "GET /api/day/2026-10-21",
|
||||
"n": 20,
|
||||
"p50Ms": 46.4,
|
||||
"p95Ms": 66.1,
|
||||
"maxMs": 72.6,
|
||||
"statementsMedian": 47,
|
||||
"statementsMax": 47,
|
||||
"failures": 0
|
||||
},
|
||||
{
|
||||
"name": "insights health status",
|
||||
"mode": "cold",
|
||||
"request": "GET /api/insights/health-status",
|
||||
"n": 20,
|
||||
"p50Ms": 156,
|
||||
"p95Ms": 190,
|
||||
"maxMs": 197.7,
|
||||
"statementsMedian": 67,
|
||||
"statementsMax": 67,
|
||||
"failures": 0
|
||||
},
|
||||
{
|
||||
"name": "insights health status",
|
||||
"mode": "warm",
|
||||
"request": "GET /api/insights/health-status",
|
||||
"n": 20,
|
||||
"p50Ms": 173.6,
|
||||
"p95Ms": 1163.4,
|
||||
"maxMs": 1419.4,
|
||||
"statementsMedian": 67,
|
||||
"statementsMax": 67,
|
||||
"failures": 0
|
||||
},
|
||||
{
|
||||
"name": "insights correlations",
|
||||
"mode": "cold",
|
||||
"request": "GET /api/insights/correlations",
|
||||
"n": 20,
|
||||
"p50Ms": 106.1,
|
||||
"p95Ms": 229.1,
|
||||
"maxMs": 383.3,
|
||||
"statementsMedian": 48,
|
||||
"statementsMax": 49,
|
||||
"failures": 0
|
||||
},
|
||||
{
|
||||
"name": "insights correlations",
|
||||
"mode": "warm",
|
||||
"request": "GET /api/insights/correlations",
|
||||
"n": 20,
|
||||
"p50Ms": 18.7,
|
||||
"p95Ms": 626.6,
|
||||
"maxMs": 1136.5,
|
||||
"statementsMedian": 7,
|
||||
"statementsMax": 7,
|
||||
"failures": 0
|
||||
},
|
||||
{
|
||||
"name": "batch ingest 5k (per 500)",
|
||||
"mode": "write",
|
||||
"request": "POST /api/measurements/batch ×10",
|
||||
"n": 10,
|
||||
"p50Ms": 185.7,
|
||||
"p95Ms": 1269.2,
|
||||
"maxMs": 1269.2,
|
||||
"statementsMedian": 50,
|
||||
"statementsMax": 53,
|
||||
"failures": 0
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
# Benchmark v1.45.0-final
|
||||
|
||||
Commit a57fa8335 with the working tree of the final commits, 2026-10-22T06:52:09.539Z. 1265561 measurement rows on the bench account, 20 measured requests per row after 3 warm-up requests, one at a time. Server: production build, web process, heap ceiling 792 MB. Postgres 16.15, 14 cores, load average 6.8,8.9,14.5 at the end. Idle background: 0 statements/s.
|
||||
|
||||
| Request | Mode | n | p50 ms | p95 ms | max ms | statements (median) | statements (max) |
|
||||
| --- | --- | ---: | ---: | ---: | ---: | ---: | ---: |
|
||||
| /api/auth/me | cold | 20 | 8.3 | 27.2 | 221 | 14 | 14 |
|
||||
| /api/auth/me | warm | 20 | 7.9 | 10.1 | 17.1 | 14 | 17 |
|
||||
| dashboard summary | cold | 20 | 86.6 | 100.8 | 126.8 | 30 | 31 |
|
||||
| dashboard summary | warm | 20 | 9.2 | 17.1 | 18.4 | 6 | 6 |
|
||||
| dashboard snapshot | cold | 20 | 545.3 | 592.5 | 606.3 | 153 | 156 |
|
||||
| dashboard snapshot | warm | 20 | 8.1 | 17.9 | 21.9 | 10 | 10 |
|
||||
| series pulse 30 d | cold | 20 | 18.7 | 27.2 | 36.1 | 8 | 8 |
|
||||
| series pulse 30 d | warm | 20 | 15.9 | 21.8 | 26 | 8 | 8 |
|
||||
| series pulse 365 d | cold | 20 | 40.7 | 55.6 | 56.2 | 7 | 8 |
|
||||
| series pulse 365 d | warm | 20 | 38.3 | 59.6 | 88.6 | 7 | 7 |
|
||||
| series pulse 3650 d | cold | 20 | 334.9 | 348.5 | 351.2 | 7 | 7 |
|
||||
| series pulse 3650 d | warm | 20 | 328.1 | 346 | 348.9 | 7 | 8 |
|
||||
| day view | cold | 20 | 68.4 | 102.6 | 104.7 | 48 | 49 |
|
||||
| day view | warm | 20 | 46.4 | 66.1 | 72.6 | 47 | 47 |
|
||||
| insights health status | cold | 20 | 156 | 190 | 197.7 | 67 | 67 |
|
||||
| insights health status | warm | 20 | 173.6 | 1163.4 | 1419.4 | 67 | 67 |
|
||||
| insights correlations | cold | 20 | 106.1 | 229.1 | 383.3 | 48 | 49 |
|
||||
| insights correlations | warm | 20 | 18.7 | 626.6 | 1136.5 | 7 | 7 |
|
||||
| batch ingest 5k (per 500) | write | 10 | 185.7 | 1269.2 | 1269.2 | 50 | 53 |
|
||||
@@ -0,0 +1,45 @@
|
||||
# v1.45.0: read path
|
||||
|
||||
Request benchmark on the seeded account (1,265,561 rows), production build,
|
||||
web process, heap ceiling 792 MB, 20 requests per row, one at a time.
|
||||
`v1.45.0-before` is the v1.44 runtime (1915f9152), `v1.45.0-final` this
|
||||
branch; both on the same machine within the hour, load average 7 to 30
|
||||
(other work on the host), so latency compares within a factor of noise and
|
||||
statements exactly. Cold means every request follows a one-row manual sync.
|
||||
|
||||
| request | before p50 / p95 ms | after p50 / p95 ms | statements before / after |
|
||||
| --- | ---: | ---: | ---: |
|
||||
| dashboard snapshot, cold | 1482 / 1526 | 545 / 593 | 158 / 153 |
|
||||
| dashboard summary, cold | 170 / 221 | 87 / 101 | 31 / 30 |
|
||||
| series pulse 3650 d, cold | 1627 / 1665 | 335 / 349 | 8 / 7 |
|
||||
| series pulse 3650 d, warm | 2091 / 2435 | 328 / 346 | 8 / 7 |
|
||||
| series pulse 365 d, cold | 184 / 193 | 41 / 56 | 8 / 7 |
|
||||
| series pulse 30 d, cold | 24 / 31 | 19 / 27 | 8 / 8 |
|
||||
| insights health status, cold | 245 / 401 | 156 / 190 | 68 / 67 |
|
||||
|
||||
What moved them:
|
||||
|
||||
- **JIT off for app sessions.** Postgres compiled every fold whose estimated
|
||||
cost passed `jit_above_cost`; on the ten-year pulse pick that was 100 to
|
||||
140 ms of a 220 ms statement (`EXPLAIN ANALYZE`: 395 ms with JIT, 220 ms
|
||||
without).
|
||||
- **The canonical-source pick groups first.** `DISTINCT ON` now sorts the
|
||||
distinct `(type, day, source)` triples instead of every raw reading (the
|
||||
ten-year pulse pick sorted 260,000 rows and spilled to disk); 220 ms to
|
||||
175 ms on its own. Parity: `tests/integration/canonical-source-pick-parity.test.ts`
|
||||
runs the old statement beside the new one over five reader shapes and two
|
||||
ladders on a fixture with overlapping and off-ladder sources, tombstones,
|
||||
empty days and readings around midnight; identical rows.
|
||||
- **The dense series reads its rows once.** Buckets and strip figures come
|
||||
from one statement over a materialised window instead of two statements
|
||||
that each picked the canonical source and scanned the readings. Parity:
|
||||
`tests/integration/dense-series-read-parity.test.ts`, the two old
|
||||
statements as reference, pulse (two ranked sources), glucose and oxygen
|
||||
saturation, day and hour grains, UTC, Europe/Berlin, Asia/Kolkata and
|
||||
America/New_York; identical buckets and figures (relative 1e-9).
|
||||
- **Closed blocks survive a sync.** The slice's pre-fold remainder (every
|
||||
reading older than five years, the snapshot's largest statement at 357 ms)
|
||||
and the day view's past history blocks are cached under a key that names
|
||||
the instant their readings end before; a sync of newer readings no longer
|
||||
drops them (`src/lib/cache/closed-block.ts`). The values are the same
|
||||
statement's; only how long they are kept changed.
|
||||
@@ -0,0 +1,28 @@
|
||||
# v1.45.0: workout duplicate window
|
||||
|
||||
A correctness change, not a speed one; the request benchmark does not read
|
||||
workouts, so there is no latency row for it.
|
||||
|
||||
Before: two copies of one session were collapsed only when both starts fell
|
||||
in the same fixed five-minute clock slot (`floor(start / 5 min)`). A pair 30 s
|
||||
apart that straddled a slot boundary stayed two workouts in the list, the
|
||||
batch write, the calendar, strain and the Coach.
|
||||
|
||||
After: per user and sport, sorted by start, a workout joins the open cluster
|
||||
while it starts less than five minutes after the cluster's first start.
|
||||
|
||||
Proof (`src/lib/measurements/__tests__/pick-canonical-workout-rows.property.test.ts`,
|
||||
against the previous picker kept as `pick-canonical-workout-rows.legacy.ts`):
|
||||
|
||||
| property | inputs |
|
||||
| --- | --- |
|
||||
| same rows as the fixed slots wherever no pair within five minutes straddles a slot boundary, three ladders | 4,000 generated inputs, over 1,000 comparable |
|
||||
| same strain impulses as before on those inputs | 2,000 generated inputs, over 500 comparable |
|
||||
| two sources' copies collapse at any offset under five minutes (the old picker missed a share) | 3,000 random offsets |
|
||||
| five minutes or more apart never collapse | 2,000 |
|
||||
| a uniform shift of every start keeps the picked set | 1,500 |
|
||||
| a row of workouts four minutes apart does not chain | fixed case |
|
||||
|
||||
One existing case changed its expectation: three runs at 08:04, 08:08 and
|
||||
08:12 used to stay three because they sat in three slots; 08:08 is now the
|
||||
08:04 run from a lower-ranked source (four minutes apart), and 08:12 stays.
|
||||
@@ -0,0 +1,26 @@
|
||||
# v1.45.0: write path
|
||||
|
||||
Same runs as `v1.45.0-read-path.md`.
|
||||
|
||||
| request | before p50 ms | after p50 ms | statements before / after |
|
||||
| --- | ---: | ---: | ---: |
|
||||
| batch ingest, 500 fresh rows per request | 166 | 186 | 53 / 50 |
|
||||
|
||||
Fresh rows were already set-based (v1.44); the benchmark's ingest is all
|
||||
fresh rows, so it shows no gain, as expected. The changes are for re-posts:
|
||||
|
||||
- **Unchanged `stats:` re-posts** write nothing and start nothing. One read
|
||||
over the batch's `stats:` ids replaces a reconciler transaction (about ten
|
||||
round trips) per row, and an all-unchanged batch no longer refolds, enqueues
|
||||
rollups or PR detection, or marks caches stale. The per-entry status stays
|
||||
`updated` and the summary's `updated` count is unchanged.
|
||||
`tests/integration/routes/measurements-batch-unchanged-stats.test.ts`: four
|
||||
unchanged re-posts take at most 12 statements in total (before: about 40)
|
||||
with zero rollup, invalidation and PR calls; a changed value, a changed
|
||||
device or a tombstoned row still goes through the reconciler.
|
||||
- **Apple Health re-import** skips the UPDATE of a row stored with exactly the
|
||||
values it would write; one read per chunk instead of one UPDATE per row.
|
||||
`tests/integration/apple-health-reimport-unchanged.test.ts`: a re-import of
|
||||
20 stored rows reports the same per-type counts and sends no UPDATE.
|
||||
- **Narrower invalidation.** The batch route tells the cache how far back it
|
||||
wrote (`touchedFrom`), so closed blocks of older readings stay.
|
||||
@@ -1,14 +1,13 @@
|
||||
{
|
||||
"$comment": "Production files over 800 lines and their length. Maintained by src/__tests__/source-size-ratchet.test.ts.",
|
||||
"count": 129,
|
||||
"total": 156380,
|
||||
"count": 128,
|
||||
"total": 155494,
|
||||
"entries": {
|
||||
"app/api/dashboard/summary/route.ts": 1032,
|
||||
"app/api/documents/inbound/route.ts": 811,
|
||||
"app/api/insights/generate/route.ts": 1209,
|
||||
"app/api/measurements/batch/route.ts": 1569,
|
||||
"app/api/measurements/route.ts": 938,
|
||||
"app/api/measurements/series/route.ts": 879,
|
||||
"app/api/medications/[id]/route.ts": 1281,
|
||||
"app/api/medications/intake/bulk/route.ts": 1044,
|
||||
"app/api/workouts/batch/route.ts": 971,
|
||||
@@ -113,7 +112,7 @@
|
||||
"lib/mcp/rich-reads.ts": 1467,
|
||||
"lib/mcp/tools.ts": 2654,
|
||||
"lib/measurements/dense-intraday-retention.ts": 1057,
|
||||
"lib/measurements/import-apple-health-export.ts": 1729,
|
||||
"lib/measurements/import-apple-health-export.ts": 1722,
|
||||
"lib/medications/scheduling/cadence.ts": 978,
|
||||
"lib/medications/scheduling/recurrence.ts": 1108,
|
||||
"lib/medications/scheduling/slot-upsert.ts": 926,
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"$comment": "Production functions over 200 lines, keyed \"file :: name\", and their length. Maintained by src/__tests__/source-size-ratchet.test.ts.",
|
||||
"count": 415,
|
||||
"total": 154564,
|
||||
"total": 154432,
|
||||
"entries": {
|
||||
"app/achievements/page.tsx :: AchievementsPage": 206,
|
||||
"app/api/admin/backups/upload/route.ts :: apiHandler(arg)": 314,
|
||||
@@ -41,7 +41,7 @@
|
||||
"app/api/measurements/batch/route.ts :: postBatch": 1262,
|
||||
"app/api/measurements/route.ts :: apiHandler(arg)": 286,
|
||||
"app/api/measurements/route.ts :: postMeasurement": 377,
|
||||
"app/api/measurements/series/route.ts :: apiHandler(arg)": 670,
|
||||
"app/api/measurements/series/route.ts :: apiHandler(arg)": 549,
|
||||
"app/api/medications/[id]/dose-history/route.ts :: apiHandler(arg)": 256,
|
||||
"app/api/medications/[id]/intake/[eventId]/route.ts :: apiHandler(arg)": 390,
|
||||
"app/api/medications/[id]/intake/route.ts :: postIntake": 607,
|
||||
@@ -394,7 +394,7 @@
|
||||
"lib/measurements/dense-intraday-retention.ts :: runDenseIntradayRetention > walkSource > writeDay > foldOnce": 212,
|
||||
"lib/measurements/drain-per-sample-cumulative.ts :: drainPerSampleCumulative": 344,
|
||||
"lib/measurements/drain-per-sample-cumulative.ts :: drainPerSampleCumulative > writeDay": 205,
|
||||
"lib/measurements/import-apple-health-export.ts :: streamParseExportXml": 1256,
|
||||
"lib/measurements/import-apple-health-export.ts :: streamParseExportXml": 1245,
|
||||
"lib/measurements/import-apple-health-export.ts :: streamParseExportXml > (anonymous) #2": 323,
|
||||
"lib/medications/efficacy/build-efficacy.ts :: buildMedicationEfficacy": 268,
|
||||
"lib/medications/intake-slot-dedup.ts :: dedupeUserIntakeSlots": 321,
|
||||
|
||||
@@ -64,8 +64,9 @@ export async function register() {
|
||||
// Without the mirror the process keeps the default method.
|
||||
}
|
||||
|
||||
// Every Node process watches its heap as it watches its event loop: a trend line, and one report naming the work in
|
||||
// flight before the heap runs out (a heap-limit crash logs nothing else).
|
||||
// Every Node process watches its heap as it watches its event loop: a
|
||||
// trend line, and one report naming the work in flight before the heap
|
||||
// runs out (a heap-limit crash logs nothing else).
|
||||
beginBootStep("monitors");
|
||||
try {
|
||||
const [{ startHttpInFlightTracking }, { startHeapMonitor }] =
|
||||
|
||||
Reference in new issue
Block a user