Table of Contents

Class TraceFileReader

Namespace
Typhon.Profiler
Assembly
Typhon.Profiler.dll

Reads a .typhon-trace binary trace file — the variable-size typed-record layout (see CurrentVersion for the current format version; MinSupportedVersion is the oldest still accepted). Provides sequential block-by-block access, yielding a raw byte span that the caller walks as a sequence of size-prefixed records.

public sealed class TraceFileReader : IDisposable
Inheritance
TraceFileReader
Implements
Inherited Members

Remarks

Typical use pattern:

using var reader = new TraceFileReader(stream);
reader.ReadHeader();
reader.ReadSystemDefinitions();
reader.ReadArchetypes();
reader.ReadComponentTypes();
while (reader.ReadNextBlock(out var records))
{
    var pos = 0;
    while (pos < records.Length)
    {
        var size = BinaryPrimitives.ReadUInt16LittleEndian(records.Span[pos..]);
        var kind = (TraceEventKind)records.Span[pos + 2];
        // dispatch to typed codec based on kind
        pos += size;
    }
}
reader.ReadSpanNames();  // optional trailing table

Constructors

TraceFileReader(Stream)

Wraps stream for reading a .typhon-trace file. Call ReadHeader() and the metadata-table readers, then iterate ReadNextBlock(out ReadOnlyMemory<byte>, out int) — see the type remarks for the full sequence. The reader takes ownership and disposes the stream in Dispose().

public TraceFileReader(Stream stream)

Parameters

stream Stream

Input stream positioned at the start of a .typhon-trace file.

Exceptions

ArgumentNullException

stream is null.

Fields

MinSupportedVersion

