| name | dial9-toolkit |
| description | JavaScript analysis toolkit for parsing and analyzing dial9 Tokio runtime traces. Always start trace diagnosis with analyzeTraces() from analyze.js, then use parseTrace() and lower-level helpers only to confirm assumptions or drill into raw events. |
dial9 Analysis Toolkit
This skill provides the JavaScript modules for working with dial9 traces programmatically.
What traces capture
dial9 traces capture the internal behavior of a Tokio async runtime:
- Poll events: Every time a worker thread polls a task future (start/end timestamps, task ID, spawn location)
- Worker lifecycle: Park/unpark events with CPU time and kernel scheduling wait
- Queue depth: Periodic samples of the global injection queue
- Task lifecycle: Spawn and terminate events with spawn location
- Wake events: Which task woke which other task, and on which worker
- CPU samples: Periodic stack traces from perf/eBPF, attached to the poll they occurred in
- Scheduling samples: Stack traces captured when the kernel deschedules a worker thread (shows blocking calls)
- Clock sync: Monotonic-to-wall-clock anchors for correlating with external logs
- Span events: Enter/exit events from
tracing spans (#[instrument]), showing what happened inside each poll with field values and nesting
Quick start
node scripts/analyze.js <trace.bin or directory>
node scripts/analyze.js traces/ --sample 50
node scripts/analyze.js trace.bin --force
Modules
| File | Purpose |
|---|
scripts/analyze.js | CLI entry point and analyzeTraces() aggregation function |
scripts/diagnose_setup.js | Setup diagnostic: detects missing frame pointers, wake events, debug symbols, sched events |
scripts/trace_parser.js | Binary parser: parseTrace(path) yields ParsedTrace objects |
scripts/trace_analysis.js | Analysis functions: buildWorkerSpans, attachCpuSamples, etc. |
scripts/decode.js | Low-level binary format decoder |
Default workflow
- Always run
analyzeTraces(path) first for trace diagnosis. This automatically runs setup diagnostics first.
- If setup diagnostics report issues (missing frame pointers, missing wake events, missing debug symbols), help the user fix those before diving into performance analysis.
- Base initial findings on the aggregate result: long polls, worker spans, scheduling delays, CPU/off-CPU groups, queue depth, task lifecycle counts, and span summaries.
- Then use
parseTrace() or lower-level helpers only to confirm assumptions, inspect raw events, or follow a specific task/wake/span chronology.
Setup diagnostic
The setup diagnostic (diagnose_setup.js) runs automatically as part of analyze.js and checks for common configuration issues:
| Check | Severity | Symptom |
|---|
missing-frame-pointers | critical | CPU stacks are 1–3 frames deep instead of 10+ |
missing-wake-events | warning | Tasks spawned but no wake events recorded |
missing-debug-symbols | warning | Stack addresses unresolved or no source locations |
no-scheduling-events | info | No off-CPU samples (sched profiling not enabled) |
Run standalone:
node scripts/diagnose_setup.js <trace.bin or directory>
const { analyzeTraces } = require('./scripts/analyze.js');
const result = await analyzeTraces('/path/to/traces/');
analyzeTraces works on a single file or a directory. It returns a single aggregated result object with everything you need for diagnosis. See the dial9-trace-analysis skill for the full return schema.
After the aggregate pass, use the low-level parser to confirm assumptions or inspect raw details that the aggregate result points at, such as specific tasks, custom filters, wake chains, or per-file chronology:
const { parseTrace } = require('./scripts/trace_parser.js');
const trace = await parseTrace('/path/to/trace.bin');
for await (const trace of parseTrace('/path/to/traces/')) { ... }