Class MemoryProfiler
- Namespace
- PopcorningGuineaPig.Engine.Diagnostics
- Assembly
- PopcorningGuineaPig.Engine.dll
Game-side, opt-in memory profiling API. Produces MemorySnapshot values that are bit-comparable with editor-side snapshots from Story 12.2, so the same diff tooling works against both editor and game captures.
public sealed class MemoryProfiler
- Inheritance
-
MemoryProfiler
- Inherited Members
Remarks
Lives in the engine assembly so a shipped game can opt in without referencing
the editor or ImGui. By design, the type is referenced lazily through
Default or constructor injection — if game code never touches
either, the trimmer (Story 12.1) strips MemoryProfiler and its sinks
from the published distributable.
Thread contract: Snapshot(string) reads IAssetRegistry dictionaries and process counters. Call only when the registry is not being mutated — i.e. between frames on the main thread, or from the periodic-sampling worker that StartPeriodicSampling(int, IMemorySink, CancellationToken) launches (the worker takes the same constraint).
Constructors
MemoryProfiler(IAssetRegistry, ILogger<MemoryProfiler>?)
Creates a new profiler bound to the supplied registry. Construct one of these
directly if your game does its own service composition; otherwise use
Default for a lazy singleton over Game.Instance.AssetRegistry.
public MemoryProfiler(IAssetRegistry assetRegistry, ILogger<MemoryProfiler>? logger = null)
Parameters
assetRegistryIAssetRegistryThe asset registry to introspect. Must not be null.
loggerILogger<MemoryProfiler>Optional logger for warnings (e.g. snapshot exceeded 50ms budget).
Properties
Default
Lazy singleton that resolves Instance's asset registry on
first access. Returns the same instance for every subsequent call. If game
code never touches this property (or new MemoryProfiler(...)) the
trimmer can strip the entire diagnostics surface.
public static MemoryProfiler Default { get; }
Property Value
Exceptions
- InvalidOperationException
Thrown if no
Game.Instanceis available when first accessed.
Methods
Snapshot(string)
Captures a point-in-time memory snapshot. Walks the asset registry and reads GC + process counters.
public MemorySnapshot Snapshot(string description)
Parameters
descriptionstringFree-form label stored on the snapshot (e.g. "after-level-load", "manual").
Returns
Remarks
Allocates ~1 KB per call. Bounded at < 50 ms on a project with ~1000 assets. Do NOT call from per-frame gameplay code — see StartPeriodicSampling(int, IMemorySink, CancellationToken) for the on-an-interval pattern.
StartPeriodicSampling(int, IMemorySink, CancellationToken)
Starts a background task that takes a snapshot every intervalMs
milliseconds and forwards it to sink. Cancellable via
StopPeriodicSampling() or the optional ct.
public Task StartPeriodicSampling(int intervalMs, IMemorySink sink, CancellationToken ct = default)
Parameters
intervalMsintMilliseconds between snapshots. Must be ≥ 10.
sinkIMemorySinkWhere to forward each snapshot.
ctCancellationTokenOptional external cancellation; combined with the internal one.
Returns
- Task
The worker task. Subscribe for completion or exceptions if you care.
Remarks
Snapshots run on a worker thread, not the game's main thread. The cost on the main thread is only the brief asset-registry reads (which the registry is contract-bound to permit between frames). Calling this a second time without first calling StopPeriodicSampling() replaces the previous sampling task.
StopPeriodicSampling()
Cancels any in-flight periodic sampling. Idempotent — safe to call when no sampling task is running.
public void StopPeriodicSampling()
WriteToFile(MemorySnapshot, string)
Convenience helper: serialize snapshot to JSON and write
it to path. Uses JsonOptions
so the on-disk format is stable across framework default changes.
public static void WriteToFile(MemorySnapshot snapshot, string path)
Parameters
snapshotMemorySnapshotpathstring