Table of Contents

Class ResourceOptions

Namespace
Typhon.Engine
Assembly
Typhon.Engine.dll

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

int

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

int

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

int

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

int

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

PageChecksumVerification

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

int

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.