Class TraceFileReader
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
streamStreamInput stream positioned at the start of a
.typhon-tracefile.
Exceptions
- ArgumentNullException
streamisnull.
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
Properties
ArchetypeDefinitions
Rich archetype definitions (v7+), available after ReadArchetypeDefinitions().
public IReadOnlyList<ArchetypeDefinitionRecord> ArchetypeDefinitions { get; }
Property Value
Archetypes
Archetype table, available after ReadArchetypes().
public IReadOnlyList<ArchetypeRecord> Archetypes { get; }
Property Value
ComponentDefinitions
Rich component-type definitions (v7+), available after ReadComponentDefinitions().
public IReadOnlyList<ComponentDefinitionRecord> ComponentDefinitions { get; }
Property Value
ComponentTypes
Component type table, available after ReadComponentTypes().
public IReadOnlyList<ComponentTypeRecord> ComponentTypes { get; }
Property Value
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
EventQueues
Event-queue catalog (v7+), available after ReadEventQueueCatalog().
public IReadOnlyList<EventQueueRecord> EventQueues { get; }
Property Value
Header
File header, available after ReadHeader().
public TraceFileHeader Header { get; }
Property Value
IndexCatalog
Flat index catalog (v7+), available after ReadIndexCatalog().
public IReadOnlyList<IndexCatalogEntry> IndexCatalog { get; }
Property Value
ResourceGraphNodes
Resource-graph snapshot (v7+), available after ReadResourceGraphSnapshot().
public IReadOnlyList<ResourceGraphNodeRecord> ResourceGraphNodes { get; }
Property Value
RuntimeConfig
Runtime config snapshot (v7+), available after ReadRuntimeConfig(). Null when the on-disk presence flag was clear.
public RuntimeConfigRecord RuntimeConfig { get; }
Property Value
SpanNames
Span name intern table, available after ReadSpanNames().
public IReadOnlyDictionary<int, string> SpanNames { get; }
Property Value
Systems
System definitions, available after ReadSystemDefinitions().
public IReadOnlyList<SystemDefinitionRecord> Systems { get; }
Property Value
Tracks
Tracks table (v11+, #354) — the top level of the runtime partitioning hierarchy. Available after ReadTracks().
public IReadOnlyList<TrackRecord> Tracks { get; }
Property Value
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
ReadArchetypes()
Reads the archetype table. Call after ReadSystemDefinitions().
public IReadOnlyList<ArchetypeRecord> ReadArchetypes()
Returns
ReadComponentDefinitions()
Reads the rich component-definitions table (v7+). Call after ReadDags().
public IReadOnlyList<ComponentDefinitionRecord> ReadComponentDefinitions()
Returns
ReadComponentTypes()
Reads the component type table. Call after ReadArchetypes().
public IReadOnlyList<ComponentTypeRecord> ReadComponentTypes()
Returns
ReadDags()
Reads the DAGs table (v11+, #354). Call after ReadTracks(), before ReadComponentDefinitions().
public IReadOnlyList<DagRecord> ReadDags()
Returns
ReadEventQueueCatalog()
Reads the event-queue catalog (v7+). Call after ReadRuntimeConfig().
public IReadOnlyList<EventQueueRecord> ReadEventQueueCatalog()
Returns
ReadHeader()
Reads and validates the file header. Must be called first.
public TraceFileHeader ReadHeader()
Returns
Exceptions
- InvalidDataException
If magic or version is wrong.
ReadIndexCatalog()
Reads the flat index-catalog table (v7+). Call after ReadArchetypeDefinitions().
public IReadOnlyList<IndexCatalogEntry> ReadIndexCatalog()
Returns
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
recordsReadOnlyMemory<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.
recordCountintNumber of records the block contains (from the block header).
Returns
- bool
trueif a block was read,falseif end of stream.
ReadResourceGraphSnapshot()
Reads the resource-graph snapshot (v7+). Call after ReadEventQueueCatalog().
public IReadOnlyList<ResourceGraphNodeRecord> ReadResourceGraphSnapshot()
Returns
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
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
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
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
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
samplesCpuSampleRecord[]Output: CPU samples, sorted by qpc and grouped per thread slot; each references a stack by
StackIndex.stacksushort[][]Output: the interned stack table — each entry is a leaf-first array of frame ids into
frameSymbols.frameSymbolsCpuFrameSymbol[]Output: the interned frame symbols;
FileIdindexes the sameFileTablethe source-location manifest uses.
Returns
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
filesstring[]Output: array of source-file paths indexed by
FileId. Empty when the trace carries no FileTable.
Returns
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
stringsstring[]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
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
filesstring[]entriesSourceLocationManifestEntry[]