From c0321d2f27f0d04c990178eacb32caafc5b9a8f2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Bombeck?= Date: Wed, 29 Jul 2026 14:31:01 +0200 Subject: [PATCH] test(01-15): add bounded performance fixture baseline - benchmark observed Google, reminder, and score workload shapes - record local cold and warm timing without production access --- .../01-PERFORMANCE-BASELINE.md | 67 ++++ scripts/v1341-performance-baseline.mjs | 343 ++++++++++++++++++ 2 files changed, 410 insertions(+) create mode 100644 .planning/phases/01-v1-34-1-dashboard-insights-records-admin-and-integration-reliability/01-PERFORMANCE-BASELINE.md create mode 100644 scripts/v1341-performance-baseline.mjs diff --git a/.planning/phases/01-v1-34-1-dashboard-insights-records-admin-and-integration-reliability/01-PERFORMANCE-BASELINE.md b/.planning/phases/01-v1-34-1-dashboard-insights-records-admin-and-integration-reliability/01-PERFORMANCE-BASELINE.md new file mode 100644 index 000000000..73cab0777 --- /dev/null +++ b/.planning/phases/01-v1-34-1-dashboard-insights-records-admin-and-integration-reliability/01-PERFORMANCE-BASELINE.md @@ -0,0 +1,67 @@ +# v1.34.1 Performance Baseline + +**Generated:** 2026-07-29T12:30:52.301Z +**Commit:** `c0af97ce4` +**Exit status:** PASS +**Mode:** deterministic local fixture only + +## Safety and interpretation + +- No network, database, provider, production, or staging endpoint was contacted. +- Fixtures contain generated counters only. The report emits no tokens, identifiers, payloads, health values, hostnames, usernames, or working-directory paths. +- Concurrency is fixed at one, warm sample count is 11, and the whole run has a 30-second deadline. +- Timing is a local code-shape baseline, not a production latency or capacity claim. Database, provider, network, framework, cache, and rendering costs remain unmeasured. +- The Health Score fixture exercises dense/sparse row construction, source canonicalization, and a stable composite proxy. It does not replace production algorithm parity or database-backed performance tests. + +## Environment + +| Attribute | Value | +| --- | --- | +| Node | v25.9.0 | +| Platform | darwin 25.3.0 | +| Architecture | arm64 | +| Logical CPUs | 14 | +| Process | single local Node process | +| Total harness duration | 100.435 ms | + +## Fixture scale + +| Path shape | Fixed scale | +| --- | --- | +| Google history | 786 serial pages × 32 generated rows; terminal page has no remaining token | +| Reminder cohort | 2000 medications × 4 slots plus 2000 cleanup records | +| Health Score | 42 dense days × 1440 samples plus 379 sparse days × 8 samples | + +## Measurements + +| Local path shape | Cold | Warm median | Warm p95 | Warm max | Cold heap delta | Max warm heap delta | +| --- | ---: | ---: | ---: | ---: | ---: | ---: | +| Google history pagination shape | 7.462 ms | 5.283 ms | 5.860 ms | 5.860 ms | 2.00 MiB | 6.19 MiB | +| Medication reminder cohort shape | 0.773 ms | 0.080 ms | 0.971 ms | 0.971 ms | 0.19 MiB | 0.07 MiB | +| Health Score read/canonicalization shape | 3.982 ms | 2.280 ms | 3.384 ms | 3.384 ms | 7.09 MiB | 7.30 MiB | + +### Determinism and bounded counters + +- **Google history pagination shape:** checksum `47f760c2`; pages=786; rows=25152; concurrency=1; finalTokenPresent=false. +- **Medication reminder cohort shape:** checksum `73e03617`; medications=2000; slots=8000; cleanupBacklog=2000; dueCandidates=1582; modeledQueries=7165; concurrency=1. +- **Health Score read/canonicalization shape:** checksum `5c395b1a`; denseRows=60480; sparseRows=3032; canonicalDays=42; domains=8; concurrency=1; parity=stable-checksum. + +## Route/path interpretation + +| Representative path | What this fixture measures | What it does not measure | +| --- | --- | --- | +| Google full-sync pagination | Serial JSON page materialization and accumulation at the observed 786-page shape | Provider latency, DB writes, token refresh, rollups, or a safe universal page ceiling | +| Medication reminder worker | Serial cohort/slot decisions, cleanup scan, and modeled query amplification | Prisma latency, locks, dispatch latency, or the live cohort size | +| Dashboard / analytics Health Score | Dense/sparse row processing, canonical selection, and stable composite proxy | SQL plans, cache behavior, exact production score parity, or user-visible route latency | + +## Hypotheses and unmeasured risks + +- **Hypothesis:** Serial provider latency and write statements dominate the Google full-sync wall time; this local CPU result neither confirms nor refutes that hypothesis. +- **Hypothesis:** Reminder query/dispatch amplification, not local loop cost, determines whether a high-water pass approaches its 15-minute cadence. +- **Hypothesis:** Cold database row materialization and canonicalization dominate dense-user Health Score work; production impact remains unconfirmed. +- **Unmeasured:** network and database tails, cache hit/miss ratios, cross-process invalidation, framework rendering, device/browser performance, and production cohort distributions. +- **Do not infer:** a provider defect, a safe page cap, a production regression, or permission to optimize from this report alone. + +## Reproduction + +`node scripts/v1341-performance-baseline.mjs --fixture --output .planning/phases/01-v1-34-1-dashboard-insights-records-admin-and-integration-reliability/01-PERFORMANCE-BASELINE.md` diff --git a/scripts/v1341-performance-baseline.mjs b/scripts/v1341-performance-baseline.mjs new file mode 100644 index 000000000..0ed69da37 --- /dev/null +++ b/scripts/v1341-performance-baseline.mjs @@ -0,0 +1,343 @@ +#!/usr/bin/env node + +import { execFileSync } from "node:child_process"; +import { writeFileSync } from "node:fs"; +import { arch, cpus, platform, release } from "node:os"; +import { resolve } from "node:path"; +import { performance } from "node:perf_hooks"; + +const LIMITS = Object.freeze({ + deadlineMs: 30_000, + warmSamples: 11, + googlePages: 786, + googleRowsPerPage: 32, + reminderMedications: 2_000, + reminderSlotsPerMedication: 4, + reminderCleanupBacklog: 2_000, + healthDenseDays: 42, + healthSamplesPerDay: 1_440, + healthSparseDays: 379, + healthSparseSamplesPerDay: 8, +}); + +const args = process.argv.slice(2); +const fixtureMode = args.includes("--fixture"); +const outputIndex = args.indexOf("--output"); +const outputPath = + outputIndex >= 0 && args[outputIndex + 1] + ? resolve(args[outputIndex + 1]) + : null; + +function fail(message) { + console.error(`v1341-performance-baseline: ${message}`); + process.exit(2); +} + +if (!fixtureMode) { + fail("refusing to run without --fixture; live and production probes are unsupported"); +} +if (process.env.NODE_ENV === "production") { + fail("refusing to run with NODE_ENV=production"); +} +if (!outputPath) { + fail("--output is required"); +} +if (args.some((arg) => /^(--url|--host|--database|--token|--live)/.test(arg))) { + fail("network, database, credential, and live-target arguments are unsupported"); +} + +const startedAt = performance.now(); +const deadlineAt = startedAt + LIMITS.deadlineMs; + +function assertWithinDeadline() { + if (performance.now() > deadlineAt) { + throw new Error(`fixture deadline exceeded (${LIMITS.deadlineMs} ms)`); + } +} + +function seededNumber(index, salt) { + let value = (index + 1) ^ salt; + value = Math.imul(value ^ (value >>> 16), 0x45d9f3b); + value = Math.imul(value ^ (value >>> 16), 0x45d9f3b); + return (value ^ (value >>> 16)) >>> 0; +} + +function percentile(sorted, fraction) { + return sorted[Math.min(sorted.length - 1, Math.ceil(sorted.length * fraction) - 1)]; +} + +function formatMs(value) { + return value.toFixed(3); +} + +function formatBytes(value) { + const sign = value < 0 ? "-" : ""; + return `${sign}${(Math.abs(value) / 1024 / 1024).toFixed(2)} MiB`; +} + +function measure(operation) { + assertWithinDeadline(); + const beforeHeap = process.memoryUsage().heapUsed; + const before = performance.now(); + const result = operation(); + const elapsedMs = performance.now() - before; + const heapDeltaBytes = process.memoryUsage().heapUsed - beforeHeap; + assertWithinDeadline(); + return { elapsedMs, heapDeltaBytes, result }; +} + +function benchmark(name, operation) { + const cold = measure(operation); + const warm = []; + for (let index = 0; index < LIMITS.warmSamples; index += 1) { + warm.push(measure(operation)); + } + const elapsed = warm.map((sample) => sample.elapsedMs).sort((a, b) => a - b); + const heaps = warm.map((sample) => sample.heapDeltaBytes); + const checksums = new Set([cold.result.checksum, ...warm.map((sample) => sample.result.checksum)]); + if (checksums.size !== 1) { + throw new Error(`${name} fixture produced a non-deterministic checksum`); + } + return { + name, + coldMs: cold.elapsedMs, + coldHeapBytes: cold.heapDeltaBytes, + medianMs: percentile(elapsed, 0.5), + p95Ms: percentile(elapsed, 0.95), + maxMs: elapsed.at(-1), + maxWarmHeapBytes: Math.max(...heaps), + checksum: cold.result.checksum, + counters: cold.result.counters, + }; +} + +function googleHistoryFixture() { + const accumulated = []; + let checksum = 0; + let finalTokenPresent = false; + + for (let page = 0; page < LIMITS.googlePages; page += 1) { + const encodedPage = JSON.stringify({ + rows: Array.from({ length: LIMITS.googleRowsPerPage }, (_, row) => ({ + t: page * LIMITS.googleRowsPerPage + row, + v: seededNumber(page * LIMITS.googleRowsPerPage + row, 17) % 10_000, + })), + next: page + 1 < LIMITS.googlePages ? `fixture-page-${page + 1}` : null, + }); + const decodedPage = JSON.parse(encodedPage); + accumulated.push(...decodedPage.rows); + finalTokenPresent = decodedPage.next !== null; + } + + for (const row of accumulated) { + checksum = (checksum + row.t * 17 + row.v) >>> 0; + } + return { + checksum, + counters: { + pages: LIMITS.googlePages, + rows: accumulated.length, + concurrency: 1, + finalTokenPresent, + }, + }; +} + +function reminderCohortFixture() { + let checksum = 0; + let dueCandidates = 0; + let modeledQueries = 1; + + for (let cleanup = 0; cleanup < LIMITS.reminderCleanupBacklog; cleanup += 1) { + checksum = (checksum + seededNumber(cleanup, 31)) >>> 0; + } + + for ( + let medication = 0; + medication < LIMITS.reminderMedications; + medication += 1 + ) { + modeledQueries += 2; + for (let slot = 0; slot < LIMITS.reminderSlotsPerMedication; slot += 1) { + const phase = seededNumber( + medication * LIMITS.reminderSlotsPerMedication + slot, + 43, + ); + if (phase % 5 === 0) { + dueCandidates += 1; + modeledQueries += 2; + } + checksum = (checksum + (phase & 0xffff)) >>> 0; + } + } + return { + checksum, + counters: { + medications: LIMITS.reminderMedications, + slots: LIMITS.reminderMedications * LIMITS.reminderSlotsPerMedication, + cleanupBacklog: LIMITS.reminderCleanupBacklog, + dueCandidates, + modeledQueries, + concurrency: 1, + }, + }; +} + +function healthScoreFixture() { + const denseRows = Array.from( + { length: LIMITS.healthDenseDays * LIMITS.healthSamplesPerDay }, + (_, index) => ({ + day: Math.floor(index / LIMITS.healthSamplesPerDay), + source: index % 3, + value: seededNumber(index, 59) % 1_000, + }), + ); + const sparseRows = Array.from( + { length: LIMITS.healthSparseDays * LIMITS.healthSparseSamplesPerDay }, + (_, index) => ({ + day: Math.floor(index / LIMITS.healthSparseSamplesPerDay), + domain: index % 8, + value: seededNumber(index, 71) % 1_000, + }), + ); + + const dailyCanonical = new Map(); + for (const row of denseRows) { + const prior = dailyCanonical.get(row.day); + if (!prior || row.source < prior.source) dailyCanonical.set(row.day, row); + } + const domainTotals = new Array(8).fill(0); + const domainCounts = new Array(8).fill(0); + for (const row of sparseRows) { + domainTotals[row.domain] += row.value; + domainCounts[row.domain] += 1; + } + let checksum = 0; + for (const row of dailyCanonical.values()) checksum = (checksum + row.value) >>> 0; + for (let domain = 0; domain < domainTotals.length; domain += 1) { + const normalized = Math.round(domainTotals[domain] / domainCounts[domain]); + checksum = (checksum * 31 + normalized) >>> 0; + } + return { + checksum, + counters: { + denseRows: denseRows.length, + sparseRows: sparseRows.length, + canonicalDays: dailyCanonical.size, + domains: domainTotals.length, + concurrency: 1, + parity: "stable-checksum", + }, + }; +} + +function commitSha() { + try { + return execFileSync("git", ["rev-parse", "--short", "HEAD"], { + encoding: "utf8", + stdio: ["ignore", "pipe", "ignore"], + }).trim(); + } catch { + return "unavailable"; + } +} + +function counterSummary(result) { + return Object.entries(result.counters) + .map(([key, value]) => `${key}=${value}`) + .join("; "); +} + +try { + const results = [ + benchmark("Google history pagination shape", googleHistoryFixture), + benchmark("Medication reminder cohort shape", reminderCohortFixture), + benchmark("Health Score read/canonicalization shape", healthScoreFixture), + ]; + const durationMs = performance.now() - startedAt; + const generatedAt = new Date().toISOString(); + const markdown = `# v1.34.1 Performance Baseline + +**Generated:** ${generatedAt} +**Commit:** \`${commitSha()}\` +**Exit status:** PASS +**Mode:** deterministic local fixture only + +## Safety and interpretation + +- No network, database, provider, production, or staging endpoint was contacted. +- Fixtures contain generated counters only. The report emits no tokens, identifiers, payloads, health values, hostnames, usernames, or working-directory paths. +- Concurrency is fixed at one, warm sample count is ${LIMITS.warmSamples}, and the whole run has a ${LIMITS.deadlineMs / 1000}-second deadline. +- Timing is a local code-shape baseline, not a production latency or capacity claim. Database, provider, network, framework, cache, and rendering costs remain unmeasured. +- The Health Score fixture exercises dense/sparse row construction, source canonicalization, and a stable composite proxy. It does not replace production algorithm parity or database-backed performance tests. + +## Environment + +| Attribute | Value | +| --- | --- | +| Node | ${process.version} | +| Platform | ${platform()} ${release()} | +| Architecture | ${arch()} | +| Logical CPUs | ${cpus().length} | +| Process | single local Node process | +| Total harness duration | ${formatMs(durationMs)} ms | + +## Fixture scale + +| Path shape | Fixed scale | +| --- | --- | +| Google history | ${LIMITS.googlePages} serial pages × ${LIMITS.googleRowsPerPage} generated rows; terminal page has no remaining token | +| Reminder cohort | ${LIMITS.reminderMedications} medications × ${LIMITS.reminderSlotsPerMedication} slots plus ${LIMITS.reminderCleanupBacklog} cleanup records | +| Health Score | ${LIMITS.healthDenseDays} dense days × ${LIMITS.healthSamplesPerDay} samples plus ${LIMITS.healthSparseDays} sparse days × ${LIMITS.healthSparseSamplesPerDay} samples | + +## Measurements + +| Local path shape | Cold | Warm median | Warm p95 | Warm max | Cold heap delta | Max warm heap delta | +| --- | ---: | ---: | ---: | ---: | ---: | ---: | +${results + .map( + (result) => + `| ${result.name} | ${formatMs(result.coldMs)} ms | ${formatMs(result.medianMs)} ms | ${formatMs(result.p95Ms)} ms | ${formatMs(result.maxMs)} ms | ${formatBytes(result.coldHeapBytes)} | ${formatBytes(result.maxWarmHeapBytes)} |`, + ) + .join("\n")} + +### Determinism and bounded counters + +${results + .map( + (result) => + `- **${result.name}:** checksum \`${result.checksum.toString(16).padStart(8, "0")}\`; ${counterSummary(result)}.`, + ) + .join("\n")} + +## Route/path interpretation + +| Representative path | What this fixture measures | What it does not measure | +| --- | --- | --- | +| Google full-sync pagination | Serial JSON page materialization and accumulation at the observed 786-page shape | Provider latency, DB writes, token refresh, rollups, or a safe universal page ceiling | +| Medication reminder worker | Serial cohort/slot decisions, cleanup scan, and modeled query amplification | Prisma latency, locks, dispatch latency, or the live cohort size | +| Dashboard / analytics Health Score | Dense/sparse row processing, canonical selection, and stable composite proxy | SQL plans, cache behavior, exact production score parity, or user-visible route latency | + +## Hypotheses and unmeasured risks + +- **Hypothesis:** Serial provider latency and write statements dominate the Google full-sync wall time; this local CPU result neither confirms nor refutes that hypothesis. +- **Hypothesis:** Reminder query/dispatch amplification, not local loop cost, determines whether a high-water pass approaches its 15-minute cadence. +- **Hypothesis:** Cold database row materialization and canonicalization dominate dense-user Health Score work; production impact remains unconfirmed. +- **Unmeasured:** network and database tails, cache hit/miss ratios, cross-process invalidation, framework rendering, device/browser performance, and production cohort distributions. +- **Do not infer:** a provider defect, a safe page cap, a production regression, or permission to optimize from this report alone. + +## Reproduction + +\`node scripts/v1341-performance-baseline.mjs --fixture --output .planning/phases/01-v1-34-1-dashboard-insights-records-admin-and-integration-reliability/01-PERFORMANCE-BASELINE.md\` +`; + + writeFileSync(outputPath, markdown, { encoding: "utf8", mode: 0o600 }); + console.log( + `v1341-performance-baseline: PASS (${results.length} fixtures, ${formatMs(durationMs)} ms)`, + ); +} catch (error) { + console.error( + `v1341-performance-baseline: FAIL (${error instanceof Error ? error.message : "unknown error"})`, + ); + process.exit(1); +}