Agent Skills › uw-syfi/vibesys › dial9-trace-loading

dial9-trace-loading

GitHub

解析本地Dial9 Tokio运行时追踪文件,理解ParsedTrace数据模型。适用于字节已就绪场景,用于分析事件、CPU采样及任务生命周期等底层性能数据。

resources/skills/dial9-tokio/skills/dial9-trace-loading/SKILL.md uw-syfi/vibesys

Trigger Scenarios

需要解析本地或内存中的Tokio运行时追踪数据 分析ParsedTrace结构以获取事件和性能指标

Install

npx skills add uw-syfi/vibesys --skill dial9-trace-loading -g -y
More Options

Non-standard path

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

Use without installing

npx skills use uw-syfi/vibesys@dial9-trace-loading

指定 Agent (Claude Code)

npx skills add uw-syfi/vibesys --skill dial9-trace-loading -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-trace-loading",
    "description": "Parse already-local dial9 Tokio runtime trace files or buffers and understand the ParsedTrace data model. Use when trace bytes are available locally or in memory; do not use to retrieve a viewer URL, API object, or S3 object."
}

Loading and Parsing Traces

Scope

This skill begins after trace bytes are local or already in memory. A viewer URL, API endpoint, or S3 location requires the environment's request or retrieval skill first. Do not select this skill merely because the eventual operation may decompress or parse a trace.

ParsedTrace structure

parseTrace(path) yields ParsedTrace objects:

{
  magic: string,                   // "D9TF" format identifier
  version: number,                 // trace format version
  events: TraceEvent[],          // PollStart, PollEnd, WorkerPark, WorkerUnpark, QueueSample, WakeEvent
  minTs: number|null,            // earliest event timestamp (ns), null if no events
  maxTs: number|null,            // latest event timestamp (ns), null if no events
  recordMinTs: number|null,      // earliest sliceable timestamped record (ns), null if none
  recordMaxTs: number|null,      // latest sliceable timestamped record (ns), null if none
  cpuSamples: CpuSample[],      // Periodic stack traces from perf/eBPF
  customEvents: CustomEvent[],   // Custom events; also spans when no spanEventSink is configured
  spawnLocations: Map<string, string>,    // spawn location ID → source location
  taskSpawnLocs: Map<number, string|null>,// task ID → spawn location (null if unknown)
  taskSpawnTimes: Map<number, number>,    // task ID → spawn timestamp (ns)
  taskTerminateTimes: Map<number, number>,// task ID → terminate timestamp (ns)
  callframeSymbols: Map<string, {symbol, location}|[{symbol, location}]>, // address → resolved symbol (array for inlined frames)
  threadNames: Map<number, string>,       // thread ID → name
  clockOffsetNs: number|null,            // monotonic-to-wall-clock offset
  clockSyncAnchors: [{monotonicNs, realtimeNs}],
  runtimeWorkers: Map<string, number[]>, // runtime name → worker IDs
  segmentMetadata: Map<string, string>,  // latest segment metadata key → value
  runtimeMetrics: [{t, runtimeName, globalQueue, aliveTasks}], // per-runtime scheduler samples (empty on pre-RuntimeMetrics traces)
  legacyActiveTaskSamples: [{t, count}], // process-wide QueueSample active-task samples from the transitional format
  truncated: boolean,
  timeFiltered: boolean,
  filterStartTime: number|null,          // start of time range filter (ns), null if unfiltered
  filterEndTime: number|null,            // end of time range filter (ns), null if unfiltered
  hasCpuTime: boolean,                   // trace includes CPU time data
  hasSchedWait: boolean,                 // trace includes kernel scheduling wait data
  hasTaskTracking: boolean,              // poll events carry task IDs (always true on current parser); for spawn/terminate checks use hasTaskLifetimes
  hasFullTaskCoverage: boolean,          // false => only dial9-spawned tasks are covered
  hasLocalQueueDepth: boolean,           // whether per-worker queue depth is available
  hasTaskLifetimes: boolean,             // false => no task spawn events in the trace
  sealedFiles: number,                   // files carrying a seal record (0 on traces predating it)
  incompleteFiles: number,               // of those, how many lost buffered events or inherited them; > 0 means counts are understated
  taskInstrumented: Map<number, boolean>, // task ID → whether task has tracing instrumentation
  taskDumps: Map<number, [{timestamp, callchain}]>, // task ID → async stack captures (sorted by timestamp); see dial9-tokio-telemetry `taskdump` feature
  allocEvents: AllocEvent[],     // Sampled memory allocations (requires dial9-tokio-telemetry memory-profiling feature)
  freeEvents: FreeEvent[],       // Deallocations paired with sampled allocs (requires `track_liveset`)
  memoryOverflows: [{timestamp, droppedAllocs, droppedFrees}], // Ring buffer overflow events (dropped samples per flush period)
  blockInPlaceGaps: [{workerId, fromTid, toTid, startNs, endNs}], // Detected block_in_place handoff intervals (worker attribution unknowable during gap)
  tidToWorker: Map<number, number>,  // thread ID → worker ID mapping (derived from park/unpark events)
  tidBindings: Map<number, [{timestamp, workerId}]>, // historical bindings for time-local context resolution
  stableTidToWorker: Map<number, number>, // TIDs bound to exactly one worker across the trace
}

