perf: coalesce auto-save serialization while a write is in flight - #90
perf: coalesce auto-save serialization while a write is in flight#90imurashka wants to merge 4 commits into
Conversation
While the previous snapshot is still on its way to the disk, a change no longer serializes the whole storage: it only marks the storage as changed. The background writer asks the storage to serialize once more when it becomes free, through the SynchronizationContext captured at build time.
…orage Look up a registered section through a type-to-index dictionary instead of scanning the section list twice with two different comparisons. Share the type-mismatch decision between Set and SetRaw, and keep reactive collection tracking in one pair of methods instead of five copies. Hand the deferred-save callback to the writer at construction so it stops travelling through a settable property on three types, and move the test-only AddRange helpers out of the runtime assembly.
ReactiveList, ReactiveSet and ReactiveDictionary each carried their own copy of the dispose flag, the OnChanged event, SetDirty and ThrowIfDisposed. Move that contract into ReactiveCollection so a change to it lands in one place. Build the nested storage key list in a single pass instead of a LINQ chain, and reuse the prefix check that RemoveAll already needed.
MarkChanged, DecreaseCounter and SaveDeferredChanges each carried their own copy of the "auto-save is on, no change scope is open, there is something to save" condition. Route the other two through MarkChanged so the policy lives in one method. Give the nested storage key list its capacity up front and reuse a cached prefix predicate, post the deferred-save callback through a static callback instead of a closure, and share one storage-opening helper across the persistence fixtures.
|
Closing without merging. Coalescing was built on the assumption that a burst of auto-saved changes leaves a pile of pooled buffers behind. It does not: below the 1 MB ceiling of That leaves the mechanism paying for itself with a The background writer (#89) is unaffected and stays on main. The refactoring commits from this branch are rebased on main without the coalescing machinery in #91. |
Auto-save no longer serializes the whole storage on every change. While the previous snapshot is still on its way to the disk, a change only marks the storage as changed; the background writer asks the storage to serialize once more when it becomes free, through the
SynchronizationContextcaptured when the storage was built.A burst of 200
Setcalls now costs one serialization instead of 200. Measured in the editor on Windows: 54 keys 2.05 ms -> 0.02 ms, 1 710 keys 49.22 ms -> 0.01 ms, 16 200 keys 457.88 ms -> 0.01 ms. Serialization still happens on the thread that owns the storage, so nothing new is read from another thread. A storage built without aSynchronizationContextkeeps serializing on every change, exactly as before.