Agent Skills › looplj/reveric › profile

profile

GitHub

在修改代码前收集运行时性能数据,定位 CPU、内存或渲染瓶颈。禁止凭直觉修复,需先捕获热点路径证据。

.agents/skills/profile/SKILL.md looplj/reveric

触发场景

用户报告高 CPU、UI 卡顿或重建过多 用户要求先进行性能分析而非直接猜测

安装

npx skills add looplj/reveric --skill profile -g -y
更多选项

非标准路径

npx skills add https://github.com/looplj/reveric/tree/unstable/.agents/skills/profile -g -y

不安装直接使用

npx skills use looplj/reveric@profile

指定 Agent (Claude Code)

npx skills add looplj/reveric --skill profile -a claude-code -g -y

安装 repo 全部 skill

npx skills add looplj/reveric --all -g -y

预览 repo 内 skill

npx skills add looplj/reveric --list

SKILL.md

Frontmatter
{
    "name": "profile",
    "description": "Profile CPU, memory, rebuild, rendering, or performance regressions before changing code. Use when the user reports high CPU, slow UI, jank, excessive rebuilds, memory growth, Activity Monitor spikes, Flutter DevTools profiling, VM service sampling, native sample\/Instruments evidence, or asks to \"profile first\" \/ \"不要猜\"."
}

Profile

Use this skill to collect runtime evidence before diagnosing performance issues. Do not patch from intuition. First capture a bounded profile while the symptom is happening, then name the concrete hot path.

Rules

  • Do not change code until a profile names the hot function, widget, isolate, thread, or native frame.
  • If CPU has already dropped, say the profile would be idle and wait for the user to reproduce.
  • Do not use screenshots as profiling evidence unless the user asks or visual state is essential.
  • Do not request huge VM sample windows such as timeOriginMicros=0&timeExtentMicros=999999999999999; it can hang and mixes idle history with the incident.
  • On macOS, avoid date -Is; use date "+%Y-%m-%dT%H:%M:%S%z".
  • Quote file paths passed to Python via sys.argv; do not interpolate unquoted paths into python -c.
  • If enabling Flutter profiling extensions, turn them off after capture.

Flutter macOS High CPU Workflow

1. Identify the Process

Use Activity Monitor PID if the user provides it. Otherwise:

pgrep -fl Reveric
ps -p <pid> -o pid,ppid,stat,etime,time,%cpu,%mem,command

If %CPU is low, do not claim a hot path. Prepare profiling and wait for reproduction.

2. Find VM Service URL

For flutter run -d macos, the app process has a VM service port and Flutter starts a development-service process containing the auth code.

lsof -Pan -p <app-pid> -iTCP -sTCP:LISTEN
ps -Ao pid,ppid,stat,etime,%cpu,%mem,command | rg "development-service|flutter_tools|Reveric"

Look for:

dart development-service --vm-service-uri=http://127.0.0.1:<port>/<auth-code>/ ...

Use the app VM service base URL:

BASE="http://127.0.0.1:<port>/<auth-code>"

Verify it:

curl -s "$BASE/getVM"

If the response says missing or invalid authentication code, the auth code is wrong or missing.

3. Identify the Main Isolate

curl -s "$BASE/getVM"

Pick the non-system isolate named main, e.g. isolates/3075428996077979. URL-encode the slash:

ISO="isolates%2F3075428996077979"

4. Capture a Bounded Hot Window

Capture only while CPU is high. Use VM timeline timestamps to bound getCpuSamples.

BASE="http://127.0.0.1:<port>/<auth-code>"
ISO="isolates%2F<main-isolate-id>"
PID=<app-pid>
OUT=/tmp/reveric-highcpu

echo "capture_start cpu=$(ps -p "$PID" -o %cpu= | tr -d ' ') at=$(date '+%Y-%m-%dT%H:%M:%S%z')"
curl -s -o "$OUT.vm.json" "$BASE/getVM"
curl -s -o "$OUT.isolate.json" "$BASE/getIsolate?isolateId=$ISO"
curl -s -o "$OUT.timeline_start.json" "$BASE/getVMTimelineMicros"
start=$(python3 -c 'import json,sys; print(json.load(open(sys.argv[1]))["result"]["timestamp"])' "$OUT.timeline_start.json")

