perf: add local render CPU benchmark - #3071
Conversation
…mark # Conflicts: # scripts/query-counts.queries.d1.json
|
Query-count snapshot changes17 routes changed, total Δ +67 queries. D1
Comparing snapshot files between base and head. Updated automatically on each push. |
@emdash-cms/admin
@emdash-cms/auth
@emdash-cms/auth-atproto
@emdash-cms/blocks
@emdash-cms/cloudflare
@emdash-cms/contentful-to-portable-text
emdash
create-emdash
@emdash-cms/gutenberg-to-portable-text
@emdash-cms/plugin-cli
@emdash-cms/plugin-types
@emdash-cms/registry-client
@emdash-cms/registry-lexicons
@emdash-cms/registry-moderation
@emdash-cms/registry-verification
@emdash-cms/sandbox-workerd
@emdash-cms/x402
@emdash-cms/plugin-ai-moderation
@emdash-cms/plugin-atproto
@emdash-cms/plugin-audit-log
@emdash-cms/plugin-color
@emdash-cms/plugin-embeds
@emdash-cms/plugin-field-kit
@emdash-cms/plugin-forms
@emdash-cms/plugin-webhook-notifier
commit: |
Scope checkThis PR changes 674 lines across 6 files. Large PRs are harder to review and more likely to be closed without review. If this scope is intentional, no action needed. A maintainer will review it. If not, please consider splitting this into smaller PRs. See CONTRIBUTING.md for contribution guidelines. |
Deploying with
|
| Status | Name | Latest Commit | Updated (UTC) |
|---|---|---|---|
| ✅ Deployment successful! View logs |
docs | 90a4ac0 | Sep 11 2026, 04:24 PM |
🚀 Deploying Preview to Cloudflare 🚀Preview URL: https://perf-render-cpu-benchmark.try.emdashcms.com, https://perf-render-cpu-benchmark-emdash-playground.emdash-cms.workers.dev (commit ae7adb0)This URL reflects your latest Preview deploymentPreview Deployments by commit
|
Overlapping PRsThis PR modifies files that are also changed by other open PRs: This may cause merge conflicts or duplicated work. A maintainer will coordinate. |
What does this PR do?
Adds a repeatable local CPU benchmark for server-rendered pages in the production-built Cloudflare performance fixture.
pnpm render-cpukeeps three distinct measurements instead of averaging them together: module evaluation fromwrangler check startup, repeated first requests in fresh workerd processes, and batches after route warm-up. It captures V8 CPU profiles through the inspector protocol, drains every streamed response, waits briefly for request-owned continuation work, and reports median active CPU, median absolute deviation, garbage collection, response wall time, and the corresponding cold/warm query count. Raw.cpuprofilefiles and a JSON summary are written outside the repository for flamegraph analysis.The query-count harness now sends browser-shaped
Acceptheaders. This exercises the HTML layout-prefetch path that real navigations use and updates the D1 query snapshots accordingly. It also keeps Astro's agent-detected dev server attached to the harness lifecycle and fails promptly if the seed server exits before becoming ready.The resulting D1 snapshot increase (
+67queries across cold and warm routes) is newly measured existing behavior, not runtime work introduced by this PR. The previous*/*requests skipped the HTML prefetch branch entirely; browser navigations already take it in production. Making that cost visible gives follow-up optimization work a truthful baseline.The fixture accepts an alternate Wrangler config path so the same build can be grounded against an isolated deployed Worker without committing account resource IDs.
Type of change
Checklist
pnpm typecheckpassespnpm lintpassespnpm testpasses (or targeted tests for my change)pnpm formathas been runmessages.pochanges except in translation PRs — a workflow extracts catalogs on merge tomain.The localization, changeset, Discussion, and screenshot items are not applicable: this changes repository-only performance tooling and a private fixture, with no published package or UI change.
AI-generated code disclosure
Screenshots / test output
Not applicable — no UI changes.
Validated on the merged current
origin/mainhead with:pnpm --config.verifyDepsBeforeRun=warn buildpnpm --config.verifyDepsBeforeRun=warn typecheckpnpm --config.verifyDepsBeforeRun=warn lintpnpm --config.verifyDepsBeforeRun=warn format:checkpnpm --config.verifyDepsBeforeRun=warn query-counts --target sqlitepnpm --config.verifyDepsBeforeRun=warn render-cpu -- --route home --startup-runs 1 --cold-runs 2 --requests 2 --batches 1 --warmups 1(includes D1 query snapshot verification)pnpm --config.verifyDepsBeforeRun=warn render-cpu -- --skip-prepare(full startup, first-request, and warm baseline across ten routes)The same fixture was deployed to an isolated benchmark Worker for grounding. Across ten page types, local and deployed median CPU had
r = 0.948correlation and0.75 msmean absolute error. Query count explained 82% of local CPU variance and 73% of deployed CPU variance.The cold-path split is material: on the merged head, Worker module evaluation was 23.5 ms median, first requests were 43–80 ms by route before adding startup, and warm renders were 4.2–12.1 ms. A warm-only profile therefore misses most of the CPU cost paid by a fresh isolate.