Agent Skills › uw-syfi/vibesys › dial9-zoom-window

dial9-zoom-window

GitHub

用于在 dial9 追踪分析中,针对聚合阶段发现的异常时间戳,放大查看特定窗口内各工作进程和 OS 线程的详细执行情况。

resources/skills/dial9-tokio/skills/dial9-zoom-window/SKILL.md uw-syfi/vibesys

Trigger Scenarios

用户请求放大查看特定时间点的事件详情 聚合分析工具标记出长轮询、队列积压或延迟异常的时间戳后

Install

npx skills add uw-syfi/vibesys --skill dial9-zoom-window -g -y
More Options

Non-standard path

npx skills add https://github.com/uw-syfi/vibesys/tree/main/resources/skills/dial9-tokio/skills/dial9-zoom-window -g -y

Use without installing

npx skills use uw-syfi/vibesys@dial9-zoom-window

指定 Agent (Claude Code)

npx skills add uw-syfi/vibesys --skill dial9-zoom-window -a claude-code -g -y

安装 repo 全部 skill

npx skills add uw-syfi/vibesys --all -g -y

预览 repo 内 skill

npx skills add uw-syfi/vibesys --list

SKILL.md

Frontmatter
{
    "name": "dial9-zoom-window",
    "description": "Zoom into a narrow time window of a dial9 trace to see every worker and OS thread at one moment. Use after an aggregate pass (`analyze.js`, `red_flag_scan.js`) flags a timestamp: a long poll, a queue spike, a latency outlier. Use when the user says \"zoom in\", \"what was happening at +6953ms\", or \"show me the window around that poll\". Also covers sharing a window as a dial9 viewer deep link, with the full list of viewer URL parameters."
}

Zooming into a time window

Aggregate analysis averages over the whole trace; it cannot show what was happening around a single event. Pick a timestamp and reconstruct the instant: which polls ran on which workers, who was on-CPU, whether the queue was backed up.

Pair with dial9-diagnose-long-poll (applies this windowing to root-cause one poll) and dial9-runtime (the execution model).

When to zoom

Zoom after an aggregate pass has given you a timestamp of interest:

  • A long poll from red_flag_scan.js (Poll of 53.1ms ... at 6953.5ms) — but note that "long" is relative: judge a poll by how far it sits in this runtime's own poll-duration tail (pollDurationByLoc p99), not an absolute millisecond cutoff. See dial9-diagnose-long-poll for the calibration.
  • A scheduling-delay outlier or queue-depth spike
  • A pollDurationByLoc max you want to see in context
  • A specific request_id whose spans you've located in time

Do not zoom to go fishing in a healthy trace — you'll drown in microsecond polls. Start aggregate, then zoom to the timestamp the aggregate flagged.

The mechanics: timestamps

dial9 timestamps are nanoseconds. Every tool reports time relative to the start of the trace in milliseconds (+6953.5ms). To convert a relative-ms position to an absolute timestamp:

absoluteNs = trace.minTs + relMs * 1e6

A window is [center - half, center + half]. Pick half to be a few times the duration of the event you're studying: for a 53ms poll, a ±40ms half-window shows the poll plus what bracketed it on both sides.

Run it

node scripts/zoom.js <trace.bin|dir> <centerMs> [halfWindowMs=20]

centerMs is the relative-ms timestamp from the aggregate tools.

Example — zoom on a 53ms long poll the red-flag scan reported at +6953ms:

node scripts/zoom.js /tmp/traces/host3/trace.bin.gz 6980 40

What it shows, and how to read each section

1. Cross-worker poll timeline

Every poll overlapping the window, across all workers, ordered by start time. * marks polls > 1ms, annotated with on-CPU / off-CPU. This is the "what ran when" view — read it top to bottom like a tape.

What to look for:

  • A single * poll that dwarfs everything else → your event. Note its worker.
  • A burst of polls for one task= → a hot connection or a tight wake loop.
  • A gap with no polls → the runtime was parked (nothing to do) or everything was blocked inside one long poll.

2. Per-worker busy time

How many ms of the window each worker spent inside polls. One worker at ~100% and the rest near 0% means the work is not parallelized across the window — either one task is hogging a worker, or the box is nearly idle with one straggler.

3. Per-OS-thread CPU census ← the section people forget

CPU samples in the window grouped by OS thread (tid), with an estimate of on-CPU time. This is the most important and least obvious view:

perf samples a thread only while it is ON-CPU. A parked/blocked thread produces zero samples. So this census is a census of who was actually running, regardless of what the tokio scheduler thought.

At the 99 Hz default, one sample ≈ 10ms of on-CPU time for that thread. So:

  • 5 samples on one tid over a 50ms window ≈ that tid was on-CPU the whole time.
  • gaps~10.0ms (evenly spaced) confirms it was continuously running, not bursty.
  • A tid here that is not a tokio worker (e.g. a spawn_blocking pool thread, a metrics flusher, the allocator) is often the hidden actor behind a stall.
  • No samples at all in the window → the whole box was idle; any long poll in the window is blocked off-box (network/disk), not on local CPU or a local lock.

