Skip to content

perf: skip stream pipeline for single-row reads and trim hot-path overhead#283

Merged
zantvoort merged 1 commit into
mainfrom
perf/hot-path-optimizations
Jul 17, 2026
Merged

perf: skip stream pipeline for single-row reads and trim hot-path overhead#283
zantvoort merged 1 commit into
mainfrom
perf/hot-path-optimizations

Conversation

@zantvoort

Copy link
Copy Markdown
Collaborator

Summary

A set of hot-path optimizations in storm-core. No behavior changes: exception types and messages on the single-row paths are identical to the previous stream-based defaults.

  • Single-row fast pathgetSingleResult()/getOptionalResult() now execute the statement, read at most two rows (the second only to enforce uniqueness), and close synchronously (QueryImpl.readSingleRow). This skips the stream pipeline construction, the leak-detection proxy, and the deferred close, none of which earn anything for a single-row read. QueryBuilder exposes overridable singleResultInternal/optionalResultInternal hooks; SelectBuilderImpl routes non-ref results through the new path and keeps ref results on the stream path.
  • RecordMapper trivial-plan fast path — when every step is a one-column pass-through and the flat args line up one-to-one with the constructor parameters, the row array is validated in place and reused directly instead of allocated and copied per row. The row reader allocates a fresh array per row, so no aliasing across rows.
  • SqlParser — the SQL operation is detected with regionMatches instead of evaluating a stream of DOTALL regexes on every parsed statement.
  • SqlInterceptorManager — a volatile counter (written under the write lock) lets intercept() skip acquiring the read lock entirely when no global operators are registered, the common production state.
  • TemplateMetricsAtomicLong counters replaced with LongAdder/LongAccumulator so concurrent template renders do not contend on a single CAS.
  • whereId/whereRef metamodel pinning — id- and ref-based predicates pin the root primary-key metamodel, so binding resolves the target column directly instead of re-deriving it from the value's runtime type on every execution. Models without a single primary-key path fall back to the previous derivation.
  • OrderableHelper — lists of zero or one element skip the graph construction and topological sort.

…rhead

- getSingleResult/getOptionalResult read at most two rows directly and
  close synchronously, skipping the stream pipeline, leak-detection
  proxy, and deferred close; exception types and messages are unchanged
- RecordMapper reuses the flat args array when every step is a
  one-column pass-through, avoiding a per-row allocation and copy
- SqlParser detects the SQL operation with regionMatches instead of
  evaluating a stream of regexes per statement
- SqlInterceptorManager skips the read lock when no global operators
  are registered
- TemplateMetrics stripes counters with LongAdder/LongAccumulator to
  avoid CAS contention
- whereId/whereRef pin the root primary-key metamodel so binding does
  not re-derive the target column from the value's runtime type
- OrderableHelper skips the topological sort for 0/1-element lists
@zantvoort
zantvoort merged commit e6034b2 into main Jul 17, 2026
7 of 8 checks passed
@zantvoort
zantvoort deleted the perf/hot-path-optimizations branch July 17, 2026 21:36
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