Class ResourceOptions
Runtime knobs for the database engine's resource subsystems (transaction chain, WAL ring buffer, checkpoint cadence, page-CRC policy). Set at startup via Resources, immutable thereafter.
public class ResourceOptions
- Inheritance
-
ResourceOptions
- Inherited Members
Remarks
Every property here is wired — it drives real engine behavior and is range-validated at DI resolution by
DatabaseEngineOptionsValidator. (A prior aspirational memory-budget surface — page-cache pages, WAL segment
sizing, a shadow-buffer budget and a never-called Validate() — was removed in #148 as vestigial: it governed no
allocations. The real cache size lives on DatabaseCacheSize; real WAL segment sizing on
WalWriterOptions.)
Constructors
ResourceOptions()
public ResourceOptions()
Properties
CheckpointBarrierTimeoutMs
Bounded budget (milliseconds) for the checkpoint cycle's WAL durability barrier waits (CK-02). On timeout the cycle raises a transient WalBackPressureTimeoutException, which the failure classification (CK-06) treats as Degraded + retry-next-cycle — never a permanent stall.
public int CheckpointBarrierTimeoutMs { get; set; }
Property Value
CheckpointDirtyPageThresholdPercent
Run a checkpoint as soon as this percentage of the page cache owes a writeback, without waiting for
CheckpointIntervalMs. 0 disables the trigger, leaving the timer and explicit forces as the
only causes — which is the pre-#830 behaviour.
public int CheckpointDirtyPageThresholdPercent { get; set; }
Property Value
Remarks
A page cannot be evicted until a checkpoint has written it (PS-10), so the cache's reclaim rate IS the checkpoint
rate and the peak writeback debt is "everything dirtied inside one interval". On a workload that dirties more
than the cache holds in CheckpointIntervalMs, the cache saturates and the next page allocation has
nothing to evict — the engine dies on PageCacheBackpressureTimeout with a cache that is ~100 % dirty.
Measured on the SpaceBattle demo (256 MiB cache, ~25 000 entities at 60 Hz): the 30 s default died at ~58 000
ticks with 32 758 of 32 768 pages owed, while a 1 s cadence ran to 104 506 ticks with debt never above 15 %.
The default of 25 % leaves three quarters of the cache as headroom for the cycle to complete while it runs. The clock cannot serve this purpose: the safe interval is a function of cache size and write rate, and nothing in the engine derives one from the other — the user only finds out they configured it wrong when the engine stops.
Raising the frequency is not the trade against throughput it looks like. On the measurement above the simulation got faster (14–28 ms per tick → 9–15 ms) and the WAL stopped sawtoothing to 6 GB, because back-pressure stalls and giant flush bursts both disappeared. Caveat: that is one workload on one machine.
CheckpointIntervalMs
Checkpoint interval when idle (milliseconds).
public int CheckpointIntervalMs { get; set; }
Property Value
Remarks
This is a durability knob — it bounds how much WAL a crash has to replay. It is deliberately NOT the knob that keeps the page cache alive; that is CheckpointDirtyPageThresholdPercent, because cache survival depends on how fast pages are dirtied, not on the clock.
MaxActiveTransactions
Maximum concurrent active transactions. Beyond this, CreateTransaction throws ResourceExhaustedException.
public int MaxActiveTransactions { get; set; }
Property Value
PageChecksumVerification
Controls when page CRC verification occurs. OnLoad verifies on every page load (higher safety, slight overhead). RecoveryOnly only during crash recovery (lower overhead).
public PageChecksumVerification PageChecksumVerification { get; set; }
Property Value
WalRingBufferSizeBytes
Size of the WAL ring buffer in bytes. When full, commit threads block until the WAL writer drains it.
public int WalRingBufferSizeBytes { get; set; }
Property Value
Remarks
This is the total pinned allocation: WalCommitBuffer ping-pongs two halves of
WalRingBufferSizeBytes / 2 each, so the default reserves 64 MB up front and each half is 32 MB. Lower it for
memory-constrained or low-write deployments — the engine is correct at any size, it just swaps buffers more often.
The default is sized for tail latency, not throughput. Measured on a 20 001-entity cluster archetype at 120 Hz (#559): the median tick is flat across 8/16/32/64 MB at ~17.6 ms, but the worst tick falls from ~29 ms to ~18 ms at 64 MB. A ring that fills makes producers block on the buffer swap, which shows up as an occasional tick blowing several times its budget — the failure mode a real-time engine cares about most.