perf(flush): an idle brain does no work — no periodic flush without a write
REPORTED from the field: a process holding many stores, with no writes for ten minutes, printed "All indexes flushed to disk in 216-601ms" per store every ~35 seconds and burned over a core at idle. Every one of those flushes re-persisted state identical to what was already on disk — the provider flushes, the watermark stamps, the generation counter, the entity-tree stamp — because flush() never asked whether anything had changed. - flush() over a clean brain is now O(1) and silent: a dirty witness is set by every committed write (both commit paths end at noteWriteForPersistence, and the deferred-embed worker lands through the single-op path) and cleared by a flush that runs. A write landing DURING a flush sets it again, so no write's work is ever skipped — it is done by the next flush. Set before the policy check, so a `'manual'` consumer's explicit flush is never a no-op it didn't ask for. - An explicit flush now tells the cadence it happened. It didn't, so the very next write saw "30s since the last flush" and kicked a background flush with nothing to do, and the idle timer fired two seconds later over writes the explicit flush had already persisted. - The graph adjacency index's auto-flush asks before it acts: two O(1) reads of the LSM MemTables, and a tick over a quiet index returns without calling into the trees at all. assessProviderHealth is NOT timer-driven — it is a synchronous O(1) read of a provider's own healthReport(), called on the read gate, so it costs nothing on an idle brain. No change needed there. Pins: tests/integration/idle-costs-nothing.test.ts — 90 idle seconds produce zero flushes, zero provider calls and zero log lines; three explicit flushes over a clean brain call no provider; one write earns exactly one flush.
This commit is contained in:
parent
3fffd9c6e6
commit
f5a6cb3f61
4 changed files with 208 additions and 0 deletions
|
|
@ -687,6 +687,17 @@ export class LSMTree {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @description Whether this tree holds anything a flush would write —
|
||||
* the MemTable is non-empty. Synchronous and O(1), so a background cadence
|
||||
* can ask before it does anything at all: the engine does no periodic work
|
||||
* without a cause.
|
||||
* @returns true when a flush would write; false when it would be a no-op.
|
||||
*/
|
||||
hasPendingWrites(): boolean {
|
||||
return !this.memTable.isEmpty()
|
||||
}
|
||||
|
||||
async close(): Promise<void> {
|
||||
this.stopCompactionTimer()
|
||||
|
||||
|
|
|
|||
Reference in a new issue