Skip to content

Read the versioners' version options off instance variables - #2923

Closed
ericproulx wants to merge 1 commit into
masterfrom
perf/versioner-options-ivars
Closed

ericproulx wants to merge 1 commit into
masterfrom
perf/versioner-options-ivars

Conversation

@ericproulx

Copy link
Copy Markdown
Contributor

Summary

Versioner::Base delegated cascade, parameter, strict and vendor through version_options into config, so each read went two Forwardable frames and two Data readers deep (about 150 ns) for a value fixed when the middleware was built. The header versioner reads vendor and strict on every request, the accept-version one strict, and the param one parameter twice.

They are now plain readers over instance variables set in #initialize, the pattern the formatter's options already use. The public readers keep their names.

Benchmarks

Median of 7 interleaved subprocess rounds against master, Ruby 4.0.6, no JIT:

request delta
header-versioned +3.4%
accept-version +1.7%
param-versioned +2.8%
path-versioned (control, reads none of them) −0.7% (noise)

The path versioner carries the four extra variables on its per-request dup, but stays in the same 160-byte object slot (15 of its 18 embedded slots).

Test plan

  • Full RSpec suite passes locally.
  • RuboCop clean.
  • Mutation-checked through existing specs: forcing strict to false, vendor to nil, a wrong parameter or an inverted cascade fails 10, 36, 18 and 34 specs respectively.
  • CI green.

🤖 Generated with Claude Code

`vendor`, `strict`, `parameter` and `cascade` were delegated through
`version_options` into `config`, so each read went two Forwardable frames
and two Data readers deep, about 150 ns, for a value fixed when the
middleware was built. The header versioner reads `vendor` and `strict` on
every request, the accept-version one `strict`, and the param one
`parameter` twice.

They are now plain readers over instance variables set in `#initialize`,
the pattern the formatter adopted for its own options. The extra
variables ride along on the per-request `dup`; the path versioner, which
reads none of them, stays in the same object slot.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@ericproulx
ericproulx force-pushed the perf/versioner-options-ivars branch from 502cbad to 58ef5dd Compare September 10, 2026 19:18
@github-actions

github-actions Bot commented Sep 10, 2026

Copy link
Copy Markdown

Danger Report

No issues found.

View run

@ericproulx

Copy link
Copy Markdown
Contributor Author

Closing in favour of #2936, which combines #2922#2934 into one PR, re-benchmarked as a whole against master. The write-up here (behaviour matrix, mutation results) still describes this part of the change.

@ericproulx ericproulx closed this Sep 11, 2026
@ericproulx
ericproulx deleted the perf/versioner-options-ivars branch September 15, 2026 21:49
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