Oldest format version this reader still accepts. Bumped to 11 (2026-05-17) for the Track→DAG partitioning hierarchy (#354): the SystemDefinitionTable layout gained a trailing DagId field and the global PhasesTable was replaced by a TracksTable + DagsTable. That is a layout-breaking change — v10-and-older traces would mis-decode, so the reader hard-rejects them. Re-record against a v11 build.

public const ushort MinSupportedVersion = 11

Field Value

ushort

Properties

ArchetypeDefinitions

Rich archetype definitions (v7+), available after ReadArchetypeDefinitions().

public IReadOnlyList<ArchetypeDefinitionRecord> ArchetypeDefinitions { get; }

Property Value

IReadOnlyList<ArchetypeDefinitionRecord>

Archetypes

Archetype table, available after ReadArchetypes().

public IReadOnlyList<ArchetypeRecord> Archetypes { get; }

Property Value

IReadOnlyList<ArchetypeRecord>

ComponentDefinitions

Rich component-type definitions (v7+), available after ReadComponentDefinitions().

public IReadOnlyList<ComponentDefinitionRecord> ComponentDefinitions { get; }

Property Value

IReadOnlyList<ComponentDefinitionRecord>

ComponentTypes

Component type table, available after ReadComponentTypes().

public IReadOnlyList<ComponentTypeRecord> ComponentTypes { get; }

Property Value

IReadOnlyList<ComponentTypeRecord>

Dags

DAGs table (v11+, #354) — each DAG references its owning track by index and carries its own ordered phase names. Available after ReadDags().

public IReadOnlyList<DagRecord> Dags { get; }

Property Value

IReadOnlyList<DagRecord>

EventQueues

Event-queue catalog (v7+), available after ReadEventQueueCatalog().

public IReadOnlyList<EventQueueRecord> EventQueues { get; }

Property Value

IReadOnlyList<EventQueueRecord>

Header

File header, available after ReadHeader().

public TraceFileHeader Header { get; }

Property Value

TraceFileHeader

IndexCatalog

Flat index catalog (v7+), available after ReadIndexCatalog().

public IReadOnlyList<IndexCatalogEntry> IndexCatalog { get; }

Property Value

IReadOnlyList<IndexCatalogEntry>

ResourceGraphNodes

Resource-graph snapshot (v7+), available after ReadResourceGraphSnapshot().

public IReadOnlyList<ResourceGraphNodeRecord> ResourceGraphNodes { get; }

Property Value

IReadOnlyList<ResourceGraphNodeRecord>

RuntimeConfig

Runtime config snapshot (v7+), available after ReadRuntimeConfig(). Null when the on-disk presence flag was clear.

public RuntimeConfigRecord RuntimeConfig { get; }

Property Value

RuntimeConfigRecord

SpanNames

Span name intern table, available after ReadSpanNames().

public IReadOnlyDictionary<int, string> SpanNames { get; }

Property Value

IReadOnlyDictionary<int, string>

Systems

System definitions, available after ReadSystemDefinitions().

public IReadOnlyList<SystemDefinitionRecord> Systems { get; }

Property Value

IReadOnlyList<SystemDefinitionRecord>

Tracks

Tracks table (v11+, #354) — the top level of the runtime partitioning hierarchy. Available after ReadTracks().

public IReadOnlyList<TrackRecord> Tracks { get; }

Property Value

IReadOnlyList<TrackRecord>

Methods

Dispose()

Disposes the reader, returns any pooled block buffer to ArrayPool<T>, and closes the underlying stream. Idempotent.

public void Dispose()

ReadArchetypeDefinitions()

Reads the rich archetype-definitions table (v7+). Call after ReadComponentDefinitions().

public IReadOnlyList<ArchetypeDefinitionRecord> ReadArchetypeDefinitions()

Returns

IReadOnlyList<ArchetypeDefinitionRecord>

ReadArchetypes()

Reads the archetype table. Call after ReadSystemDefinitions().

public IReadOnlyList<ArchetypeRecord> ReadArchetypes()

Returns

IReadOnlyList<ArchetypeRecord>

ReadComponentDefinitions()

Reads the rich component-definitions table (v7+). Call after ReadDags().

public IReadOnlyList<ComponentDefinitionRecord> ReadComponentDefinitions()

Returns

IReadOnlyList<ComponentDefinitionRecord>

ReadComponentTypes()

Reads the component type table. Call after ReadArchetypes().

public IReadOnlyList<ComponentTypeRecord> ReadComponentTypes()

Returns

IReadOnlyList<ComponentTypeRecord>

ReadDags()

Reads the DAGs table (v11+, #354). Call after ReadTracks(), before ReadComponentDefinitions().

public IReadOnlyList<DagRecord> ReadDags()

Returns

IReadOnlyList<DagRecord>

ReadEventQueueCatalog()

Reads the event-queue catalog (v7+). Call after ReadRuntimeConfig().

public IReadOnlyList<EventQueueRecord> ReadEventQueueCatalog()

Returns

IReadOnlyList<EventQueueRecord>

ReadHeader()

Reads and validates the file header. Must be called first.

public TraceFileHeader ReadHeader()

Returns

TraceFileHeader

Exceptions

InvalidDataException

If magic or version is wrong.

ReadIndexCatalog()

Reads the flat index-catalog table (v7+). Call after ReadArchetypeDefinitions().

public IReadOnlyList<IndexCatalogEntry> ReadIndexCatalog()

Returns

IReadOnlyList<IndexCatalogEntry>

ReadNextBlock(out ReadOnlyMemory<byte>, out int)

Reads the next compressed block of raw records. Returns the decoded byte payload in records; caller walks it as a sequence of u16-size-prefixed records.

public bool ReadNextBlock(out ReadOnlyMemory<byte> records, out int recordCount)

Parameters

records ReadOnlyMemory<byte>

Receives the decoded block bytes. Empty on end-of-stream. The returned memory is rented from Shared and is valid only until the next call to ReadNextBlock(out ReadOnlyMemory<byte>, out int) or Dispose(). Do not stash the slice across iterations — the underlying buffer is returned to the pool on the next call and may be handed to another caller.

recordCount int

Number of records the block contains (from the block header).

Returns

bool

true if a block was read, false if end of stream.

ReadResourceGraphSnapshot()

Reads the resource-graph snapshot (v7+). Call after ReadEventQueueCatalog().

public IReadOnlyList<ResourceGraphNodeRecord> ReadResourceGraphSnapshot()

Returns

IReadOnlyList<ResourceGraphNodeRecord>

ReadRuntimeConfig()

Reads the runtime-config record (v7+). Call after ReadIndexCatalog(). Returns null when the on-disk presence flag was clear (host had no engine-level config to capture, e.g., standalone profiling).

public RuntimeConfigRecord ReadRuntimeConfig()

Returns

RuntimeConfigRecord

ReadSpanNames()

Reads the span name table if present at the current stream position. Returns the cumulative dictionary (merges with any previously-read span name table). Tolerates end-of-stream — if fewer than 4 bytes remain, the method returns the current dictionary unchanged instead of throwing, since the span name table is an optional trailing structure.

public IReadOnlyDictionary<int, string> ReadSpanNames()

Returns

IReadOnlyDictionary<int, string>

ReadStaticStructures()

Convenience helper that walks the six v7 static-structure tables in order. Equivalent to calling each Read... in sequence; matches the writer's WriteEmptyStaticStructures shape so tests can pair them. After the call, the data is available via ComponentDefinitions / ArchetypeDefinitions / etc.

public void ReadStaticStructures()

ReadSystemDefinitions()

Reads the system definition table. Call after ReadHeader().

public IReadOnlyList<SystemDefinitionRecord> ReadSystemDefinitions()

Returns

IReadOnlyList<SystemDefinitionRecord>

Remarks

v7+ — RFC 07 access declarations are always present (the v5/v6 partial-read paths were removed alongside the version bump in MinSupportedVersion).

ReadTracks()

Reads the tracks table (v11+, #354). Call after ReadComponentTypes(), before ReadDags().

public IReadOnlyList<TrackRecord> ReadTracks()

Returns

IReadOnlyList<TrackRecord>

TryReadCpuSampleSection(out CpuSampleRecord[], out ushort[][], out CpuFrameSymbol[])

Read the trailing CpuSampleSection (#351, v10+). Returns false if the trace file doesn't carry one (the header offset is zero — a v9-or-earlier trace, or a v10 trace captured without CPU sampling). Uses absolute seek; requires a seekable stream.

public bool TryReadCpuSampleSection(out CpuSampleRecord[] samples, out ushort[][] stacks, out CpuFrameSymbol[] frameSymbols)

Parameters

samples CpuSampleRecord[]

Output: CPU samples, sorted by qpc and grouped per thread slot; each references a stack by StackIndex.

stacks ushort[][]

Output: the interned stack table — each entry is a leaf-first array of frame ids into frameSymbols.

frameSymbols CpuFrameSymbol[]

Output: the interned frame symbols; FileId indexes the same FileTable the source-location manifest uses.

Returns

bool

TryReadFileTable(out string[])

Read the trailing FileTable (interned source-file paths) on its own. Unlike TryReadSourceLocationManifest(out string[], out SourceLocationManifestEntry[]) — which requires the SourceLocationManifest trailer to be present too — this reads the FileTable whenever FileTableOffset is non-zero. A trace can carry a populated FileTable (because CPU-sample frames resolved to source, #351) without any #302 call-site manifest, so the CPU-sample loader needs a manifest-independent way to map a CpuFrameSymbol.FileId back to a path. Returns false when no FileTable was written. Uses absolute seek; requires a seekable stream.

public bool TryReadFileTable(out string[] files)

Parameters

files string[]

Output: array of source-file paths indexed by FileId. Empty when the trace carries no FileTable.

Returns

bool

TryReadQuerySourceStringTable(out string[])

Read the trailing QuerySourceStringTable (#342, v9+). Returns false if the trace file doesn't carry one (offset in the header is zero — e.g., v8 trace, or v9 trace with no Query Definition Export activity). Uses absolute seek; requires a seekable stream.

public bool TryReadQuerySourceStringTable(out string[] strings)

Parameters

strings string[]

Output: array of source strings indexed by ID. Slot 0 is the sentinel ("no string") and is always empty/null. Caller uses these IDs to resolve DefinitionSourceFileId, ExecutionSourceFileId, etc. on Query Definition Export events.

Returns

bool

TryReadSourceLocationManifest(out string[], out SourceLocationManifestEntry[])

Read the trailing source-location manifest (#302, Phase 3 of profiler-source-attribution). Returns false if the trace file doesn't carry one (offsets in the header are zero). Uses absolute seeks; requires a seekable stream. See claude/design/Profiler/10-profiler-source-attribution.md §4.6.

public bool TryReadSourceLocationManifest(out string[] files, out SourceLocationManifestEntry[] entries)

Parameters

files string[]
entries SourceLocationManifestEntry[]

Returns

bool