본문으로 건너뛰기
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(원문)

설치하기 전에 에이전트에게 전달되는 지시 내용을 확인할 수 있습니다.

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 / 1,000자

이 양식은 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/octane1.5천2026년 10월 20일 업데이트

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/octane1.5천2026년 10월 20일 업데이트

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/octane1.5천2026년 10월 20일 업데이트

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/octane1.5천2026년 10월 20일 업데이트

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/octane1.5천2026년 10월 20일 업데이트

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/octane1.5천2026년 10월 20일 업데이트

octanejs의 스킬 모두 보기

이 스킬의 문제 신고