Do not reason from the aggregate sample rate ("p50 gap was 70ms so the box was idle") — aggregate gaps are large precisely because few threads are on-CPU. Always reason per tid.

4. Global queue depth

Max/min global injection-queue depth in the window. max=0 while a worker sits in a 53ms poll is the proof that the long poll was not causing head-of-line blocking — nothing was waiting behind it. max>0 means work piled up: the long poll (or a busy runtime) was actually delaying other tasks.

5. Inner spans of the dominant poll

If the app installed the tracing layer (Dial9TracingLayer), the tracing spans that executed inside the longest poll, by name. Tells you what code ran inside a long poll even without reading CPU stacks.

Share the window as a viewer deep link

Every window has a URL. The full interactive viewer honors ?start=/?end= (ABSOLUTE monotonic ns, visible viewport bounds) per its stable URL contract, which ships with this skill as references/viewer-urls.md: every param the viewer, flamegraph and trace browser pages honor, plus ready-made link recipes. zoom.js prints this link at the end of every window report; to construct it yourself from the relative-ms numbers the aggregate tools print:

// centerMs / halfMs: the same numbers you passed to zoom.js.
const centerMs = 6953.5, halfMs = 40;
const start = Math.round(trace.minTs + (centerMs - halfMs) * 1e6);
const end = Math.round(trace.minTs + (centerMs + halfMs) * 1e6);
console.log(`viewer.html?trace=<TRACE_URL>&start=${start}&end=${end}`);

<TRACE_URL> is the trace served over HTTP, percent-encoded: the viewer cannot fetch file:// paths. "Building a link" in references/viewer-urls.md covers serving it with dial9 serve. The same start/end params work on flamegraph.html as parse-time bounds for a CPU-profile view of the window. When the window explains a finding, link the sample itself too (the dominant poll, its task, a blocking-call analysis of the window), as "Linking analysis findings" there describes. Do not invent ?worker= or ?source=; the reference lists every param the pages honor.

From window back to cause

The zoom is descriptive — it shows the instant. To turn "worker 9 sat in a 53ms off-CPU poll while tid=31 ran EmfCollector::flush the whole time" into a root cause and a fix, hand off to dial9-diagnose-long-poll, which formalizes the per-tid census into a holder-vs-off-box verdict and corroborates it across the trace.

Version History

  • 256ebe6 Current 2026-10-18 21:29

Same Skill Collection

.agents/skills/add-agent-provider/SKILL.md
.agents/skills/add-bundled-skill/SKILL.md
.agents/skills/build-client-feature/SKILL.md
.agents/skills/change-container-images/SKILL.md
.agents/skills/create-issue/SKILL.md
.agents/skills/enforce-rules/SKILL.md
.agents/skills/open-pr/SKILL.md
.agents/skills/review-pr/SKILL.md
.agents/skills/software-design/SKILL.md
.agents/skills/testing/SKILL.md
.agents/skills/vs-init/SKILL.md
.agents/skills/write-agent-prompt/SKILL.md
.agents/skills/write-docs/SKILL.md
.agents/skills/write-skills/SKILL.md
.agents/skills/write-vibesys-tests/SKILL.md
resources/skills/dial9-tokio/skills/dial9-diagnose-long-poll/SKILL.md
resources/skills/dial9-tokio/skills/dial9-red-flags/SKILL.md
resources/skills/dial9-tokio/skills/dial9-runtime/SKILL.md
resources/skills/dial9-tokio/skills/dial9-toolkit/SKILL.md
resources/skills/dial9-tokio/skills/dial9-trace-analysis/SKILL.md
resources/skills/dial9-tokio/skills/dial9-trace-loading/SKILL.md
resources/skills/dial9-tokio/skills/dial9-trace-recipes/SKILL.md
resources/skills/kernel-correctness/SKILL.md
resources/skills/kernel-ncu-analysis/SKILL.md
resources/skills/kernel-performance/SKILL.md
resources/skills/kernel-rocprof-analysis/SKILL.md
resources/skills/microservice-optimization/SKILL.md
resources/skills/neuron-agentic-development/skills/neuron-nki-debugging/SKILL.md
resources/skills/neuron-agentic-development/skills/neuron-nki-docs/SKILL.md
resources/skills/neuron-agentic-development/skills/neuron-nki-profiling/SKILL.md
resources/skills/serving-systems/SKILL.md
.agents/skills/change-module-graph/SKILL.md
.agents/skills/triage-prs/SKILL.md
.agents/skills/tui-bug-hunt/SKILL.md
.agents/skills/vs-meta-opt/SKILL.md
resources/skills/neuron-agentic-development/skills/neuron-nki-profile-querying/SKILL.md
resources/skills/neuron-agentic-development/skills/neuron-nki-writing/SKILL.md

Metadata

Files
0
Version
256ebe6
Hash
e66077f2
Indexed
2026-10-18 21:29

홈 - 위키
Copyright © 2011-2026 iteam. Current version is 2.155.2. UTC+08:00, 2026-10-20 03:04
浙ICP备14020137号-1