Experiment 145: Inline stream flush dequeue

Date: 2026-06-08

Status: Rejected

Direction:stream-rerun-dispatch

Benchmark Run: None

Archive: Not created; the candidate was a two-method private cleanup, and

the snippets below are enough to recreate it if an allocation profile ever

names this path.

Problem

StreamEngine._flushQueue bounds stream re-query admission with

ReaderPool.availableWorkerCount, then builds a temporary list before it

dequeues entries:

 final dequeued = _requeryQueue.take(_pool.availableWorkerCount).toList(); 

ReaderPool.availableWorkerCount also used _workers.where(...).length.

Both are small Dart collection helpers on a stream fan-out path. Exp 120 and

exp 122 already fixed the correctness and dispatch-pressure shape of stream

admission, but the current implementation still had a tiny allocation-shaped

cleanup available.

Hypothesis

Replacing the helper chain with straight loops should remove avoidable

collection objects without changing stream ordering or public behavior:

Accept only if the focused stream profile shows a clear improvement or at

least a neutral result across the measured stream shapes. Reject if the result

is mixed, because exp 120/122 already drove dispatcherParkedTotal,

dispatcherWakeRetryTotal, and dispatcherMaxParkedConcurrent to zero.

Approach

The candidate patch changed only two private methods:

 int get availableWorkerCount { var count = 0; for (final worker in _workers) { if (worker.isAvailable) count++; } return count; } 
 var available = _pool.availableWorkerCount; while (available > 0 && _requeryQueue.isNotEmpty) { final entry = _requeryQueue.first; _requeryQueue.remove(entry); _requery(entry); available--; } 

The implementation was tested with the existing profile-mode stream admission

harness, then reverted after the result did not clear the acceptance bar. No

runtime code from this experiment is kept.

Results

Focused command:

 dart run -DRESQLITE_PROFILE=true benchmark/profile/stream_concrete_pool_profile.dart --label=<label> 

Full aggregate record:

Two-pass profile A/B:

workloadbaseline runs msbaseline median mscandidate runs mscandidate median msdelta
A11c baseline51.41, 80.5765.9955.22, 48.4051.81-21.5%
A11c disjoint56.21, 64.4760.3461.05, 58.6259.84-0.8%
A11c overlap116.18, 147.79131.99111.64, 125.62118.63-10.1%
keyed PK subscriptions25.06, 24.7924.9323.85, 32.0627.96+12.2%

Counter result:

workloadbaseline parked/retries/maxcandidate parked/retries/max
A11c baseline0 / 0 / 00 / 0 / 0
A11c disjoint0 / 0 / 00 / 0 / 0
A11c overlap0 / 0 / 00 / 0 / 0
keyed PK subscriptions0 / 0 / 00 / 0 / 0

The wall-time rows are mixed and noisy. A11c overlap trends better, but the

keyed-PK row moves the wrong way on the two-run median and the main dispatch

counters were already zero on baseline. That means the patch is not removing

the active stream bottleneck; at best it is a sub-signal allocation cleanup.

Decision

Rejected.

The code is mechanically correct, but it does not produce decision-quality

evidence under the current profile workload. Keeping it would add churn to a

stream-admission path that is already behaviorally settled by exp 120 and exp

122.

The important result is negative: do not spend another implementation pass on

_flushQueue collection-helper cleanup unless a future allocation profile

shows this exact temporary list or availability count as material.

Future Notes

Future stream-dispatch work still needs the signal requested by

signals.json: completion-side scheduling cost or writer-side dispatch wall.

This experiment does not change that route. It only closes the small

take(...).toList() cleanup as below current signal.