Without a spanEventSink, an annotated completed span remains a custom event and carries a normalized singleEventSpan projection. The primary viewer configures a sink, so legacy and single-event spans are instead stored in the optional spanEvents columns and are absent from customEvents. The normalized projection contains start, end, name, spanType, threadId, taskId, workerId, fields, and units; structural-role fields are excluded from fields, except that the span.name field remains an attribute. Consumers should read both storage paths through the shared span-data builder rather than matching schema or physical field names.

Span timing uses any two of start, duration, and end. A packed event timestamp supplies end when present; fields carrying dial9.role=span.start or dial9.role=span.duration supply the other timing quantities using their unit annotations. Timestamp-less schemas must provide both timing fields. See docs/design/single-event-spans.md for the schema convention.

Event types

const EVENT_TYPES = {
  PollStart: 0,   // Worker begins polling a task
  PollEnd: 1,     // Worker finishes polling a task
  WorkerPark: 2,  // Worker goes to sleep (no work available)
  WorkerUnpark: 3,// Worker wakes up
  QueueSample: 4, // Global queue depth sample
  WakeEvent: 9,   // One task wakes another
};

TraceEvent fields

Field Present on Description
timestamp all Monotonic nanoseconds
workerId PollStart/End, Park/Unpark Which worker thread
taskId PollStart Which task is being polled
spawnLoc PollStart Source location where the task was spawned
localQueue PollStart, Park, Unpark Worker's local queue depth
globalQueue QueueSample Global injection queue depth
cpuTime Park, Unpark Cumulative CPU time (ns) for this worker
schedWait Unpark Kernel scheduling wait time (ns) since last park
wakerTaskId WakeEvent Task that sent the wake
wokenTaskId WakeEvent Task that was woken
targetWorker WakeEvent Worker the wake was sent to

CpuSample fields

Field Description
timestamp Monotonic nanoseconds
workerId Worker thread that was sampled
tid OS thread ID
source 0 = CPU profiling sample, 1 = scheduling (off-CPU) sample
callchain Array of address strings like "0x55cc6d053893"

AllocEvent fields

Field Description
timestamp Monotonic nanoseconds at the allocation
tid OS thread ID of the allocating thread
size Allocation size in bytes
addr Returned pointer address as a decimal string (BigInt-safe)
callchain Array of address strings like "0x55cc6d053893"

FreeEvent fields

Field Description
timestamp Monotonic nanoseconds at the free
tid OS thread ID of the freeing thread
addr Pointer that was freed, as a decimal string (BigInt-safe)
size Size of the allocation being freed (denormalized from the matching AllocEvent)
allocTimestampNs Monotonic-ns timestamp of the original allocation (denormalized)

Parse options

const trace = await parseTrace('/path/to/trace.bin', {
  maxEvents: 100000,        // Cap event count (metadata/symbols always parsed)
  startTime: 1000000000,    // Filter events to time range (absolute ns)
  endTime:   2000000000,
});

Converting timestamps

Trace timestamps are monotonic nanoseconds. To convert to wall clock:

if (trace.clockOffsetNs != null) {
  const wallNs = event.timestamp + trace.clockOffsetNs;
  const wallDate = new Date(wallNs / 1e6);
}

To get relative time from trace start:

const relativeMs = (event.timestamp - trace.minTs) / 1e6;

Symbol resolution

const { formatFrame, symbolizeChain, deduplicateSamples } = require('./trace_parser.js');

// Resolve a full callchain to frame objects
const frames = symbolizeChain(sample.callchain, trace.callframeSymbols);
// [{symbol: "hyper::proto::h1::dispatch::Dispatcher<...>::poll_inner", location: "hyper-0.14.28/src/proto/h1/dispatch.rs:174"}, ...]

// Format a single frame for display
const { text, docsUrl } = formatFrame(frames[0]);
// text: "Dispatcher::poll_inner dispatch.rs:174"

// Deduplicate samples by stack trace
const groups = deduplicateSamples(trace.cpuSamples, trace.callframeSymbols);
// [{count: 8932, leaf: "__schedule", frames: [...]}, ...]

Handling gzip

parseTrace automatically decompresses gzip input. Pass .bin.gz files directly.

Merging multiple trace files

Trace files can be concatenated back-to-back. The parser handles multiple concatenated segments transparently (headers, string pools, and schemas are re-read at each boundary).

gunzip -k segment-001.bin.gz segment-002.bin.gz segment-003.bin.gz
cat segment-001.bin segment-002.bin segment-003.bin > combined.bin

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-recipes/SKILL.md
resources/skills/dial9-tokio/skills/dial9-zoom-window/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
01981883
Indexed
2026-10-18 21:29

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