Transient
Heap-only component storage for scratch data that should never touch disk.
Status: โ Implemented ยท Visibility: Public ยท Level: ๐ต Core ยท Category: Ecs
๐ฏ What it solves
Some component data is genuinely throwaway between runs โ animation state, input buffers, pathfinding scratch,
targeting info. Paying any persistence cost (WAL, checkpoint, page-cache writeback) for data nobody needs to
survive a crash is pure overhead. Transient removes that cost entirely: the data lives only in process
memory, is structurally part of the same ECS entity as your durable components, and uses the same
Read<T>()/Write<T>() API as every other mode.
โ๏ธ How it works (in brief)
A Transient component's chunks live in pinned heap memory rather than the memory-mapped file โ there is no
WAL record, no checkpoint participation, and no dirty tracking; the JIT eliminates the dirty-tracking branches
entirely for this mode. Reads and writes are direct pointer arithmetic. On crash or restart, Transient
component segments come back empty โ the application is responsible for re-initializing any state it needs.
๐ป Usage
[Component("Game.AnimState", 1, StorageMode = StorageMode.Transient)]
public struct AnimState
{
public int ClipId;
public float Time;
}
[Archetype]
partial class Actor : Archetype<Actor>
{
public static readonly Comp<AnimState> Anim = Register<AnimState>();
}
using var tx = dbe.CreateQuickTransaction();
var id = tx.Spawn<Actor>(Actor.Anim.Set(new AnimState { ClipId = 3, Time = 0f }));
tx.Commit();
using var tx2 = dbe.CreateQuickTransaction();
var e = tx2.OpenMut(id);
ref var anim = ref e.Write(Actor.Anim);
anim.Time += dt; // ~40 ns write, no dirty tracking, no WAL
| Option | Default | Effect |
|---|---|---|
TransientOptions.MaxMemoryBytes |
256 MB | AllocateChunk throws once total Transient allocation across the engine exceeds the cap |
โ ๏ธ Guarantees & limits
- All data is lost on crash and on every restart โ there is no recovery path, by design.
- Write ~40 ns / read ~15 ns โ the cheapest mode in the engine (no dirty-tracking, no WAL), in the same class as raw Flecs/DOTS ECS array access.
- No locking, no torn-data protection, no isolation โ "developer owns concurrency" (same model as Unity DOTS/Flecs); two concurrent writes to the same component are undefined.
- An entity can mix
Transientcomponents withVersioned/SingleVersionones; on recovery only the non-Transientcomponents come back โ the application must re-initializeTransientstate for surviving entities. ComponentCollection<T>(variable-length) fields are supported onTransient.ReadsSnapshotis rejected forTransientcomponents โ there is no history to freeze to.
๐งช Tests
- StorageModeReadWriteTests โ
Transientspawn/read/write, no dirty-bitmap tracking, rollback frees chunks - ClusterTransientTests โ pure-
Transientcluster has no page-cache segment (heap-only), mixed SV+Transient bulk iteration
๐ Related
- Sibling: Entity Clusters โ
Transientcomponents live in a parallel heap-backed cluster segment with the same SoA layout - Sibling: SingleVersion (Tick-Fence Durable) โ same near-zero write cost, but durable to the last tick fence instead of never persisted
- Parent feature: Storage Modes