Skip to content

perf: Skip redundant __init__ assignments and remove dead attributes in ResponseFuture (-32ns/call - 4.7% improvement for the common case, +43ns (+4.5%) for the non-common case, - code cleanup also)#806

Draft
mykaul wants to merge 2 commits intoscylladb:masterfrom
mykaul:perf/response-future-init-cleanup

Conversation

@mykaul
Copy link
Copy Markdown

@mykaul mykaul commented Apr 7, 2026

Summary

  • Remove 3 dead class attributes from ResponseFuture:
    • default_timeout — belongs to Session, never used in RF
    • _profile_manager — belongs to Session, never used in RF
    • _warned_timeout — never read or written anywhere in the codebase
  • Skip 4 redundant STORE_ATTR operations in __init__ when parameters are None (matching the class-level default): _metrics, prepared_statement, _host, _continuous_paging_state
  • Move prepared_statement and _continuous_paging_state class defaults (previously only set in __init__) to class level so the conditional skip works correctly

Thread Safety

All skipped attributes have class-level None defaults and are only set during __init__ or by the owning thread after construction. No lazy initialization of shared mutable state is introduced — the thread-safety invariants are preserved.

Benchmark

ResponseFuture.__init__ micro-benchmark, min() of 7 × 200k iterations:

Scenario Before After Δ
Common case (all 4 params = None) 670 ns/call 638 ns/call -32 ns/call (4.7%)
Non-None case (metrics + prepared_statement + host set) 957 ns/call 1001 ns/call +43 ns/call (+4.5%)

The common case (simple queries without metrics/prepared statements/host pinning) is the dominant path. The non-None case overhead is from the added if checks, but these params are rarely all non-None simultaneously.

Tests

All 645 unit tests pass (43 skipped), matching the origin/master baseline.

…in ResponseFuture

- Remove 3 dead class attributes (default_timeout, _profile_manager,
  _warned_timeout) that were never read or written on ResponseFuture
- Add prepared_statement and _continuous_paging_state as class-level
  defaults (both None), skip __init__ assignment when parameter is None
- Conditionalize _metrics and _host assignments: only set when non-None
- Saves 4 STORE_ATTR operations per query on the common path (simple
  statements, no metrics, no host targeting, no continuous paging)
@mykaul mykaul changed the title perf: Skip redundant __init__ assignments and remove dead attributes in ResponseFuture perf: Skip redundant __init__ assignments and remove dead attributes in ResponseFuture (-32ns/call - 4.7% improvement for the common case, +43ns (+4.5%) for the non-common case, - code cleanup also) Apr 7, 2026
…te_response_future

For prepared-statement workloads (the perf-critical case), BoundStatement
is the most common query type reaching _create_response_future. Checking
it before SimpleStatement saves one wasted isinstance() call per dispatch.

Benchmark (80% BoundStatement, 15% SimpleStatement, 5% other):
  SimpleStatement first: 32.8 ns/dispatch
  BoundStatement first:  23.2 ns/dispatch
  Speedup: ~1.4-1.7x (~10-15 ns/dispatch saved)
@mykaul
Copy link
Copy Markdown
Author

mykaul commented Apr 10, 2026

Follow-up commit: reorder isinstance chain in _create_response_future

Commit: 40f45ecf5perf: reorder isinstance chain to check BoundStatement first in _create_response_future

Change

Swapped the isinstance check order so BoundStatement is checked before SimpleStatement in the _create_response_future dispatch chain. For prepared-statement workloads (the perf-critical case), this saves one wasted isinstance() call per dispatch.

BoundStatement and SimpleStatement are sibling classes under Statement — no subclass relationship — so reorder is safe with no behavioral change.

Benchmark results (benchmarks/bench_isinstance_dispatch.py)

Simulated workload mix: 80% BoundStatement, 15% SimpleStatement, 5% other:

Python 3.14.3
SimpleStatement first: 32.8 ns/dispatch
BoundStatement first:  23.2 ns/dispatch
Speedup: ~1.4–1.7x (~10–15 ns/dispatch saved)

Tests

607 unit tests passed, 0 failures.

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