Table of Contents

Class TraceFileCacheReader

Namespace
Typhon.Profiler
Assembly
Typhon.Profiler.dll

Opens and reads a .typhon-trace-cache sidecar file. Small sections (TickIndex, TickSummaries, ChunkManifest, GlobalMetrics, SpanNames) are loaded eagerly on construction — they're capped at tens of MB even for 500K-tick traces, and the server/client need random access to them anyway. The bulk FoldedChunkData section stays on disk; callers read chunks on demand via ReadChunkRaw(in ChunkManifestEntry, Span<byte>) or DecompressChunk(in ChunkManifestEntry, Span<byte>, Span<byte>).

public sealed class TraceFileCacheReader : IDisposable
Inheritance
TraceFileCacheReader
Implements
Inherited Members

Remarks

Construction validates the magic, version, and section-table consistency. Fingerprint verification against the source is a separate concern (see VerifyFingerprint(ReadOnlySpan<byte>) and ComputeSourceFingerprint(string, Span<byte>)) — the reader does NOT open the source file itself.

Constructors

TraceFileCacheReader(Stream)

Opens a cache reader over stream, validating the magic, cache version, and chunker version, then eagerly loading the small sections. The stream must be seekable; the reader takes ownership and disposes it in Dispose().

public TraceFileCacheReader(Stream stream)

Parameters

stream Stream

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

Exceptions

ArgumentNullException

stream is null.

ArgumentException

stream is not seekable.

InvalidDataException

The magic, cache version, or chunker version does not match this reader.

Properties

ChunkManifest

Chunk manifest addressing folded chunk payloads in the cache file, loaded eagerly at construction.

public IReadOnlyList<ChunkManifestEntry> ChunkManifest { get; }

Property Value

IReadOnlyList<ChunkManifestEntry>

GlobalMetrics

Trace-wide aggregate metrics (the fixed header of the GlobalMetrics section), loaded eagerly at construction.

public ref readonly GlobalMetricsFixed GlobalMetrics { get; }

Property Value

GlobalMetricsFixed

Header

The cache file's header. Contains version, fingerprint, and section-table location.

public ref readonly CacheHeader Header { get; }

Property Value

CacheHeader

IsSelfContained

True when IsSelfContained is set in the header. A self-contained cache carries the source metadata tables (header / systems / archetypes / component types) inside its SourceMetadata section, so the loader does not need to read a sibling .typhon-trace file.

public bool IsSelfContained { get; }

Property Value

bool

PostTickSummaries

v12 per-tick post-tick markers. Empty for v11-or-older caches.

public IReadOnlyList<PostTickSummary> PostTickSummaries { get; }

Property Value

IReadOnlyList<PostTickSummary>

QueueIdToName

v12 queue-id → display-name map. Empty for v11-or-older caches.

public IReadOnlyDictionary<ushort, string> QueueIdToName { get; }

Property Value

IReadOnlyDictionary<ushort, string>

QueueTickSummaries

v12 per-(tick, queue) rollup rows. Empty for v11-or-older caches.

public IReadOnlyList<QueueTickSummary> QueueTickSummaries { get; }

Property Value

IReadOnlyList<QueueTickSummary>

SourceMetadataBytes

Verbatim bytes of the embedded source metadata: TraceFileHeader + system definitions table + archetypes table + component types table, in the same wire format the engine produces. Empty span when the cache has no SourceMetadata section (i.e., not self-contained). Callers project header / tables by feeding these bytes through a TraceFileReader over a MemoryStream.

public ReadOnlySpan<byte> SourceMetadataBytes { get; }

Property Value

ReadOnlySpan<byte>

SpanNames

Interned span-name id → name map. Empty when the source carried no span-name table.

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

Property Value

IReadOnlyDictionary<int, string>

SystemAggregates

Per-system trace-wide duration aggregates, loaded eagerly at construction. Empty when the section is absent.

public IReadOnlyList<SystemAggregateDuration> SystemAggregates { get; }

Property Value

IReadOnlyList<SystemAggregateDuration>

SystemArchetypeTouches

v15 per-(tick, system, archetype) entity-touch rows. Empty for v14-or-older caches.

public IReadOnlyList<SystemArchetypeTouchSummary> SystemArchetypeTouches { get; }

Property Value

IReadOnlyList<SystemArchetypeTouchSummary>

SystemTickSummaries

v12 per-(tick, system) rollup rows. Empty for v11-or-older caches.

public IReadOnlyList<SystemTickSummary> SystemTickSummaries { get; }

Property Value

IReadOnlyList<SystemTickSummary>

TickIndex

Per-tick source-file index, loaded eagerly at construction.

public IReadOnlyList<TickIndexEntry> TickIndex { get; }

Property Value

IReadOnlyList<TickIndexEntry>

TickSummaries

Per-tick overview rollups, loaded eagerly at construction. Drives the viewer's timeline.

public IReadOnlyList<TickSummary> TickSummaries { get; }

Property Value

IReadOnlyList<TickSummary>

Methods

ComputeSourceFingerprint(string, Span<byte>)

Compute the 32-byte source-file fingerprint: SHA-256 of source mtime-ticks + length + first 4 KB + last 4 KB. Cheap (~1 ms) and collision-resistant enough to detect any meaningful mutation.

public static void ComputeSourceFingerprint(string sourcePath, Span<byte> destination32)

Parameters

sourcePath string
destination32 Span<byte>

CopySourceFingerprint(Span<byte>)

Copies the 32-byte source fingerprint into destination. For source-derived caches the bytes are a SHA-256 hash of the source file; for self-contained caches (IsSelfContained) they are an arbitrary session-derived identifier and must not be treated as a hash.

public void CopySourceFingerprint(Span<byte> destination)

Parameters

destination Span<byte>

DecompressChunk(in ChunkManifestEntry, Span<byte>, Span<byte>)

Read and LZ4-decompress a chunk into uncompressedDestination. compressedScratch is a caller-supplied scratch buffer for the compressed read (callers pool these across many chunks). Both buffers must be sized ≥ the entry's respective lengths.

public void DecompressChunk(in ChunkManifestEntry entry, Span<byte> uncompressedDestination, Span<byte> compressedScratch)

Parameters

entry ChunkManifestEntry
uncompressedDestination Span<byte>
compressedScratch Span<byte>

Dispose()

Disposes the reader and closes the underlying stream. Idempotent.

public void Dispose()

GetSourceFingerprintHex()

Returns SourceFingerprint as a 64-char uppercase hex string. Useful for IDs that need to cross a process boundary (e.g., /api/trace/open responses: the client uses this string as an invalidation key for its OPFS chunk cache — source file changes produce a different fingerprint, old cached chunks become unreachable).

public string GetSourceFingerprintHex()

Returns

string

ReadChunkRaw(in ChunkManifestEntry, Span<byte>)

Read a chunk's compressed bytes into compressedDestination. The destination must be at least entry.CacheByteLength bytes long. No decompression happens here.

public void ReadChunkRaw(in ChunkManifestEntry entry, Span<byte> compressedDestination)

Parameters

entry ChunkManifestEntry
compressedDestination Span<byte>

VerifyFingerprint(ReadOnlySpan<byte>)

Verify the cache's header fingerprint against a freshly-computed fingerprint for the source file. Returns true if they match (cache is still valid for this source).

public bool VerifyFingerprint(ReadOnlySpan<byte> expectedFingerprint32)

Parameters

expectedFingerprint32 ReadOnlySpan<byte>

Returns

bool