Record exp 159: Row.containsKey identity fast path (rejected)#154
Closed
danReynolds wants to merge 1 commit into
Closed
Record exp 159: Row.containsKey identity fast path (rejected)#154danReynolds wants to merge 1 commit into
danReynolds wants to merge 1 commit into
Conversation
Tested whether extending exp 158's RowSchema.indexOf identity scan to Row.containsKey produces a measurable win on row_map_facade. Three paired runs of the focused benchmark moved the containsKey row median 15.231 -> 14.707 ms (-3.4%) under the candidate, but the candidate range (12.377-15.101 ms) fully overlaps the baseline range (13.930-15.329 ms), so the change collapses to noise. HashMap<String, int>.containsKey is already very fast on canonical-string keys (Dart caches String.hashCode), so the identity-scan replacement saves only nanoseconds per call. The row.dart change has been reverted before merge; only the experiment writeup, README row, signals.json update, and regenerated docs/experiments/history.json land here. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Owner
Author
|
Heads-up: experiment number 159 is now taken on main — PR #153 (exp 159: writer request pipelining + persistent reply port) just merged with experiments/159-writer-pipelining.md and the matching signals.json/README rows. This record PR will need renumbering (next free looks like 161, since the open #155 claims 160) before merge to keep the monotonic-numbering convention and avoid clobbering history.json entries. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Hypothesis
Experiment 158 added a schema-name identity fast path to
RowSchema.indexOfand sawrow_map_facadehot-lookup drop 10.750 → 5.136 ms (-52%). It intentionally leftRow.containsKeyon the original_indexByName.containsKey(key)path; the containsKey row median moved 17.720 → 17.701 ms (neutral). Exp 159 tested whether routingRow.containsKeythrough the sameindexOffast path would produce a measurable win on the same benchmark, given the change is behavior-preserving and trivially small.Approach
One-line swap inside
Row.containsKey:Reuses the existing 32-column identity scan + private
HashMap<String, int>fallback established by exp 158 (RowSchema.indexOfunchanged). No public API changes, no transfer surface changes. A pre-run sanity check confirmedidentical("updated_at", schema.names[5]) == trueon the benchmark schema, so the identity fast path actually fires when measured.Results
Three paired runs of
dart run benchmark/experiments/row_map_facade.dart(8-column schema, 500,000 inner iterations per case):The candidate range fully overlaps the baseline range and the run-3 candidate (15.101 ms) is above the run-3 baseline (13.930 ms). The nominal -3.4% median delta is smaller than per-run variance on both sides.
Outcome
Rejected — below the noise floor on
row_map_facade.HashMap<String, int>.containsKeyis already very fast on canonical-string keys because Dart cachesString.hashCode, so the identity-scan replacement saves only nanoseconds per call. The candidate also adds a small theoretical downside on non-canonical keys (an up-to-32 element identity scan before the HashMap fallback).Would reopen if a workload appears where containsKey on canonical-and-present column names is a material fraction of wall time (e.g. a streaming consumer filtering rows by optional-column presence per emission). The runtime change has been reverted before merge; only the experiment writeup, README row, signals.json update, and regenerated
docs/experiments/history.jsonland here.This is not evidence against exp 158's
indexOffast path — that still stands. It only bounds the containsKey-side extension.Test plan
dart pub getin the worktreedart analyze lib/—No issues found!dart test test/database_test.dart— 49/49 pass (includesrow.containsKey('id')/row.containsKey('name')/row.containsKey('nonexistent')assertions on the candidate before revert)identical('updated_at', schema.names[5]) == truerow_map_facadeA/B: 3 baseline + 3 candidate runs (table above)dart run benchmark/finalize_experiment.dart --experiment=experiments/159-row-containskey-identity-fast-path.md🤖 Generated with Claude Code