sample "$PID" 8 -file "$OUT.native-sample.txt" >/tmp/reveric-sample-command.log 2>&1 &
sample_pid=$!
sleep 8

curl -s -o "$OUT.timeline_end.json" "$BASE/getVMTimelineMicros"
end=$(python3 -c 'import json,sys; print(json.load(open(sys.argv[1]))["result"]["timestamp"])' "$OUT.timeline_end.json")
extent=$((end-start))
curl -s -o "$OUT.cpu-samples.json" "$BASE/getCpuSamples?isolateId=$ISO&timeOriginMicros=$start&timeExtentMicros=$extent"
wait "$sample_pid"
ps -p "$PID" -o pid,stat,etime,time,%cpu,%mem,command > "$OUT.ps.txt"
echo "capture_done start=$start extent=$extent cpu=$(ps -p "$PID" -o %cpu= | tr -d ' ') files=$OUT.*"

sample gives native/main-thread evidence. getCpuSamples gives Dart function evidence. Use both.

Parse CPU Samples

Summarize Dart samples:

python3 - /tmp/reveric-highcpu.cpu-samples.json <<'PY'
import json, collections, sys
p = sys.argv[1]
data = json.load(open(p))['result']
funcs = data['functions']
samples = data['samples']
exclusive = collections.Counter()
inclusive = collections.Counter()
tags = collections.Counter()
for s in samples:
    tags[s.get('vmTag', '?')] += 1
    stack = s.get('stack') or []
    if stack:
        exclusive[stack[0]] += 1
        inclusive.update(stack)
def name(i):
    f = funcs[i]
    return f"{f.get('function', {}).get('name')} {f.get('resolvedUrl') or ''}"
print('sampleCount', data.get('sampleCount'), 'period', data.get('samplePeriod'), 'extent', data.get('timeExtentMicros'))
print('tags', tags.most_common())
print('\nTop exclusive:')
for i, _ in exclusive.most_common(40):
    print(exclusive[i], 'excl', inclusive[i], 'incl', name(i))
print('\nFirst app frame per sample:')
first = collections.Counter()
for s in samples:
    for i in s.get('stack') or []:
        url = funcs[i].get('resolvedUrl') or ''
        if 'package:reveric' in url or '/reveric-worktrees/' in url:
            first[i] += 1
            break
for i, _ in first.most_common(60):
    print(first[i], name(i))
PY

Read the result like this:

  • High Dart tag with top framework.dart updateChild/update/performRebuild: widget rebuild/update hot path.
  • High app frame such as parseStreamingJson: business code is driving the rebuilds or CPU work.
  • High RegExp_ExecuteMatch: look for regex in the app frames.
  • High native main-thread frame in sample: check paint/raster/layout vs Dart invocation.

Flutter Build/Rebuild Timeline

Use only after CPU samples show Flutter build/update work. Enable, clear timeline, capture a short window, then disable.

BASE="http://127.0.0.1:<port>/<auth-code>"
ISO="isolates%2F<main-isolate-id>"
PID=<app-pid>
OUT=/tmp/reveric-builds

curl -s "$BASE/ext.flutter.profileWidgetBuilds?isolateId=$ISO&enabled=true"
curl -s "$BASE/ext.flutter.profileUserWidgetBuilds?isolateId=$ISO&enabled=true"
curl -s "$BASE/ext.flutter.inspector.trackRebuildDirtyWidgets?isolateId=$ISO&enabled=true"
curl -s -o "$OUT.clear.json" "$BASE/clearVMTimeline"
echo "timeline_start cpu=$(ps -p "$PID" -o %cpu= | tr -d ' ')"
sleep 5
curl -s -o "$OUT.timeline.json" "$BASE/getVMTimeline"
ps -p "$PID" -o pid,stat,etime,time,%cpu,%mem,command > "$OUT.ps.txt"
curl -s "$BASE/ext.flutter.profileWidgetBuilds?isolateId=$ISO&enabled=false"
curl -s "$BASE/ext.flutter.profileUserWidgetBuilds?isolateId=$ISO&enabled=false"
curl -s "$BASE/ext.flutter.inspector.trackRebuildDirtyWidgets?isolateId=$ISO&enabled=false"

