@bompus/house-rules 0.0.0-stage → 0.13.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.
- package/CODE_OF_CONDUCT.md +83 -0
- package/CONTRIBUTING.md +54 -0
- package/LICENSE +21 -0
- package/README.md +378 -2
- package/THIRD_PARTY_NOTICES.md +188 -0
- package/compose.mjs +125 -0
- package/composition.mjs +361 -0
- package/config-view.mjs +209 -0
- package/config.mjs +381 -0
- package/docs/assets/banner-dark.png +0 -0
- package/docs/assets/banner-light.png +0 -0
- package/docs/assets/overview.png +0 -0
- package/docs/configuration.md +269 -0
- package/docs/skill-names.md +50 -0
- package/examples/person/house-rules.json +15 -0
- package/examples/person/rules/10-tooling.md +8 -0
- package/examples/person/rules/20-reporting.md +9 -0
- package/examples/project/AGENTS.md +18 -0
- package/package.json +42 -4
- package/rule-references.mjs +91 -0
- package/rules/core.md +340 -0
- package/rules/modifiers/backlog-outline.md +25 -0
- package/rules/modifiers/backlog-visual.md +16 -0
- package/rules/modifiers/coded-offers.md +70 -0
- package/rules/modifiers/cross-session-relay.md +23 -0
- package/rules/modifiers/effort-estimates.md +41 -0
- package/rules/modifiers/land-when-done.md +12 -0
- package/rules/modifiers/low-quota-handoff.md +20 -0
- package/rules/modifiers/model-default-questions.md +33 -0
- package/rules/modifiers/multi-agent.md +38 -0
- package/rules/modifiers/no-attribution.md +16 -0
- package/rules/modifiers/periodic-updates.md +25 -0
- package/rules/modifiers/plan-files.md +82 -0
- package/rules/modifiers/question-cards.md +48 -0
- package/rules/modifiers/release-batching.md +15 -0
- package/rules/modifiers/scratch-on-disk.md +15 -0
- package/rules/modifiers/shared-host-load.md +19 -0
- package/rules/modifiers/solo-operator.md +13 -0
- package/rules/modifiers/squash-landing.md +22 -0
- package/rules/modifiers/upstream-contributions.md +45 -0
- package/rules/modifiers/web-image-formats.md +35 -0
- package/rules/references/backlog-view.md +154 -0
- package/rules/references/github-actions.md +45 -0
- package/rules/references/landing.md +39 -0
- package/rules/references/multi-agent.md +51 -0
- package/rules/references/release-batching.md +66 -0
- package/rules/references/squash-landing.md +50 -0
- package/rules/references/thread-visuals.md +45 -0
- package/setup.mjs +445 -0
- package/skills/hr-agent-guidance-audit/LICENSE +21 -0
- package/skills/hr-agent-guidance-audit/SKILL.md +91 -0
- package/skills/hr-agent-guidance-audit/agents/openai.yaml +2 -0
- package/skills/hr-agent-guidance-audit/references/prune-workflow.md +72 -0
- package/skills/hr-agent-guidance-audit/references/records-and-lessons.md +60 -0
- package/skills/hr-agent-guidance-audit/references/retirement-verdicts.md +49 -0
- package/skills/hr-agent-guidance-refresh/LICENSE +21 -0
- package/skills/hr-agent-guidance-refresh/SKILL.md +36 -0
- package/skills/hr-agent-guidance-refresh/agents/openai.yaml +2 -0
- package/skills/hr-agent-guidance-refresh/references/verification.md +47 -0
- package/skills/hr-api-exposure-check/SKILL.md +159 -0
- package/skills/hr-api-exposure-check/agents/openai.yaml +3 -0
- package/skills/hr-audit-choices/SKILL.md +67 -0
- package/skills/hr-audit-choices/agents/openai.yaml +2 -0
- package/skills/hr-benchmarking/NOTICE.md +36 -0
- package/skills/hr-benchmarking/SKILL.md +279 -0
- package/skills/hr-benchmarking/agents/openai.yaml +2 -0
- package/skills/hr-benchmarking/references/javascript.md +130 -0
- package/skills/hr-benchmarking/references/tools.md +165 -0
- package/skills/hr-benchmarking/scripts/process-attribution.ps1 +20 -0
- package/skills/hr-benchmarking/scripts/process-attribution.py +107 -0
- package/skills/hr-better-accessibility/LICENSE +22 -0
- package/skills/hr-better-accessibility/NOTICE.md +46 -0
- package/skills/hr-better-accessibility/SKILL.md +119 -0
- package/skills/hr-better-accessibility/agents/openai.yaml +3 -0
- package/skills/hr-better-accessibility/focus-and-keyboard.md +130 -0
- package/skills/hr-better-accessibility/forms.md +82 -0
- package/skills/hr-better-accessibility/hit-areas.md +98 -0
- package/skills/hr-better-accessibility/motion-and-zoom.md +81 -0
- package/skills/hr-better-accessibility/screen-readers.md +102 -0
- package/skills/hr-better-accessibility/semantics-and-aria.md +84 -0
- package/skills/hr-better-colors/LICENSE +21 -0
- package/skills/hr-better-colors/NOTICE.md +37 -0
- package/skills/hr-better-colors/SKILL.md +114 -0
- package/skills/hr-better-colors/agents/openai.yaml +3 -0
- package/skills/hr-better-colors/color-formats.md +90 -0
- package/skills/hr-better-colors/color-usage.md +140 -0
- package/skills/hr-better-colors/contrast.md +80 -0
- package/skills/hr-better-colors/palette-generation.md +104 -0
- package/skills/hr-better-colors/palette-structure.md +76 -0
- package/skills/hr-better-colors/token-naming.md +97 -0
- package/skills/hr-better-layout/LICENSE +22 -0
- package/skills/hr-better-layout/NOTICE.md +48 -0
- package/skills/hr-better-layout/SKILL.md +92 -0
- package/skills/hr-better-layout/agents/openai.yaml +3 -0
- package/skills/hr-better-layout/grouping-and-alignment.md +144 -0
- package/skills/hr-better-layout/spacing-and-adaptivity.md +215 -0
- package/skills/hr-better-typography/LICENSE +22 -0
- package/skills/hr-better-typography/NOTICE.md +46 -0
- package/skills/hr-better-typography/SKILL.md +172 -0
- package/skills/hr-better-typography/agents/openai.yaml +3 -0
- package/skills/hr-better-typography/choosing-fonts.md +69 -0
- package/skills/hr-better-typography/css-cheat-sheet.md +65 -0
- package/skills/hr-better-typography/details-and-accessibility.md +119 -0
- package/skills/hr-better-typography/spacing-and-sizing.md +131 -0
- package/skills/hr-better-typography/variable-fonts-and-opentype.md +105 -0
- package/skills/hr-better-typography/wrapping-and-punctuation.md +57 -0
- package/skills/hr-better-writing/LICENSE +22 -0
- package/skills/hr-better-writing/NOTICE.md +46 -0
- package/skills/hr-better-writing/SKILL.md +122 -0
- package/skills/hr-better-writing/agents/openai.yaml +3 -0
- package/skills/hr-code-review/LICENSE +21 -0
- package/skills/hr-code-review/NOTICE.md +26 -0
- package/skills/hr-code-review/SKILL.md +163 -0
- package/skills/hr-code-review/agents/openai.yaml +3 -0
- package/skills/hr-code-review/references/acp-client.md +43 -0
- package/skills/hr-code-review/references/evidence.md +57 -0
- package/skills/hr-code-review/references/impact.md +103 -0
- package/skills/hr-code-review/references/panel-adjudication.md +58 -0
- package/skills/hr-code-review/references/panel-plan.md +61 -0
- package/skills/hr-code-review/references/panel-recommendations.json +105 -0
- package/skills/hr-code-review/references/panel-recommendations.md +46 -0
- package/skills/hr-code-review/references/panel-setup.md +54 -0
- package/skills/hr-code-review/references/reviewer-role.md +31 -0
- package/skills/hr-code-review/scripts/acp-panel-client.mjs +299 -0
- package/skills/hr-code-review/scripts/check-receipts.mjs +263 -0
- package/skills/hr-code-review/scripts/panel-plan.mjs +69 -0
- package/skills/hr-code-review/scripts/panel-preferences.mjs +220 -0
- package/skills/hr-design-exploration/SKILL.md +105 -0
- package/skills/hr-design-exploration/agents/openai.yaml +4 -0
- package/skills/hr-diagnosing-bugs/NOTICE.md +45 -0
- package/skills/hr-diagnosing-bugs/SKILL.md +108 -0
- package/skills/hr-diagnosing-bugs/agents/openai.yaml +3 -0
- package/skills/hr-diagnosing-bugs/references/reporting.md +97 -0
- package/skills/hr-diagnosing-bugs/scripts/check-pr-offer.mjs +47 -0
- package/skills/hr-explain-code/NOTICE.md +37 -0
- package/skills/hr-explain-code/SKILL.md +110 -0
- package/skills/hr-explain-code/agents/openai.yaml +5 -0
- package/skills/hr-explain-code/references/helper-brief.md +39 -0
- package/skills/hr-extract-shared-steps/SKILL.md +134 -0
- package/skills/hr-extract-shared-steps/agents/openai.yaml +3 -0
- package/skills/hr-forgotten-work-audit/SKILL.md +130 -0
- package/skills/hr-forgotten-work-audit/references/brief-template.md +56 -0
- package/skills/hr-forgotten-work-audit/references/result-format.md +46 -0
- package/skills/hr-handoff/LICENSE +21 -0
- package/skills/hr-handoff/NOTICE.md +29 -0
- package/skills/hr-handoff/SKILL.md +114 -0
- package/skills/hr-handoff/agents/openai.yaml +5 -0
- package/skills/hr-handoff/assets/ledger.example.json +10 -0
- package/skills/hr-handoff/assets/receipt.example.json +76 -0
- package/skills/hr-handoff/assets/source.example.json +20 -0
- package/skills/hr-handoff/references/reconciliation.md +124 -0
- package/skills/hr-handoff/references/successor-thread.md +76 -0
- package/skills/hr-handoff/scripts/check-reconciliation.mjs +324 -0
- package/skills/hr-house-rules-setup/SKILL.md +114 -0
- package/skills/hr-house-rules-setup/agents/openai.yaml +5 -0
- package/skills/hr-issue-tracker-setup/SKILL.md +49 -0
- package/skills/hr-issue-tracker-setup/agents/openai.yaml +5 -0
- package/skills/hr-lean-plan/SKILL.md +146 -0
- package/skills/hr-lean-plan/agents/openai.yaml +5 -0
- package/skills/hr-maintainability-review/SKILL.md +186 -0
- package/skills/hr-maintainability-review/agents/openai.yaml +5 -0
- package/skills/hr-manual-qa/NOTICE.md +36 -0
- package/skills/hr-manual-qa/SKILL.md +37 -0
- package/skills/hr-manual-qa/agents/openai.yaml +3 -0
- package/skills/hr-navigation-retro/LICENSE +21 -0
- package/skills/hr-navigation-retro/NOTICE.md +5 -0
- package/skills/hr-navigation-retro/SKILL.md +86 -0
- package/skills/hr-navigation-retro/agents/openai.yaml +4 -0
- package/skills/hr-navigation-retro/references/inputs.md +67 -0
- package/skills/hr-navigation-retro/scripts/retro.py +552 -0
- package/skills/hr-navigation-retro/scripts/transcripts.py +205 -0
- package/skills/hr-ordering-tests/SKILL.md +51 -0
- package/skills/hr-ordering-tests/agents/openai.yaml +2 -0
- package/skills/hr-plain-prose/SKILL.md +264 -0
- package/skills/hr-plain-prose/agents/openai.yaml +3 -0
- package/skills/hr-plain-prose/scripts/check.mjs +331 -0
- package/skills/hr-pr-followup/LICENSE +21 -0
- package/skills/hr-pr-followup/NOTICE.md +9 -0
- package/skills/hr-pr-followup/SKILL.md +74 -0
- package/skills/hr-pr-followup/agents/openai.yaml +2 -0
- package/skills/hr-pr-followup/references/review-helpers.md +111 -0
- package/skills/hr-pr-followup/scripts/check-landing.py +204 -0
- package/skills/hr-pr-followup/scripts/check-pr-review.ts +510 -0
- package/skills/hr-pr-followup/scripts/merge-pr.sh +100 -0
- package/skills/hr-pr-followup/scripts/resolve-pr-thread.ts +219 -0
- package/skills/hr-pr-followup/scripts/verify-landed.sh +184 -0
- package/skills/hr-progress-report/SKILL.md +49 -0
- package/skills/hr-progress-report/agents/openai.yaml +5 -0
- package/skills/hr-read-reddit/SKILL.md +44 -0
- package/skills/hr-read-reddit/agents/openai.yaml +2 -0
- package/skills/hr-read-reddit/scripts/reddit.ts +252 -0
- package/skills/hr-read-x-links/SKILL.md +42 -0
- package/skills/hr-read-x-links/agents/openai.yaml +2 -0
- package/skills/hr-read-x-links/scripts/x-post.ts +264 -0
- package/skills/hr-research-shared-links/SKILL.md +103 -0
- package/skills/hr-split-to-prs/LICENSE +21 -0
- package/skills/hr-split-to-prs/NOTICE.md +9 -0
- package/skills/hr-split-to-prs/SKILL.md +61 -0
- package/skills/hr-split-to-prs/agents/openai.yaml +2 -0
- package/skills/hr-sqlite/SKILL.md +174 -0
- package/skills/hr-sqlite/agents/openai.yaml +2 -0
- package/skills/hr-sqlite/references/evidence.md +94 -0
- package/skills/hr-sqlite/references/tool-decisions.md +39 -0
- package/skills/hr-sqlite/scripts/inspect-sqlite.py +245 -0
- package/skills/hr-stock-ui-audit/SKILL.md +132 -0
- package/skills/hr-stock-ui-audit/agents/openai.yaml +3 -0
- package/skills/hr-stock-ui-audit/scripts/scan.mjs +619 -0
- package/skills/hr-tdd/LICENSE +21 -0
- package/skills/hr-tdd/NOTICE.md +10 -0
- package/skills/hr-tdd/SKILL.md +40 -0
- package/skills/hr-tdd/agents/openai.yaml +3 -0
- package/skills/hr-tdd/mocking.md +39 -0
- package/skills/hr-tdd/tests.md +77 -0
- package/skills/hr-test-audit/LICENSE +21 -0
- package/skills/hr-test-audit/NOTICE.md +67 -0
- package/skills/hr-test-audit/SKILL.md +146 -0
- package/skills/hr-test-audit/agents/openai.yaml +3 -0
- package/skills/hr-test-audit/scripts/floor-guard.ts +137 -0
- package/skills/hr-usage-report/SKILL.md +90 -0
- package/skills/hr-usage-report/agents/openai.yaml +2 -0
- package/skills/hr-usage-report/assets/example-report.json +125 -0
- package/skills/hr-usage-report/assets/report-template.html +377 -0
- package/skills/hr-usage-report/scripts/render-report.ts +86 -0
- package/skills/hr-usage-report/scripts/usage-by-model.ts +499 -0
- package/skills/hr-what-next/SKILL.md +151 -0
- package/skills/hr-what-next/agents/openai.yaml +4 -0
- package/skills/hr-what-next/references/reporting.md +59 -0
- package/skills/hr-what-next/scripts/check-open-work.mjs +711 -0
- package/skills/hr-writing-for-agents/NOTICE.md +46 -0
- package/skills/hr-writing-for-agents/SKILL-MECHANICS.md +83 -0
- package/skills/hr-writing-for-agents/SKILL.md +108 -0
- package/skills/hr-writing-for-agents/agents/openai.yaml +3 -0
- package/skills/hr-writing-pr/NOTICE.md +48 -0
- package/skills/hr-writing-pr/SKILL.md +119 -0
- package/skills/hr-writing-pr/agents/openai.yaml +2 -0
- package/skills/hr-writing-pr/scripts/benefit-chart.py +200 -0
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# Source notices
|
|
2
|
+
|
|
3
|
+
This notice accompanies the hr-benchmarking bundle when copied on its own.
|
|
4
|
+
|
|
5
|
+
## cursor/plugins (pstack)
|
|
6
|
+
|
|
7
|
+
Source: https://github.com/cursor/plugins (compared at revision `e43c7ee`)
|
|
8
|
+
|
|
9
|
+
- `skills/hr-benchmarking/SKILL.md`: the validity checks are adapted from
|
|
10
|
+
`pstack/skills/benchmark-checklist/`.
|
|
11
|
+
|
|
12
|
+
Copyright (c) 2026 Lauren Tan
|
|
13
|
+
|
|
14
|
+
## house-rules and MIT permission notice
|
|
15
|
+
|
|
16
|
+
MIT License
|
|
17
|
+
|
|
18
|
+
Copyright (c) 2026 Aaron Queen
|
|
19
|
+
|
|
20
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
21
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
22
|
+
in the Software without restriction, including without limitation the rights
|
|
23
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
24
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
25
|
+
furnished to do so, subject to the following conditions:
|
|
26
|
+
|
|
27
|
+
The above copyright notice and this permission notice shall be included in all
|
|
28
|
+
copies or substantial portions of the Software.
|
|
29
|
+
|
|
30
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
31
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
32
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
33
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
34
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
35
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
36
|
+
SOFTWARE.
|
|
@@ -0,0 +1,279 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: hr-benchmarking
|
|
3
|
+
description: Benchmark equivalent work with repeated timing, CPU and memory measurements under stated inputs and controls, and check whether saved results support a performance claim. Use when asked to benchmark, to measure which option is faster or uses less memory, or to time agent or model runs. Not for public model leaderboard research.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Benchmarking
|
|
7
|
+
|
|
8
|
+
Follow the repository and host's commands, resource limits, authorization and
|
|
9
|
+
landing rules. Reuse an existing workload and runner before building a harness.
|
|
10
|
+
Read [the tool reference](references/tools.md) when selecting a benchmark,
|
|
11
|
+
profiler or correctness check, or interpreting its measurements.
|
|
12
|
+
|
|
13
|
+
## Define the comparison
|
|
14
|
+
|
|
15
|
+
State the question, baseline, candidate, representative input and timed region.
|
|
16
|
+
Exercise ordinary supported inputs and cases that disable an optimization.
|
|
17
|
+
State any restrictions behind a performance claim.
|
|
18
|
+
|
|
19
|
+
For a requested candidate set, record its inventory and distinguish
|
|
20
|
+
configurations or capacity modes. Keep untested, invalid and unsupported
|
|
21
|
+
candidates visible with reasons. A subset comparison establishes results only
|
|
22
|
+
for its tested scope, not a winner across the full inventory.
|
|
23
|
+
|
|
24
|
+
Test the newest stable release of each candidate. When the version installed
|
|
25
|
+
or deployed differs, say so in the results, and ask which to test if the
|
|
26
|
+
request does not settle it. When told to use an older version, use it and
|
|
27
|
+
offer the newest as an alternative.
|
|
28
|
+
|
|
29
|
+
Before running, list the selected engines, workloads, metrics, controls and
|
|
30
|
+
repetitions. Count the planned runs explicitly, including controls and stages;
|
|
31
|
+
state which decision each retained dimension helps make. Choose combinations
|
|
32
|
+
for that decision rather than automatically running every combination. Use a
|
|
33
|
+
broader matrix when its required coverage is stated. State the benchmark's
|
|
34
|
+
expected wall-clock time, waits included, before the first run.
|
|
35
|
+
Name the measurement unit: request, operation, batch or whole command. State
|
|
36
|
+
whether setup, startup, compilation, input loading, retries and cleanup count.
|
|
37
|
+
|
|
38
|
+
Record exact runtime, compiler, dependency and runner versions, build flags,
|
|
39
|
+
input identity and source revisions. Freeze copied quality and control artifacts;
|
|
40
|
+
record their hashes and the executed artifact's identity. Agreement across
|
|
41
|
+
runtimes alone does not verify the intended artifact. Keep these fixed across
|
|
42
|
+
repeated arms; reject mixed versions when resuming a checkpoint.
|
|
43
|
+
|
|
44
|
+
Compare runtime knobs within the same build. Use equivalent outputs, release
|
|
45
|
+
settings and comparable tuning. An untuned arm compares configurations rather
|
|
46
|
+
than implementations.
|
|
47
|
+
|
|
48
|
+
Keep warm and cold conditions explicit. Reset state or use fresh processes
|
|
49
|
+
where the question requires independence. Record warmup and cache conditions.
|
|
50
|
+
A reused service needs equivalent state across arms, not an arbitrary restart.
|
|
51
|
+
|
|
52
|
+
## Confirm the work
|
|
53
|
+
|
|
54
|
+
Validate outputs, consumed results and error counts outside the timed region
|
|
55
|
+
where practical. Confirm requests arrived and asynchronous work was awaited.
|
|
56
|
+
Include failures, timeouts and unresolved attempts in both arms' denominators.
|
|
57
|
+
A faster wrong result or skipped operation is not a performance improvement.
|
|
58
|
+
|
|
59
|
+
Identify the limiting resource from CPU versus wall time, resource counters or
|
|
60
|
+
a separate profile. Check that throughput is possible given the machine and
|
|
61
|
+
input. When the generator limits the result, report that limit.
|
|
62
|
+
|
|
63
|
+
Before changing a component to remove a suspected cost, attribute time to that
|
|
64
|
+
component in the real workload with a profile or a counter. For fast feedback,
|
|
65
|
+
benchmark each changed piece through its actual production entry point with
|
|
66
|
+
representative fixed inputs and equivalent consumed outputs. Do not benchmark a
|
|
67
|
+
copied implementation or stub out work material to the comparison.
|
|
68
|
+
|
|
69
|
+
Compare each piece before and after against its immediate predecessor. Before
|
|
70
|
+
running, declare integration milestones when changed pieces enter the consuming
|
|
71
|
+
workload. Keep that workload before any piece changes as the original baseline.
|
|
72
|
+
At those milestones, compare the integrated workload with both its immediate
|
|
73
|
+
predecessor and the original baseline to track cumulative effects. Plan applicable
|
|
74
|
+
caller and integration checks for copying, serialization, startup and orchestration
|
|
75
|
+
costs that isolation excludes. Run those checks at the milestones and report
|
|
76
|
+
results or specific coverage limits. Re-time the change in the workload that uses
|
|
77
|
+
it at those milestones; a full-application run is not required after every piece.
|
|
78
|
+
An isolated gain does not establish an end-to-end gain. A setting that ran 7.6
|
|
79
|
+
times faster in isolation changed a 33 s indexing run by 0.1 s.
|
|
80
|
+
|
|
81
|
+
Select metrics for the question and limiting resource: wall time or latency,
|
|
82
|
+
memory, disk I/O, CPU, throughput, errors and output size as relevant. State each
|
|
83
|
+
metric's unit, process scope and interval; distinguish peak process memory from
|
|
84
|
+
retained memory, logical bytes from physical storage I/O, and warm from cold cache
|
|
85
|
+
state. Cache hits and delayed writeback can hide storage costs; record unavailable
|
|
86
|
+
counters and attribution limits rather than inferring physical I/O from logical
|
|
87
|
+
bytes. Do not require irrelevant additional counters; retain the CPU and memory
|
|
88
|
+
observations required below.
|
|
89
|
+
|
|
90
|
+
## Measure without changing the experiment
|
|
91
|
+
|
|
92
|
+
Keep measured files, toolchains and services unchanged, and keep other work on
|
|
93
|
+
the machine from competing with the run.
|
|
94
|
+
|
|
95
|
+
Prefer removing competing work to raising priority. Record effective CPU and
|
|
96
|
+
I/O scheduling policies and memory protections; keep them equal across arms.
|
|
97
|
+
Use normal scheduling and all available CPUs for ordinary measurements. Omit
|
|
98
|
+
automatic `nice` and `taskset` wrappers; verify inherited priority and affinity
|
|
99
|
+
rather than assuming their omission resets either. Use restricted affinity or
|
|
100
|
+
changed priority only for representative deployment settings, an explicit resource
|
|
101
|
+
agreement or a stated sensitivity question. Record the reason and effective values.
|
|
102
|
+
Preserve frozen protocols and report constrained results within their tested scope.
|
|
103
|
+
Read [scheduling controls](references/tools.md#scheduling-controls) before
|
|
104
|
+
choosing them.
|
|
105
|
+
|
|
106
|
+
Apply worker limits to requested processing concurrency. Report sampled OS-thread
|
|
107
|
+
counts separately; runtime background threads are not processing workers. A
|
|
108
|
+
thread count alone does not establish CPU contention; keep it diagnostic unless
|
|
109
|
+
the experiment separately justifies using it to reject a run.
|
|
110
|
+
|
|
111
|
+
Before collecting results, set the criteria for rejecting a run: competing
|
|
112
|
+
load, swapping and memory-limit or OOM events, each with its metric and
|
|
113
|
+
threshold. Check the machine against them before each arm and watch them
|
|
114
|
+
throughout the measured interval. A run that fails them, or whose inputs change, is rejected even when the benchmark caused the
|
|
115
|
+
failure. A rejection invalidates that measurement; it does not by itself show
|
|
116
|
+
an implementation defect. Keep rejected runs outside the accepted sample and
|
|
117
|
+
report them; a later passing run neither erases a rejection nor loosens the
|
|
118
|
+
criteria.
|
|
119
|
+
|
|
120
|
+
Attribute CPU, load and resident memory to the recorded benchmark process tree
|
|
121
|
+
or resource scope before calling them competing work. Expected benchmark
|
|
122
|
+
utilization is not contention, and total host CPU and load average include it.
|
|
123
|
+
Keep an activity counter diagnostic until separate evidence shows its cutoff
|
|
124
|
+
matters. Collect boundary counters adjacent to the measured work, with
|
|
125
|
+
unrelated probes outside that interval, and record sample times. A counter
|
|
126
|
+
interval extending past completion cannot by itself establish overlap; keep
|
|
127
|
+
post-run observations diagnostic and let the machine settle before the next arm.
|
|
128
|
+
|
|
129
|
+
Before claiming negligible observer impact or a small decisive gain, test
|
|
130
|
+
sensitivity to observation separately with balanced controls and a preset
|
|
131
|
+
precision criterion. Retain inconclusive controls; do not subtract observer CPU
|
|
132
|
+
from workload wall time. For remote agent or model evaluations, record the
|
|
133
|
+
timing regime and concurrent local work.
|
|
134
|
+
|
|
135
|
+
Screen correctness and quality first, then use one run per selected arm to
|
|
136
|
+
explore timing and resource behavior. Preserve screened-out results and their
|
|
137
|
+
reasons. Label screening exploratory; one run does not support a performance
|
|
138
|
+
claim. A correctness-only check can use one candidate run; report its coverage.
|
|
139
|
+
|
|
140
|
+
Before exploratory runs, define the decision-relevant signal for selecting
|
|
141
|
+
comparisons for confirmation. Choose comparisons that meet that signal, plus
|
|
142
|
+
decision-critical comparisons, for repeated confirmation; keep necessary controls.
|
|
143
|
+
Set the confirmation plan before its runs and update the explicit run count
|
|
144
|
+
when the scope changes.
|
|
145
|
+
|
|
146
|
+
The default stopping rule for a performance claim is 3 runs per arm. Add 2 more
|
|
147
|
+
per arm only when the arms' ranges overlap or the effect is near the noise,
|
|
148
|
+
meaning the gap is within the variation criterion set below. 5 per arm is the
|
|
149
|
+
cap. If 5 runs per arm leave the comparison unresolved, report it as
|
|
150
|
+
inconclusive rather than adding runs. Use another count only when the user asks
|
|
151
|
+
for it or a run is too long to repeat 3 times, and declare it before the first
|
|
152
|
+
run, with the reason. Alternate the arms in every run so drift reaches each arm.
|
|
153
|
+
|
|
154
|
+
For a performance claim, assess run-to-run variation from those alternating runs.
|
|
155
|
+
Treat variation as already known only when earlier repeated runs of the
|
|
156
|
+
same variant, build and input used the same workload, host, run conditions and
|
|
157
|
+
variation statistic, and met the repetition count or stopping rule declared for
|
|
158
|
+
this claim. Otherwise include an A/A arm,
|
|
159
|
+
which runs the same variant twice in the same alternation. Its spread is that
|
|
160
|
+
comparison's own noise floor, and it can supply the preset variation statistic.
|
|
161
|
+
Before the first run used in that claim, set a reproducible variation criterion
|
|
162
|
+
(statistic and threshold), and the stopping rule if it differs from the default.
|
|
163
|
+
|
|
164
|
+
For short or tail metrics, such as the longest stall in a run, give the
|
|
165
|
+
threshold an absolute floor or use a percentile or count metric; a percentage
|
|
166
|
+
of a single small maximum can fail on the workload's own variation.
|
|
167
|
+
Retain every result. Keep pilots that informed the plan separate from the
|
|
168
|
+
claim's sample. Capture raw results, exit status, elapsed time, CPU and memory
|
|
169
|
+
observations. Report monitoring overhead separately from the
|
|
170
|
+
measured workload; batch compatible probes when they dominate elapsed time.
|
|
171
|
+
Report the selected repetition count or stopping rule, variation statistic and
|
|
172
|
+
threshold, sample count, median and range. Always give the run count and the
|
|
173
|
+
range with any central value, never a bare average. Apply the preset
|
|
174
|
+
criterion and report a gap within run-to-run variation as no clear change. Profile
|
|
175
|
+
separately from the runs used to claim a speed difference.
|
|
176
|
+
|
|
177
|
+
When using saved evidence for a performance claim, bind archived inputs, source,
|
|
178
|
+
cohort and results to their recorded identities and artifact hashes. Validate
|
|
179
|
+
historical reports against that frozen archive; later changes in the live
|
|
180
|
+
checkout alone do not invalidate historical evidence. Verify run identities and
|
|
181
|
+
stages against the declared plan.
|
|
182
|
+
|
|
183
|
+
Recompute qualification from recorded raw counters and preset limits; an accepted
|
|
184
|
+
summary or changed label is insufficient. Reject missing, duplicate or
|
|
185
|
+
misclassified required observations. When an evidence reader exists, put these
|
|
186
|
+
checks and focused corruption regressions there. After a rebase or merge
|
|
187
|
+
touches the reader or a check it imports, run the integrated reader over the
|
|
188
|
+
saved archive before landing, and compare its accepted and excluded records
|
|
189
|
+
with the frozen reader's. A shared check changed on the base branch can reject
|
|
190
|
+
records that the frozen reader accepted.
|
|
191
|
+
|
|
192
|
+
Record memory by what it measures. Whole-process peak RSS includes startup,
|
|
193
|
+
inputs and dependencies. Heap snapshots describe retained objects; allocation
|
|
194
|
+
profiles describe allocation activity. Forced-GC probes are separate from
|
|
195
|
+
ordinary latency measurements. Match retention semantics and payloads when
|
|
196
|
+
comparing caches; equal requested capacities need not mean equal memory use.
|
|
197
|
+
For cache-retention probes, keep the cache owner reachable through the final
|
|
198
|
+
observation; otherwise collection of the owner can be mistaken for release by
|
|
199
|
+
the cache operation.
|
|
200
|
+
|
|
201
|
+
For WeakRef-based retention probes, use bounded allocation batches and calibrated
|
|
202
|
+
collection boundaries after creating or dereferencing targets. Avoid observer
|
|
203
|
+
arrays or locals that keep measured values strongly reachable; preserve the
|
|
204
|
+
intended owner lifetime. Report live payload, cache occupancy and process RSS
|
|
205
|
+
separately. Keep this collection protocol outside ordinary latency runs; yielding
|
|
206
|
+
or forced collection alone does not guarantee that a target is reclaimed.
|
|
207
|
+
|
|
208
|
+
Batch latency percentiles describe batches, not individual requests.
|
|
209
|
+
|
|
210
|
+
## Report and decide
|
|
211
|
+
|
|
212
|
+
Keep the full workload, versions, conditions, repetitions, output identity,
|
|
213
|
+
errors and measurement units in the measurement record. Include excluded costs,
|
|
214
|
+
coverage limits, collector overhead, scheduling, resource caps, pre-run
|
|
215
|
+
machine checks and rejected attempts there.
|
|
216
|
+
|
|
217
|
+
Pull requests and other change summaries show the workload, baseline and
|
|
218
|
+
candidate, measured results, relevant checks and limits that affect the claim.
|
|
219
|
+
Omit operational measurement details unless the reader needs them to interpret
|
|
220
|
+
the result or asks for them. A claimed difference with unknown limits, unequal
|
|
221
|
+
work or missing repetitions is unverified or inconclusive.
|
|
222
|
+
|
|
223
|
+
Show numeric before/after results in a table with a benefit column containing
|
|
224
|
+
percent change or a times improvement. Use the metric's direction and label
|
|
225
|
+
worsening, unchanged or inconclusive results. With a zero or missing baseline,
|
|
226
|
+
show an absolute change or state that the benefit cannot be calculated.
|
|
227
|
+
|
|
228
|
+
There is no minimum gain size. A favorable difference counts as a gain when it
|
|
229
|
+
lies outside the variation criterion declared before the first run (the comparison's
|
|
230
|
+
own run-to-run spread, from its A/A arm or already-known variation, as a
|
|
231
|
+
percentage of the baseline) and the outputs are identical. Report a gap inside
|
|
232
|
+
that criterion as no clear change, and name the statistic and threshold beside
|
|
233
|
+
it. An unfavorable difference outside it is a regression; label it worsening.
|
|
234
|
+
Report memory and CPU costs beside the gain. If the variation criterion cannot support a percentage, keep its result
|
|
235
|
+
separate and label unsupported differences inconclusive. Changing presentation
|
|
236
|
+
does not change frozen acceptance or rejection gates.
|
|
237
|
+
|
|
238
|
+
Show a comparison of three or more variants or conditions as a chart beside the
|
|
239
|
+
before/after table, unless every row is no clear change. Choose the chart for the
|
|
240
|
+
question:
|
|
241
|
+
|
|
242
|
+
| Question | Chart |
|
|
243
|
+
| -------------------------------- | ------------------------------------------ |
|
|
244
|
+
| Repeated runs of each variant | Dot plot of every run, mean marked |
|
|
245
|
+
| Conditions crossed with variants | Grouped bars, baseline as a reference line |
|
|
246
|
+
| Ranking of options | Sorted horizontal bars |
|
|
247
|
+
| Resource cost (CPU, memory) | Bars per variant, one panel per resource |
|
|
248
|
+
| Change with load or time | Line chart |
|
|
249
|
+
|
|
250
|
+
Put units and run counts on the axes, start bars at zero, mark a gap inside the
|
|
251
|
+
variation criterion as no clear change, and give the chart an explicit background colour so
|
|
252
|
+
it reads the same on a light or a dark page.
|
|
253
|
+
In a pull request, the headline chart and when it may be skipped come from
|
|
254
|
+
`hr-writing-pr`; this table applies to any other chart.
|
|
255
|
+
|
|
256
|
+
For agent, model, rule or skill comparisons, distinguish development cases
|
|
257
|
+
from held-out cases and report runs per case. Check each case for a ceiling: a
|
|
258
|
+
case every arm already passes cannot show a pass-rate improvement. Report it
|
|
259
|
+
apart from the cases that could, and report any metric the case does not
|
|
260
|
+
saturate (time, cost, graded quality) on its own. Include a one-line instruction
|
|
261
|
+
control when claiming an improvement from a rule or skill. Keep helper,
|
|
262
|
+
setup and retry costs visible. Before collecting results, define a per-case
|
|
263
|
+
contribution threshold. If a case exceeds it, report results both with and
|
|
264
|
+
without that case.
|
|
265
|
+
|
|
266
|
+
For bug-review evaluations, freeze the supported input contract and label
|
|
267
|
+
procedure before calls. A passing reference suite does not certify a clean
|
|
268
|
+
control. Adjudicate additional findings against that contract. A confirmed extra
|
|
269
|
+
defect makes the affected specificity estimate unavailable; retain earlier
|
|
270
|
+
receipts and introduce a new control version. Leave disputed domains unresolved.
|
|
271
|
+
|
|
272
|
+
Report provider completion, output-format compliance and independently checked
|
|
273
|
+
artifact acceptance separately. Distinguish observed call time from verification
|
|
274
|
+
and rework time. Keep returned usage units separate from attributable account
|
|
275
|
+
charges; unknown attribution remains unknown.
|
|
276
|
+
|
|
277
|
+
Record every experiment, rejected ones included, with the observed result and
|
|
278
|
+
what was decided. End with adopt, reject or inconclusive, and the evidence for that
|
|
279
|
+
decision. Any implementation or publication still follows the user's scope.
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
# JavaScript and TypeScript measurement
|
|
2
|
+
|
|
3
|
+
Use built-in runtime profilers and oha from [the tool reference](tools.md).
|
|
4
|
+
TypeScript applications execute through a runtime; compiler timing and
|
|
5
|
+
application timing answer different questions.
|
|
6
|
+
|
|
7
|
+
## TypeScript measurement
|
|
8
|
+
|
|
9
|
+
Use [compiler diagnostics](https://www.typescriptlang.org/tsconfig/extendedDiagnostics.html)
|
|
10
|
+
for compiler phases and repeated whole-command timing for builds. For application
|
|
11
|
+
performance, record the executed artifact, build target, module format and source
|
|
12
|
+
maps. Use the same compiled JS artifact for an engine-only comparison; report
|
|
13
|
+
startup or transformation separately when it is part of the question.
|
|
14
|
+
|
|
15
|
+
[Node type stripping](https://nodejs.org/api/typescript.html) performs no type
|
|
16
|
+
checking and ignores `tsconfig.json`. A successful direct `.ts` execution does
|
|
17
|
+
not establish TypeScript correctness.
|
|
18
|
+
|
|
19
|
+
## Running under Bun versus Node
|
|
20
|
+
|
|
21
|
+
Confirm the runtime before comparing: print `process.execPath` or
|
|
22
|
+
`process.versions.bun` from inside the code under test, in worker threads too.
|
|
23
|
+
Verified on Bun 1.4.x:
|
|
24
|
+
|
|
25
|
+
- `bun x vitest` is not Bun. `bun x` honors the tool's `#!/usr/bin/env node`
|
|
26
|
+
shebang and runs the whole suite under Node. Use `bun --bun x vitest run`.
|
|
27
|
+
- `node` can resolve to Bun. On Bun 1.4.3, a package script that calls `node` printed Bun's
|
|
28
|
+
version under `bun --bun run` and Node's under plain `bun run`; a `Bun.spawnSync(['node', …])`
|
|
29
|
+
reached real Node in both modes. The shim depends on Bun's `run.bun` setting, which defaults
|
|
30
|
+
on only when `node` is absent from `PATH`. Check `process.versions.bun` in the spawned process,
|
|
31
|
+
and filter `PATH` entries matching `/bun/i` when you need real Node.
|
|
32
|
+
- With no `node_modules` up the tree, `require.resolve` falls back to Bun's global
|
|
33
|
+
install cache ([oven-sh/bun#42893](https://github.com/oven-sh/bun/issues/42893)).
|
|
34
|
+
Pass `--no-install` for a hermetic "not installed" result.
|
|
35
|
+
- File-path and `{ eval: true }` workers both run under Bun, and `node:sqlite` and
|
|
36
|
+
NAPI `.node` addons load.
|
|
37
|
+
- Many busy, allocating workers wait on each other's parallel GC marking
|
|
38
|
+
([oven-sh/bun#44186](https://github.com/oven-sh/bun/issues/44186)); with 8
|
|
39
|
+
workers `BUN_JSC_numberOfGCMarkers=1` roughly halved wall time. Attribute with a
|
|
40
|
+
profiler before concluding anything about worker scaling.
|
|
41
|
+
- Node 26.11 renamed its synchronous SQLite classes to `Database` and `Statement`
|
|
42
|
+
(`DatabaseSync` and `StatementSync` stay as aliases) and caches common property
|
|
43
|
+
keys in its SQLite bindings. Record the exact Node version beside SQLite
|
|
44
|
+
results; an older baseline does not establish the gap on the new runtime.
|
|
45
|
+
|
|
46
|
+
## Choosing what to hunt
|
|
47
|
+
|
|
48
|
+
Start with something a user waits for. Use a representative workload and data size, then count the work before timing individual functions.
|
|
49
|
+
|
|
50
|
+
- Count messages and bytes per action, SQL statements, subprocesses, React commits, queue depth and oldest-item age. Measure idle CPU, event-loop delay and utilization. Use a CPU profile to attribute expensive work; delay alone does not identify its cause.
|
|
51
|
+
- Check repeated work first: whole-state rebuilds after small updates, serialization per subscriber, repeated parsing or validation, N+1 queries and per-row transactions. Check for backpressure when producers outrun consumers.
|
|
52
|
+
- Vary one input size while holding the rest fixed. Look for quadratic growth, large linear costs, and fixed costs paid too often. A high count alone does not establish a bottleneck.
|
|
53
|
+
- Check work that survives its owner: listeners, timers, caches, pending requests and reconnect loops. Measure repeated open/close cycles and hidden, idle and disconnected states separately.
|
|
54
|
+
- Profile startup imports, rendering and layout, compression, logging and tracing when they appear in the user-visible path. Investigate engine-specific tuning only when a profile identifies the relevant hot loop.
|
|
55
|
+
|
|
56
|
+
Record null results and their tested conditions. Stop a candidate when its measured benefit is within the declared variation criterion, or when it cannot materially improve the chosen user-visible outcome. Do not use a universal percentage cutoff.
|
|
57
|
+
|
|
58
|
+
### Deciding whether to move synchronous work
|
|
59
|
+
|
|
60
|
+
Prioritize hot paths, then inspect less frequent paths for long individual stalls. A rare operation can still delay unrelated requests.
|
|
61
|
+
|
|
62
|
+
Measure the longest blocked interval and the average blocked milliseconds per call multiplied by calls per second. The product is milliseconds blocked per second; divide by 1,000 to estimate the duty-cycle fraction. This average does not describe burst latency. Compare against the application's actual response and frame budgets. A 60 Hz frame is about 16.7 ms; higher refresh rates leave less time.
|
|
63
|
+
|
|
64
|
+
Reduce unnecessary work first. Consider reuse, bounded caching, batching and yielding between chunks when their correctness requirements fit. A promise or `async` wrapper does not make CPU work leave the event loop.
|
|
65
|
+
|
|
66
|
+
Use the runtime's asynchronous APIs for supported I/O. They add scheduling and completion overhead and can contend for a shared thread pool. For CPU work, compare chunked yielding with a reused [worker or worker pool](https://nodejs.org/api/worker_threads.html). Include worker startup, message and clone or transfer costs, queueing, memory, cancellation and shutdown. Do not create a new worker for every small call by default.
|
|
67
|
+
|
|
68
|
+
Compare equal completed work under representative concurrency. Report wall time, CPU, memory and unrelated-request latency beside the longest stall. Offloading may improve responsiveness while costing more total CPU; state that tradeoff. A saturated worker queue can erase the improvement. There is no universal payload size or duration at which async or a worker wins.
|
|
69
|
+
|
|
70
|
+
### Runtime checks
|
|
71
|
+
|
|
72
|
+
- **Cloudflare Workers:** [deployed timers](https://developers.cloudflare.com/workers/runtime-apis/performance/) such as `Date.now()` and `performance.now()` advance after I/O, so they cannot time an uninterrupted CPU section. Local Wrangler uses workerd and permits advancing timers; use it for attribution and confirm deployed behavior with platform CPU metrics. Check current platform limits. A Durable Object runs JavaScript on one thread, but requests can interleave across awaits; distinguish synchronous blocking from storage gates and explicit concurrency controls.
|
|
73
|
+
- **Bun:** JavaScriptCore and V8 can have different hot paths. Verify the runtime and use its profiler; remeasure relevant changes on each supported runtime.
|
|
74
|
+
- **Electron:** attribute renderer and main-process work separately. Synchronous IPC blocks the caller; expensive main-thread work can delay all windows.
|
|
75
|
+
- **React Native and web:** use production builds. Count commits per actual streamed update or action, not per estimated token. Separate JavaScript work from layout, paint and native UI work. Record visibility and observer overhead.
|
|
76
|
+
|
|
77
|
+
## Event-loop and server-code measurement
|
|
78
|
+
|
|
79
|
+
Each event-loop thread of a Node or Bun server runs request handling, timers and
|
|
80
|
+
synchronous database calls. A slow call matters when it holds that thread, so
|
|
81
|
+
measure the hold, not only the duration. (M) marks a result measured on one
|
|
82
|
+
workload and host, not a benchmark.
|
|
83
|
+
|
|
84
|
+
- **Measure the longest stall, not wall time.** Run a 1 ms `setInterval` that
|
|
85
|
+
records the largest gap between ticks while the call runs, after letting the
|
|
86
|
+
loop settle first. Report it beside wall time. They differ: a snapshot read took
|
|
87
|
+
79 ms of wall time and held the loop for 12.6 ms because the runtime yielded
|
|
88
|
+
between steps (M). `perf_hooks.monitorEventLoopDelay` has a resolution of at
|
|
89
|
+
least 1 ms, so use it for coarse trends, not for claims of a few ms. State the
|
|
90
|
+
probe interval beside any figure near it.
|
|
91
|
+
- **Time the real function, not a copy.** A copied string-appending coalescer
|
|
92
|
+
looked quadratic; the real one showed equal CPU and equal longest stall within
|
|
93
|
+
noise, because V8 joins repeated concatenation lazily (M). A replica that leaves
|
|
94
|
+
out framework overhead is only a lower bound. Run server code inside the
|
|
95
|
+
project's own test runner with its in-memory test layer, write results to a file
|
|
96
|
+
because runners often swallow `console.log`, and delete the temporary test
|
|
97
|
+
afterwards.
|
|
98
|
+
- **Count volume when volume is the cost.** For code that emits events or
|
|
99
|
+
messages, feed a fixed synthetic input through the real component and count the
|
|
100
|
+
events and serialized bytes at several sizes. Counts are deterministic, so they
|
|
101
|
+
need no repetitions; stall and wall time still do. One adapter emitted three
|
|
102
|
+
events per streamed chunk, two of them carrying the whole reply so far: 15,003
|
|
103
|
+
events (three per chunk plus one closing update of each) and 263.6 MB for 5,000
|
|
104
|
+
chunks of 10 characters (about 125 MB for each of
|
|
105
|
+
the two full-text copies), growing about 3.3 to 3.6 times per doubling, with a
|
|
106
|
+
longest stall under 6 ms (M). That is a volume problem, not
|
|
107
|
+
a stall.
|
|
108
|
+
- **Separate loop time from child-process time.** Work done by an asynchronously
|
|
109
|
+
spawned process uses CPU but does not hold the loop. Count such a spawn as loop
|
|
110
|
+
cost only for its spawning and parsing. `spawnSync`, `execSync` and `execFileSync` block the
|
|
111
|
+
loop for the child's whole lifetime, so count that time as a stall.
|
|
112
|
+
- **Prove that work left the loop with a test that cannot pass otherwise.** Hold
|
|
113
|
+
the main connection or thread busy (blocked on a latch) and
|
|
114
|
+
assert the moved work still completes. A speed measurement alone cannot show
|
|
115
|
+
where the work ran. Moving one read off the loop took the longest stall from a
|
|
116
|
+
median 165 ms to 2.5 ms over 12 runs per arm, with no clear change in wall time, measured with a 2 ms probe (M).
|
|
117
|
+
- **Measure retention with forced garbage collection.** Run N synthetic sessions
|
|
118
|
+
or turns, force a collection, and compare heap deltas with the suspect field
|
|
119
|
+
kept and dropped, keeping the owner reachable to the end. One researcher's run, not
|
|
120
|
+
repeated, kept only the two fields that were read and went from 61.45 MiB to
|
|
121
|
+
2.10 MiB over 30 sessions of 10 turns of 200 KiB.
|
|
122
|
+
- **Time startup on the built artifact, interleaved.** Alternate arms on
|
|
123
|
+
one build, using the default run count in [the skill](../SKILL.md). An
|
|
124
|
+
environment variable can stand in for an API
|
|
125
|
+
call, but note what it changes (it also reaches child processes). A V8 compile
|
|
126
|
+
cache took a CLI's `--help` from a 554 ms median to 381 ms over 11 runs (M).
|
|
127
|
+
- **Treat another researcher's numbers as leads.** Of three top candidates from a
|
|
128
|
+
model's blind read-only pass, re-measuring left one refuted, one mostly covered
|
|
129
|
+
by existing work and one real but small. Re-run a lead with the real function
|
|
130
|
+
and the stall probe before acting on it.
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
# Benchmarking and investigation tools
|
|
2
|
+
|
|
3
|
+
These defaults come from tools used in our work. Prefer a suitable runner
|
|
4
|
+
already used by the project. Check the official version's documentation before
|
|
5
|
+
relying on flags or interpreting output.
|
|
6
|
+
|
|
7
|
+
## Timing and resource measurement
|
|
8
|
+
|
|
9
|
+
| Task | Default and reason | Limits to record |
|
|
10
|
+
| ---------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
11
|
+
| Whole CLI commands | [Hyperfine](https://github.com/sharkdp/hyperfine): repeated runs with wall time, CPU time and peak memory, warmup/preparation and JSON output. | Works across Linux, macOS and Windows. Declare warm/cold conditions. Since 2.0 commands run without a shell unless `-S` or `--shell` is given; 1.x needs `-N` for that. Peak memory and `--metrics` hardware counters are measured on Linux and macOS only; on Windows use another tool for memory. Check `schema_version` before reading exported JSON; 2.0 changed its layout. |
|
|
12
|
+
| JavaScript operations | [Tinybench](https://github.com/tinylibs/tinybench), directly or through the project's benchmark runner: warmup and task latency/throughput statistics. | The unit is a task invocation. For 1,000-operation batches, batch p99 divided by 1,000 is the p99 of batch-average costs, not mean operation cost or individual-operation p99. |
|
|
13
|
+
| HTTP load, including JS/TS servers | [oha](https://github.com/hatoo/oha): a native load generator with concurrency/rate controls, latency distributions and JSON output. | Declare protocol, connections, rate, deadlines, keepalive and error handling. Check generator CPU/network limits. For fixed-rate load, `--latency-correction` corrects coordinated omission; it is ignored unless `-q` is set. |
|
|
14
|
+
| Command CPU and memory | [GNU time](https://www.gnu.org/software/time/manual/time.html), commonly `/usr/bin/time -v`: wall time, CPU and maximum RSS. | GNU options differ from shell `time` and BSD/macOS tools. RSS is a lifetime high-water mark for the observed process; it does not isolate retained cache memory. |
|
|
15
|
+
| Host or process contention | Linux [mpstat/pidstat](https://github.com/sysstat/sysstat): processor utilization and process CPU, memory and I/O observations. | Sampling can miss short bursts; some counters need kernel support. These explain interference, not application latency. |
|
|
16
|
+
|
|
17
|
+
On Linux with compressed swap enabled, observe compressed-swap activity as
|
|
18
|
+
well as disk swap I/O. Unchanged `pswpin`/`pswpout` counters do not establish
|
|
19
|
+
absence of swapping. For [zswap](https://www.kernel.org/doc/html/latest/admin-guide/mm/zswap.html),
|
|
20
|
+
record available `zswpin`/`zswpout`/`zswpwb` deltas from the benchmark cgroup's
|
|
21
|
+
`memory.stat` over the measured interval. Label host-wide deltas as system-wide;
|
|
22
|
+
they cannot attribute activity to the workload.
|
|
23
|
+
|
|
24
|
+
Use [cgroup swap and zswap accounting](https://www.kernel.org/doc/html/latest/admin-guide/cgroup-v2.html)
|
|
25
|
+
(`memory.swap.current`, `memory.zswap.current`) to distinguish the workload
|
|
26
|
+
from other jobs. These occupancy values do not measure activity by themselves.
|
|
27
|
+
Record missing counters and preserve the run plan's declared pressure criteria.
|
|
28
|
+
|
|
29
|
+
## Process attribution
|
|
30
|
+
|
|
31
|
+
Prefer `pidstat -u -r -d -p ALL 1 20` for the standard Linux process view.
|
|
32
|
+
For receipts that retain PID birth identity, use the bundled collector:
|
|
33
|
+
|
|
34
|
+
```sh
|
|
35
|
+
python3 scripts/process-attribution.py --seconds 20 --output /disk/path/receipt.json
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
Run from the skill directory. Linux receipts contain raw one-second snapshots
|
|
39
|
+
and CPU deltas ranked by busy cores, with process name, parent PID, birth ticks,
|
|
40
|
+
RSS pages and unmatched boundary counts. They omit command arguments.
|
|
41
|
+
|
|
42
|
+
Each row also reports `reapedChildCores`: CPU of children the process reaped
|
|
43
|
+
during the interval, attributed to that parent. It shows which process ran
|
|
44
|
+
commands too short-lived to appear in a snapshot, not the commands themselves,
|
|
45
|
+
and can include CPU the children used before the interval started.
|
|
46
|
+
|
|
47
|
+
Each interval reports `cpuBusyCores` per logical CPU. Busy CPU excludes idle,
|
|
48
|
+
iowait and steal time. A CPU brought online or offline during the interval
|
|
49
|
+
reports `null`.
|
|
50
|
+
The collector uses its own `/proc/self/status` `VmHWM` for peak RSS;
|
|
51
|
+
`ru_maxrss` can retain a launcher's inherited high-water mark.
|
|
52
|
+
It records observer CPU and scan duration. Report those costs beside the results; no
|
|
53
|
+
negligible-impact claim follows from successful collection.
|
|
54
|
+
|
|
55
|
+
On Windows, `scripts/process-attribution.ps1` accepts mandatory `OutputPath`
|
|
56
|
+
and `StopPath` arguments. It saves process PID, start time, name and cumulative
|
|
57
|
+
CPU, plus host activity and observer CPU/working set. Match PID and start time
|
|
58
|
+
before computing deltas. It stops when the stop file exists or after 120 samples;
|
|
59
|
+
choose a fresh stop path. Use the host's approved PowerShell invocation without
|
|
60
|
+
changing execution policy.
|
|
61
|
+
|
|
62
|
+
Neither collector stops jobs or changes any setting. Boundary samples
|
|
63
|
+
miss processes that start and exit between them; unreadable processes are counted
|
|
64
|
+
as missing. CPU contributors explain observed activity, not whether it changed
|
|
65
|
+
application latency.
|
|
66
|
+
|
|
67
|
+
## Scheduling controls
|
|
68
|
+
|
|
69
|
+
These Linux controls change resource allocation under competition; they do not
|
|
70
|
+
establish isolation. Check support for the actual kernel, controller and I/O
|
|
71
|
+
path. Record effective values and unavailable controls for every arm; requesting
|
|
72
|
+
a setting does not prove it took effect.
|
|
73
|
+
|
|
74
|
+
| Control | Effect and limit |
|
|
75
|
+
| -------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
76
|
+
| [Nice level](https://man7.org/linux/man-pages/man2/nice.2.html) | Lower numeric values raise fair CPU scheduling priority. Permissions and autogroup policy affect the result. This does not reserve a core. |
|
|
77
|
+
| CPU affinity (`taskset`) | Restricts available CPUs and can affect worker counts and parallelism. It does not reserve exclusive cores. Use it for a declared CPU configuration, not automatic noise reduction. |
|
|
78
|
+
| [CPU and I/O cgroup weights](https://docs.kernel.org/admin-guide/cgroup-v2.html) | Adjust relative shares among active sibling groups. Parent limits and controller/device support still apply; a higher weight is not a capacity guarantee. |
|
|
79
|
+
| [Process I/O priority](https://man7.org/linux/man-pages/man2/ioprio_set.2.html) | Depends on the supporting I/O scheduler and path. Process-specific priority does not cover asynchronous writes. |
|
|
80
|
+
| [Memory protection](https://docs.kernel.org/admin-guide/cgroup-v2.html) | `memory.low` and `memory.min` protect against reclaim, not memory-bandwidth competition. Excessive hard protection can cause OOM. Memory caps remain limits, not reservations. |
|
|
81
|
+
|
|
82
|
+
In a virtual machine, guest affinity does not reserve host cores; host
|
|
83
|
+
activity, shared cache, memory bandwidth and power limits still apply.
|
|
84
|
+
|
|
85
|
+
Avoid realtime [CPU](https://man7.org/linux/man-pages/man7/sched.7.html) or
|
|
86
|
+
[I/O](https://man7.org/linux/man-pages/man1/ionice.1.html) classes for generic
|
|
87
|
+
benchmark noise reduction; they can starve dependencies or monitoring.
|
|
88
|
+
Preserve the host's scheduling policy unless it authorizes a different regime.
|
|
89
|
+
|
|
90
|
+
## Profiling and debugging
|
|
91
|
+
|
|
92
|
+
Use a separate diagnostic run; instrumentation changes the work it observes.
|
|
93
|
+
|
|
94
|
+
| Question | Tool and reason | Limits to record |
|
|
95
|
+
| ------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------- |
|
|
96
|
+
| Where does JavaScript CPU time go? | Runtime CPU profiler: [Node](https://nodejs.org/api/cli.html#--cpu-prof) or [Bun](https://bun.com/docs/project/benchmarking#cpu-profiling). | Match runtime/version and profile settings. Samples locate hotspots; verify improvements with unprofiled runs. |
|
|
97
|
+
| Which JS objects are allocated or retained? | Runtime allocation profiles and heap snapshots: [Node](https://nodejs.org/api/cli.html#--heap-prof), [Bun](https://bun.com/docs/project/benchmarking#heap-profiling). | Matching flags do not guarantee matching metrics; see the distinction below. |
|
|
98
|
+
| Where does native/kernel CPU work go? | Linux [perf stat](https://github.com/torvalds/linux/blob/master/tools/perf/Documentation/perf-stat.txt) and [perf record](https://github.com/torvalds/linux/blob/master/tools/perf/Documentation/perf-record.txt): counters, samples and call graphs. | Permissions, hardware/kernel support, symbols and stack unwinding affect evidence. Frame-pointer unwinding needs compatible binaries. |
|
|
99
|
+
| Which system calls fail or wait? | Linux [strace](https://github.com/strace/strace/blob/master/doc/strace.1.in): syscall results, errors and ordering. | Interception changes execution; summaries are not ordinary throughput. Traces may contain sensitive paths or payloads. |
|
|
100
|
+
| Which native allocations churn? | Linux [heaptrack](https://github.com/KDE/heaptrack): allocation counts, temporary allocations and allocation stacks. | Symbols improve attribution. Pool allocators need annotations; native allocation traces do not identify individual GC-managed JS objects. |
|
|
101
|
+
|
|
102
|
+
### Native and JavaScript CPU profiles
|
|
103
|
+
|
|
104
|
+
Keep native symbols in the diagnostic build. For a Rust release build, use
|
|
105
|
+
`CARGO_PROFILE_RELEASE_DEBUG=line-tables-only CARGO_PROFILE_RELEASE_STRIP=none`.
|
|
106
|
+
For Node JIT frames under `perf`, add `--perf-basic-prof`. A runtime CPU profile
|
|
107
|
+
may attribute a native addon's work to its JavaScript caller; use native samples
|
|
108
|
+
to see inside that call. Node `--cpu-prof` writes separate files for worker threads;
|
|
109
|
+
retain them alongside the main-thread profile.
|
|
110
|
+
|
|
111
|
+
If `perf report` stalls while expanding a large binary's inline frames, try
|
|
112
|
+
`perf report --stdio --no-inline`. This omits inline-call expansion, so record
|
|
113
|
+
that limit when attributing samples.
|
|
114
|
+
|
|
115
|
+
### Viewing profiles
|
|
116
|
+
|
|
117
|
+
[speedscope](https://github.com/jlfwong/speedscope) opens profiles locally as
|
|
118
|
+
interactive flame graphs, including Node CPU profiles and Linux `perf` captures.
|
|
119
|
+
It has been used to inspect JavaScript and native stacks across worker threads.
|
|
120
|
+
To import a `perf` capture, write `perf script > profile.perf` without a custom
|
|
121
|
+
`-F` field list; a partially recognized format can display one stack without an
|
|
122
|
+
import error. Check that the expected threads and stacks appear.
|
|
123
|
+
|
|
124
|
+
The npm CLI opens the default browser with `speedscope <profile>`. When using a
|
|
125
|
+
controlled browser, serve its packaged `dist/release/` directory and the profile
|
|
126
|
+
over loopback HTTP, then open `index.html#profileURL=<URL-encoded-profile-url>`.
|
|
127
|
+
Use `encodeURIComponent(profileUrl)` for the value so query parameters remain
|
|
128
|
+
part of the profile URL. Choose a free port and keep private captures on the
|
|
129
|
+
local host. Follow the host's browser rules.
|
|
130
|
+
|
|
131
|
+
### Allocation and waiting-time limits
|
|
132
|
+
|
|
133
|
+
`heaptrack` unwinds a stack on each native allocation. Start with a small input:
|
|
134
|
+
millions of allocations can make instrumentation dominate runtime. Treat that
|
|
135
|
+
runtime as diagnostic overhead, and verify improvements with uninstrumented runs.
|
|
136
|
+
|
|
137
|
+
On-CPU profiles omit time spent off CPU. Use a separate
|
|
138
|
+
[bpftrace](https://bpftrace.org/docs) scheduler trace when a thread's wall time
|
|
139
|
+
greatly exceeds its CPU time. Track the target and its descendants, and aggregate
|
|
140
|
+
time between switch-out and switch-in. Off-CPU time includes both blocked time
|
|
141
|
+
and time runnable threads wait for a CPU; sums across threads can exceed wall time.
|
|
142
|
+
Kernel tracepoints, PID namespaces and privileges affect attribution, so verify
|
|
143
|
+
the target's identity and that probes attached before starting it.
|
|
144
|
+
|
|
145
|
+
Node `--heap-prof` samples allocation activity. Bun's documentation describes
|
|
146
|
+
a full V8-format heap snapshot at exit, not the same sampled allocation history;
|
|
147
|
+
its accepted interval flag does not add allocation sampling. Record which kind
|
|
148
|
+
of artifact was captured and verify semantics for the version used.
|
|
149
|
+
|
|
150
|
+
For a concrete crash, hang or event-tracing question, use the available
|
|
151
|
+
[debugger](https://www.sourceware.org/gdb/documentation/) or
|
|
152
|
+
[system tracing tool](https://bpftrace.org/docs). They are optional diagnostic
|
|
153
|
+
tools, not benchmark prerequisites; platform and permissions affect availability.
|
|
154
|
+
|
|
155
|
+
For TypeScript compiler versus application timing, and for Bun-versus-Node pitfalls, read [the language reference](javascript.md).
|
|
156
|
+
|
|
157
|
+
## Correctness and audit evidence
|
|
158
|
+
|
|
159
|
+
Use the repository's lint, type checks, focused tests and relevant static or
|
|
160
|
+
security analysis. These establish intended behavior and detect defects; passing
|
|
161
|
+
them does not establish speed or memory use. State their coverage limits.
|
|
162
|
+
|
|
163
|
+
Add a tool after using it successfully on a real task. Record the question it
|
|
164
|
+
answered, why it helped, its platform and measurement limits, and the official
|
|
165
|
+
documentation. Keep untried candidates in research notes until then.
|