rolldown-perf-kit 0.0.0-stage → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (43) hide show
  1. package/AGENTS.md +345 -0
  2. package/LICENSE +25 -0
  3. package/README.md +621 -2
  4. package/harness.mjs +4860 -0
  5. package/lib/build.mjs +57 -0
  6. package/lib/cdp.mjs +217 -0
  7. package/lib/chunk-discovery.mjs +226 -0
  8. package/lib/coverage.mjs +498 -0
  9. package/lib/field/analysis.mjs +225 -0
  10. package/lib/field/browser.mjs +232 -0
  11. package/lib/field/build-match.mjs +86 -0
  12. package/lib/field/capture.mjs +501 -0
  13. package/lib/field/config.mjs +84 -0
  14. package/lib/field/run.mjs +612 -0
  15. package/lib/gen-app.mjs +399 -0
  16. package/lib/graph-diff.mjs +136 -0
  17. package/lib/interrupt.mjs +25 -0
  18. package/lib/measure.mjs +540 -0
  19. package/lib/min-cut.mjs +218 -0
  20. package/lib/module-graph.mjs +318 -0
  21. package/lib/network-evidence.mjs +84 -0
  22. package/lib/node/launch.mjs +351 -0
  23. package/lib/node/measure.mjs +289 -0
  24. package/lib/paint-diagnostics.mjs +76 -0
  25. package/lib/parity/anchor.mjs +186 -0
  26. package/lib/parity/capture.mjs +527 -0
  27. package/lib/parity/compare.mjs +813 -0
  28. package/lib/parity/png.mjs +166 -0
  29. package/lib/parity/run.mjs +145 -0
  30. package/lib/profile.mjs +281 -0
  31. package/lib/replay/cert.mjs +45 -0
  32. package/lib/replay/model.mjs +656 -0
  33. package/lib/replay/run.mjs +1140 -0
  34. package/lib/replay/server.mjs +499 -0
  35. package/lib/replay/shaper.mjs +158 -0
  36. package/lib/rolldown-support.mjs +161 -0
  37. package/lib/serve.mjs +142 -0
  38. package/lib/worker/attrib.mjs +125 -0
  39. package/lib/worker/config.mjs +116 -0
  40. package/lib/worker/launch.mjs +337 -0
  41. package/lib/worker/measure.mjs +296 -0
  42. package/package.json +38 -4
  43. package/replay.mjs +79 -0
package/replay.mjs ADDED
@@ -0,0 +1,79 @@
1
+ #!/usr/bin/env node
2
+ // perf-kit-replay - record a deployed page once, replay it against local builds.
3
+ // Standalone: no harness target, no lab state. The archive folder is the whole
4
+ // interface between the agent that records and the agent that replays.
5
+
6
+ import { cmdInspect, cmdRecord, cmdReplay } from './lib/replay/run.mjs';
7
+
8
+ const HELP = `perf-kit-replay - field-like load numbers for builds that are not deployed
9
+
10
+ record load a deployed page in the user's logged-in Chrome and write an archive
11
+ inspect what an archive holds, whether it is complete, the next commands
12
+ replay serve an archive to headless Chrome with local builds in place of the deployed files
13
+
14
+ TWO AGENTS
15
+ recording agent (needs the user's Chrome with chrome://inspect/#remote-debugging on):
16
+ node replay.mjs record --url https://app.example.com/ [--cookie name=value]
17
+ [--block analytics.example.com] [--gate /api/items] [--ignore-lcp '#splash']
18
+ [--build <local copy of the served build>] --json
19
+ -> returns { archive, handoff, complete, gaps, next, ... }. complete:false -> record
20
+ again with a longer --settle. Hand over the "archive" path only.
21
+ replaying agent (no browser login needed):
22
+ node replay.mjs inspect --archive <dir> --json usable? complete? warnings? recorded when?
23
+ lateChunksBeforeLcp: late static chunks in the field runs
24
+ node replay.mjs replay --archive <dir> --dist recorded=<served build> --calibrate --json --exit-code
25
+ node replay.mjs replay --archive <dir> --dist base=<dir> --dist candidate=<dir> --json
26
+ The calibration verdict says what to do next:
27
+ pass an A/B on this archive is usable
28
+ record-again the archive misses responses most field runs got: record again
29
+ model-error the archive is complete; a new recording does not fix it: report the rows
30
+ Trust an A/B only after the calibration passes. HANDOFF.txt in the archive repeats this.
31
+
32
+ record
33
+ --url <page> --cookie name=value (repeat) --block <substring> (repeat) --gate <substring>
34
+ --ignore-lcp <selector> --redact <regex> (repeat) --variant <name> or: --config <field.json> [--variant <name>]
35
+ --build <dir> local copy of the build the site serves (calibration, HTML check)
36
+ --runs 6 --settle 3000 --pause 3000 --timeout 30000 --out <dir> --cdp-port <n> --cdp-url <ws>
37
+ Writes to $TMPDIR/perf-kit-replay/<site>-<variant> (owner-only; refuses a git work tree).
38
+ The archive holds REAL responses of the recording account: never copy it anywhere.
39
+
40
+ replay
41
+ --archive <dir> --dist [name=]<dir> (repeat for an A/B) --runs 6 --calibrate
42
+ --diagnose 1 [--cut gate|lcp|fcp] coverage + CPU profile run per dist
43
+ --document merged|local|recorded default merged: the dist's index.html + the tags only the deployed HTML has
44
+ --storage warm|empty warm: one unmeasured load in the same browser context first, so the build's
45
+ own storage (cached boot data) is there, as on a returning visit. Default warm
46
+ when the recorded page had localStorage, else empty
47
+ --bandwidth <Mbit/s> --rtt <ms> --static-ttfb <ms> --wire <kB> --ect slow-2g|2g|3g|4g|off model overrides
48
+ --out <dir> default <archive>/replay-report
49
+
50
+ common
51
+ --json print one JSON result object on stdout; the log goes to stderr
52
+ --exit-code replay --calibrate: exit 1 on model-error, 3 on record-again
53
+ exit codes 0 done, 1 model-error (--exit-code), 2 error, 3 record-again (--exit-code)`;
54
+
55
+ const [command, ...rest] = process.argv.slice(2);
56
+ const commands = { record: cmdRecord, inspect: cmdInspect, replay: cmdReplay };
57
+ if (!commands[command]) {
58
+ console.log(HELP);
59
+ process.exit(command && command !== 'help' ? 2 : 0);
60
+ }
61
+ const json = rest.includes('--json');
62
+ const exitOnFail = rest.includes('--exit-code');
63
+ const argv = rest.filter((a) => a !== '--json' && a !== '--exit-code');
64
+ const log = console.log;
65
+ if (json) console.log = (...args) => console.error(...args);
66
+ try {
67
+ const result = await commands[command](argv);
68
+ if (json) process.stdout.write(`${JSON.stringify(result)}\n`);
69
+ if (exitOnFail && result?.calibration) {
70
+ const codes = { pass: 0, 'model-error': 1, 'record-again': 3 };
71
+ process.exitCode = codes[result.calibration.verdict] ?? 1;
72
+ }
73
+ } catch (err) {
74
+ if (json) process.stdout.write(`${JSON.stringify({ error: err.message })}\n`);
75
+ console.error(`error: ${err.message}`);
76
+ process.exitCode = 2;
77
+ } finally {
78
+ console.log = log;
79
+ }