Skip to content

perf(stable-api): inline encoding_get for MRI stable versions#730

Merged
ianks merged 1 commit into
mainfrom
perf/stable-api-encoding-get-fast-path
Apr 20, 2026
Merged

perf(stable-api): inline encoding_get for MRI stable versions#730
ianks merged 1 commit into
mainfrom
perf/stable-api-encoding-get-fast-path

Conversation

@ianks

@ianks ianks commented Apr 20, 2026

Copy link
Copy Markdown
Collaborator

Summary

Follow-up to #681. The initial implementation of encoding_get delegates to the exported rb_enc_get_index function on all calls — but for the vast majority of objects (any encoding with index < 0x7f, which covers ASCII, UTF-8, US-ASCII, and all commonly used encodings), the encoding index is stored inline in RBasic.flags and can be read with no function call.

This PR restores the fast path: read the index directly from flags, and only fall back to rb_enc_get_index when the inline slot reads as RUBY_ENCODING_INLINE_MAX (0x7f), which is the sentinel that CRuby uses to signal "look at the ivar instead."

Semantics are unchanged — parity-tested against the compiled C shim.

Changes

  • crates/rb-sys/src/stable_api/ruby_{2_7,3_0,3_1,3_2,3_3,3_4,4_0}.rs — inline flag read + sentinel fallback.
  • No changes to compiled.c/compiled.rs: C side already uses ENCODING_GET macro when defined, and TruffleRuby keeps its rb_enc_get_index fallback (no RBasic.flags exposed).

Test plan

  • Parity tests pass locally (test_encoding_get_ascii_string, test_encoding_get_utf8_string)
  • CI green across all Ruby versions + TruffleRuby

🤖 Generated with Claude Code

Avoid the dylib call to rb_enc_get_index for the common case by reading
the encoding index directly from RBasic.flags. The inline index is
stored in bits RUBY_ENCODING_SHIFT..+7 (= FL_USHIFT+10..+17). Only when
the inline slot equals RUBY_ENCODING_INLINE_MAX (0x7f) — meaning the
real index is stored out-of-line via an ivar — do we fall back to
rb_enc_get_index. Matches CRuby's ENCODING_GET inline function
semantics exactly. Tested parity with compiled C shim on ASCII/UTF-8.

The C shim (compiled.c) and TruffleRuby's compiled-only path are
unchanged — both continue to use ENCODING_GET macro or rb_enc_get_index
respectively, since TruffleRuby's RBasic does not expose flags.
@ianks ianks merged commit d03ff5c into main Apr 20, 2026
57 checks passed
@ianks ianks deleted the perf/stable-api-encoding-get-fast-path branch April 20, 2026 14:46
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