Skip to content

exp 168: reject Database resolved-runtime cache#164

Open
danReynolds wants to merge 1 commit into
mainfrom
exp-168-resolved-runtime-cache
Open

exp 168: reject Database resolved-runtime cache#164
danReynolds wants to merge 1 commit into
mainfrom
exp-168-resolved-runtime-cache

Conversation

@danReynolds

Copy link
Copy Markdown
Owner

Hypothesis

Exp 159 attacked fixed per-round-trip overhead inside Writer._request by
caching _sendPort and removing the await _workerPort.future microtask
hop. Every public Database method (select, selectBytes, execute,
executeBatch, transaction) still does final ... = await _runtime; at
the top — one microtask hop above the writer/reader call, on every Database
method call, because _runtime is already-resolved after open.

If exp 159's residual is really port-wake + event-loop scheduling, the
same pattern at the layer above should chip another hop off every call. At
~1-2 µs per hop the upper bound on sequential-awaited (2000 writes) is
~2-4 ms out of a ~32 ms median: theoretical ~6-12%, comfortably above the
focused-benchmark noise band exp 159 used to accept its win.

Approach

lib/src/database.dart:

  • New nullable field _DatabaseRuntime? _resolvedRuntime.
  • Inside the existing Future.sync(() async { ... }) body, after spawn
    awaits complete, assign the runtime record to _resolvedRuntime before
    return runtime.
  • Hot paths replace final ... = await _runtime; with
    final ... = _resolvedRuntime ?? await _runtime; at 5 call sites.
  • close and diagnostics keep await _runtime — cold.
  • stream keeps Stream.fromFuture(_runtime).asyncExpand(...) — one-shot
    per stream creation.

No public API change. No new measurement scaffolding.

Results

dart run benchmark/experiments/writer_pipelining.dart, two passes, 7
rounds each, order flipped between passes per the JOURNAL "phase-ordered
A/B" lesson.

pass shape baseline candidate delta
1 sequential-awaited (2000) 32.169 ms 31.425 ms −2.3%
1 concurrent-burst (10×200) 24.465 ms 25.818 ms +5.5%
1 transaction-guardrail (50×10) 4.587 ms 4.244 ms −7.5%
2 sequential-awaited (2000) 31.794 ms 32.603 ms +2.5%
2 concurrent-burst (10×200) 24.089 ms 25.138 ms +4.4%
2 transaction-guardrail (50×10) 4.093 ms 4.342 ms +6.1%

Sequential-awaited and transaction-guardrail flip sign between passes at
the same magnitude as round-to-round variance. Concurrent-burst trends
small-positive (regression) both passes but inside the per-round spread.

dart analyze lib: clean. dart test test/database_test.dart test/stream_test.dart: 75/75 pass.

Outcome

Rejected — below the focused-benchmark noise floor across two
order-flipped passes.
The theoretical 6–12% headroom did not show up in
measured wall time; deltas alternate sign between passes at the same
magnitude as single-phase variance. Same shape as the recent
overhead-removal rejection cluster (exp 145, exp 148, exp 151): once
per-call cost drops below ~2 µs the focused harness can't separate it
from machine jitter.

No runtime code kept. Exp 159's "further reduction needs request batching
across calls (group commit) or a different transport" framing remains the
correct steering for the sequential-write floor. Would reopen if a future
measurement system can resolve sub-1 µs per-call deltas on real
workloads.

Test plan

  • dart analyze lib — clean
  • dart test test/database_test.dart — 49/49 pass
  • dart test test/stream_test.dart test/stream_invalidation_coalescing_test.dart test/stream_cache_hit_reliability_test.dart — pass
  • dart test test/stream_dependency_shapes_test.dart test/stream_overflow_fallback_test.dart test/stream_trigger_cascade_test.dart — pass
  • dart run benchmark/finalize_experiment.dart --experiment=experiments/168-resolved-runtime-cache.md — green

🤖 Generated with Claude Code

Mirror exp 159's `_sendPort` cache one layer up: a sync-readable
`_resolvedRuntime` field on `Database` so post-open `select` /
`selectBytes` / `execute` / `executeBatch` / `transaction` skip the
`await _runtime` microtask hop.

Two order-flipped passes on writer_pipelining.dart produced
alternating-sign deltas inside per-round variance — sequential-awaited
-2.3% / +2.5%, transaction-guardrail -7.5% / +6.1%, concurrent-burst
+4-5% both passes — so the ~1-2 us per-call hop sits at or below the
focused-harness floor.

No runtime code kept. Database-layer microtask hop trimming above the
writer no longer moves exp 159's sequential-write residual floor; the
next reduction candidate must reduce round-trip count (group commit)
or change transport, not chase hops.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant