Class TraceFileCacheReader
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
streamStreamSeekable stream positioned at the start of a
.typhon-trace-cachefile.
Exceptions
- ArgumentNullException
streamisnull.- ArgumentException
streamis 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
GlobalMetrics
Trace-wide aggregate metrics (the fixed header of the GlobalMetrics section), loaded eagerly at construction.
public ref readonly GlobalMetricsFixed GlobalMetrics { get; }
Property Value
Header
The cache file's header. Contains version, fingerprint, and section-table location.
public ref readonly CacheHeader Header { get; }
Property Value
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
PostTickSummaries
v12 per-tick post-tick markers. Empty for v11-or-older caches.
public IReadOnlyList<PostTickSummary> PostTickSummaries { get; }
Property Value
QueueIdToName
v12 queue-id → display-name map. Empty for v11-or-older caches.
public IReadOnlyDictionary<ushort, string> QueueIdToName { get; }
Property Value
QueueTickSummaries
v12 per-(tick, queue) rollup rows. Empty for v11-or-older caches.
public IReadOnlyList<QueueTickSummary> QueueTickSummaries { get; }
Property Value
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
SpanNames
Interned span-name id → name map. Empty when the source carried no span-name table.
public IReadOnlyDictionary<int, string> SpanNames { get; }
Property Value
SystemAggregates
Per-system trace-wide duration aggregates, loaded eagerly at construction. Empty when the section is absent.
public IReadOnlyList<SystemAggregateDuration> SystemAggregates { get; }
Property Value
SystemArchetypeTouches
v15 per-(tick, system, archetype) entity-touch rows. Empty for v14-or-older caches.
public IReadOnlyList<SystemArchetypeTouchSummary> SystemArchetypeTouches { get; }
Property Value
SystemTickSummaries
v12 per-(tick, system) rollup rows. Empty for v11-or-older caches.
public IReadOnlyList<SystemTickSummary> SystemTickSummaries { get; }
Property Value
TickIndex
Per-tick source-file index, loaded eagerly at construction.
public IReadOnlyList<TickIndexEntry> TickIndex { get; }
Property Value
TickSummaries
Per-tick overview rollups, loaded eagerly at construction. Drives the viewer's timeline.
public IReadOnlyList<TickSummary> TickSummaries { get; }
Property Value
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
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
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
entryChunkManifestEntryuncompressedDestinationSpan<byte>compressedScratchSpan<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
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
entryChunkManifestEntrycompressedDestinationSpan<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
expectedFingerprint32ReadOnlySpan<byte>