跳到正文
cccskills
免费在 GitHub 公开

perf-review

Check that a diff, branch, or PR keeps Octane hot paths fast - stable V8 shapes and monomorphic sites, DOM work without forced layout, no new microtask hops or ad-hoc task posters - and that it carries the evidence each risk needs. Use before readying a PR that touches packages/octane/src, compiler output, or binding hot paths, or when reviewing agent-written code.

中文简介正在准备中。当前显示原文说明。

集成工具GitHub
查看安装方法

包含的文件(1)

  • SKILL.md8.3 KB

SKILL.md(原文)

安装前可以查看交给 AI 代理的指令内容。

Skill: Perf review

Use this to verify that a change applied the hot-path discipline in performance-audit, which you load alongside this skill. Its references hold the rules and the runtime code that already follows them: V8 shapes, DOM work, and scheduling.

This is a validator. On someone else's PR, report findings and do not push fixes unless asked. On your own diff before handoff, fix every must-fix finding and run the review again.

1. Choose the target

node scripts/perf-review-scan.mjs                         # your worktree against its merge-base with origin/main
node scripts/perf-review-scan.mjs --head <branch>         # a branch's committed diff
gh pr diff <number> --repo octanejs/octane | node scripts/perf-review-scan.mjs --diff -
node scripts/perf-review-scan.mjs packages/<binding>/src/ # a binding's hot path
  • The default scope is shipped runtime source under packages/octane/src, excluding compiler/. Path prefixes replace that scope; tests, fixtures, and benchmarks are always excluded. --json prints machine-readable findings.
  • gh pr diff carries only three lines of context, so the loop and read-after-write notes see less. A pasted diff also lacks the head's runtime modules, so --diff skips hot-class-shape. For a full review, check out the PR head in a worktree and use --head.

2. Classify the change before judging it

For each changed function, find its callers and decide how often it runs:

  • Hot: per render, node, item, event, signal notification, or server request. Framework fundamentals count as hot until the call graph shows otherwise (.rulesync/rules/core-engineering.md).
  • Cold: module initialization, once per root, error and abort paths, and development-only branches. A development-only branch must still not change a production shape.

Then note which dimensions apply: shapes and allocation, reachability, DOM, scheduling, and compiler output.

3. Read the mechanical candidates

The scan reports candidates on added lines with comments and strings blanked. Every candidate must end up as a finding or as a dismissal with a reason.

RuleCatchesTypical dismissal
hot-class-shapeA BlockImpl, ScopeImpl, or LiteBlockImpl field that is a runtime class field, never assigned in the constructor, assigned conditionally, or assigned without a declarationNone. Holds on main; fix it
hot-field-writeA write through a Block or Scope receiver, cast or not, to a field those classes do not declareNone. Holds on main; declare and initialize it
delete-operatordelete on an objectIntentional dictionary or cold path
conditional-shape...(cond ? {…} : {…}) or ...(cond && {…})Cold options object
shape-mutationObject.freeze, defineProperty, setPrototypeOf outside module-scope constantsOnce per template or module, or a pinned exemplar
holey-arraynew Array(n) without .fillNever indexed out of order and cold
rest-or-argumentsA rest parameter or argumentsCold branch, as in the HMR wrapper
layout-readGeometry reads, noting a DOM write earlier in the hunkBatched measure phase, or a layout effect that reads before writing
microtask-hopqueueMicrotask, Promise.resolve().then, noting an enclosing loopOne hop per burst that does no framework work per value
await-as-yieldawait of a settled valueNot used to yield
schedule-renderA new scheduleRender call, noting an enclosing loopCalled once per burst, not per item or value
animation-framerequestAnimationFrameVisual work meant to land before paint, with a timer fallback
task-posterMessageChannel, setTimeout(…, 0) or without a delay, setImmediate, postTask, requestIdleCallbackExtends an existing poster

The scan cannot see the following, so check them by hand:

  • Compiled output. Compile a representative fixture from packages/octane/tests/_fixtures/ before and after through the public compiler. Diff it for per-render closures, literals whose keys vary, extra runtime calls per node, changed bagN arity, and new runtime imports.
  • Reachability. A new reference from a hot or compiled path to a large function or driver, a new import into a runtime module, or a hydrating guard that does not fold.
  • Polymorphism and representation. A hot function that now receives a new receiver shape or argument type, returns a different shape, or stores a new type in an existing field, such as a double in a Smi field or undefined in a numeric one.
  • Allocation. Closures, literals, spreads, Array.from, or iterators created per item or per render.
  • DOM across functions. A read after a write that sits in a different function or hunk, and new per-element listeners or per-node DOM creation where a template clone would do.
  • Scheduling semantics. An existing render request moved into a loop or a producer, more frequent drainPassivesBeforeRender, or a change to the contract in docs/differences-from-react.md §Scheduler.