Summarize widget event counts and durations:

python3 - /tmp/reveric-builds.timeline.json <<'PY'
import json, collections, sys
p = sys.argv[1]
events = json.load(open(p))['result']['traceEvents']
print('events', len(events))
print('\nTop event names:')
for name, count in collections.Counter(e.get('name', '') for e in events).most_common(80):
    print(count, name)
stacks = collections.defaultdict(list)
summary = collections.defaultdict(lambda: [0, 0, 0])
for e in events:
    key = (e.get('tid'), e.get('name', ''))
    if e.get('ph') == 'B':
        stacks[key].append(e.get('ts'))
    elif e.get('ph') == 'E' and stacks[key]:
        dur = e.get('ts') - stacks[key].pop()
        row = summary[e.get('name', '')]
        row[0] += 1
        row[1] += dur
        row[2] = max(row[2], dur)
print('\nTop total durations:')
for name, (count, total, max_dur) in sorted(summary.items(), key=lambda kv: kv[1][1], reverse=True)[:100]:
    print(f'{total:>9}us total {count:>5}x avg={total/count:>7.1f}us max={max_dur:>7}us {name}')
PY

Use build profiling to identify rebuild fan-out. Example interpretation: a few NovelEditorPage builds with large duration means root-level rebuild is expensive; many SvgPicture/VectorGraphic/RevericIcon events means icon-heavy UI is being rebuilt repeatedly.

Outcome Format

Report evidence before recommendations:

Profile window:     [duration, pid, starting/ending CPU]
Dart samples:       [sampleCount, dominant tags]
Native sample:      [main thread / raster / IO / other dominant stack]
Hot app frames:     [function + file]
Build timeline:     [top widgets by count/duration, if captured]
Root hypothesis:    [specific path that explains all symptoms]
Next code target:   [file/function to inspect or change]
Artifacts:          [/tmp/... files]

Only propose a fix after the profile and source trace agree.

版本历史

  • ca297eb 当前 2026-11-02 08:45

同 Skill 集合

.agents/skills/cineview-design/SKILL.md
.agents/skills/domain-modeling/SKILL.md
.agents/skills/flutter-build-responsive-layout/SKILL.md
.agents/skills/flutter-fix-layout-issues/SKILL.md
.agents/skills/git/SKILL.md
.agents/skills/grilling/SKILL.md
.agents/skills/handoff/SKILL.md
.agents/skills/humanizer-zh/SKILL.md
.agents/skills/hunt/SKILL.md
.agents/skills/patrol/SKILL.md
.agents/skills/riverpod/SKILL.md
.agents/skills/sqlite/SKILL.md
.agents/skills/tdd/SKILL.md
.agents/skills/think/SKILL.md
.agents/skills/worktree/SKILL.md
.agents/skills/write/SKILL.md
assets/official_skills/map-design/SKILL.md
assets/official_skills/screenplay-production/SKILL.md
assets/official_skills/screenplay-writing/SKILL.md
designs/desktop/SKILL.md
.agents/skills/baoyu-design/SKILL.md
.agents/skills/impeccable/SKILL.md
assets/bundled_skills/canvas-composition/SKILL.md
assets/bundled_skills/management/SKILL.md
assets/bundled_skills/media-editing/SKILL.md
assets/bundled_skills/screenplay-tools/SKILL.md
assets/bundled_skills/setup/SKILL.md
assets/bundled_skills/story-continuity/SKILL.md
.agents/skills/grill-me/SKILL.md
.agents/skills/grill-with-docs/SKILL.md

元信息

文件数
0
版本
ca297eb
Hash
e6a4efb2
收录时间
2026-11-02 08:45

首页 - Wiki
Copyright © 2011-2026 iteam. Current version is 2.155.2. UTC+08:00, 2026-11-02 16:25
浙ICP备14020137号-1