4. Judge each dimension

Answer these from the code. Cite file:line for every answer.

  • Shapes: Is every new field on a hot record initialized at every allocation site, with identical keys and order across literal sites? Does any hot function gain a receiver map, argument type, or return shape?
  • Allocation: What does the change allocate per render or per item? Can it be hoisted, reused, or replaced with an intrusive list?
  • DOM: Are reads batched before writes, and outside the render walk? Is each built subtree inserted once? Do resize callbacks that write go through createResizeObserver?
  • Scheduling: Can any producer now render or commit per value or hop? Does a new microtask chain do framework work at each step? Does a new task poster duplicate schedulePostPaint, actCheckpoint, createResizeObserver's poster, or resumeOnSettle, and does it survive hidden tabs and act()? Does the change alter the documented contract without a decision from #1864?
  • React divergences: Is anything you would flag a documented divergence in docs/differences-from-react.md? Those are not defects. When a trade-off is ambiguous, prefer React semantics.

5. Require evidence

Each finding names the evidence it needs, from the table in performance-audit: a one-map %HaveSameMap probe, allocation per call with pinned semi-space, deterministic work counters, bundle rows from the CI report, the marker-task commit count, or Event Timing in Chromium. Mark whether the PR provides it.

Run only the owning suite or a scratch probe locally, one at a time. Leave the full pnpm test, benchmark sweeps, and browser suites to CI.

Report

## Perf review: <PR, branch, or worktree> (<base>..<head>)

Scan: `node scripts/perf-review-scan.mjs <args>` → <N> candidates.
Hot paths touched: <functions, with their frequency>.

| # | Severity | Location | Dimension | Finding | Required evidence | Provided? |
| --- | --- | --- | --- | --- | --- | --- |
| 1 | must-fix | packages/octane/src/runtime.ts:1234 | shapes | … | `%HaveSameMap` across modes | no |

Dismissed candidates:
- `packages/octane/src/runtime.ts:4567` [microtask-hop]: error-report path, once per uncaught error.

Not checked: <for example, browser latency, because no Chromium run>.
  • must-fix: breaks a rule on a hot path, or fails hot-class-shape or hot-field-write.
  • needs-evidence: may be fine, but the claim or the risk needs the listed measurement before the PR is ready.
  • note: a cold-path observation or a follow-up.

A finding without a file:line and an argument for why the path is hot is not a finding. When create-a-pr invokes this skill, paste the report into the PR body's validation section.

评价

还没有评价。欢迎分享你的使用感受。

评论

无需登录即可发表。欢迎分享使用感受、提问,或说明在哪些环境下无法运行。

还没有评论。来写第一条吧。

提交后会立即公开。请勿填写邮箱、电话等个人信息。URL 最多 2 个。

0 / 1000 字

此表单受 reCAPTCHA 保护,适用 Google 的隐私权政策和服务条款。

同一仓库的技能

Write a new Octane component in .tsrx, convert JSX to .tsrx, or add scoped <style> blocks and themes. Use when creating a .tsrx file rather than editing one, because the path-scoped tsrx-authoring rule only fires once such a file is open.

中文简介正在准备中。当前显示原文说明。

octanejs/octane14672026年10月21日 更新

Find and fix a bug in the octane monorepo. Use when given a failing test, a regression, or a report that behavior differs from expectation, including deciding whether a React mismatch is an intentional divergence.

中文简介正在准备中。当前显示原文说明。

octanejs/octane14672026年10月21日 更新

Keep a change small and in the existing idiom - size the plan and weigh smaller alternatives before writing it, reuse the mechanism that already owns the behavior instead of adding a parallel one, and simplify the diff before handoff. Use when planning any change beyond a few lines, before readying a PR, or when reviewing agent-written code for bloat.

中文简介正在准备中。当前显示原文说明。

octanejs/octane14672026年10月21日 更新

Open a pull request for octane work. Load before creating the branch, commit, changeset, or PR, including when opening a PR is the tail step of a task that was about something else.

中文简介正在准备中。当前显示原文说明。

octanejs/octane14672026年10月21日 更新

Work a GitHub issue in the octane repo. Use when given an issue number or link. Fetches the issue, classifies the owning area, and plans the fix.

中文简介正在准备中。当前显示原文说明。

octanejs/octane14672026年10月21日 更新

Change Octane's runtime, compiler, scheduler, reconciler, SSR, or hydration engine. Use before editing packages/octane/src. Covers the observable contract, hot-path analysis, and the performance evidence required before handoff.

中文简介正在准备中。当前显示原文说明。

octanejs/octane14672026年10月21日 更新

查看 octanejs 的全部技能

报告此技能的问题