Skip to content

Annotate Symbol#empty? as leaf#17464

Merged
tekknolagi merged 1 commit into
ruby:masterfrom
sampokuokkanen:symbol-empty-ruby
Jul 2, 2026
Merged

Annotate Symbol#empty? as leaf#17464
tekknolagi merged 1 commit into
ruby:masterfrom
sampokuokkanen:symbol-empty-ruby

Conversation

@sampokuokkanen

@sampokuokkanen sampokuokkanen commented Jun 24, 2026

Copy link
Copy Markdown
Contributor

Move Symbol#empty? from the C sym_empty into symbol.rb, implemented as RBOOL(RSTRING_LEN(rb_sym2str(self)) == 0), mirroring the existing Symbol#to_s and #name leaf builtins.

Also added an annotate_builtin! in zjit/src/cruby_methods.rs to tell ZJIT that the method does not need GC now.

Symbol#empty? as a leaf builtin, via benchmark-driver (GC.disable, loop_count: 20_000_000, Apple M1). Speedup vs master (CFUNC sym_empty):

benchmark interpreter --yjit --zjit
:"".empty? 1.24x 1.30x 1.19x
:abcdefgh.empty? 1.19x 1.19x 1.17x

Windows native and WSL2 also get faster:

benchmark interpreter
:"".empty? 1.47x
:abcdefgh.empty? 1.36x

WSL2 (Ubuntu) x86_64-linux

benchmark interpreter --yjit --zjit
:"".empty? 1.39x 1.33x 1.32x
:abcdefgh.empty? 1.37x 1.39x 1.33x

@matzbot matzbot requested a review from a team June 24, 2026 12:39
Comment thread symbol.rb
@tekknolagi

Copy link
Copy Markdown
Contributor

FWIW we can do better in ZJIT. Modified your script to print slightly differently.

plum% ../build-rel-stats/miniruby tmp/symempty.rb  # your commit
best time for 400000 iterations: 0.007s (57.0M/s)
plum% ../build-rel-stats/miniruby --zjit tmp/symempty.rb  # your commit
best time for 400000 iterations: 0.002s (188.8M/s)
plum% ../build-rel-stats/miniruby --zjit tmp/symempty.rb  # teach HIR how to inline it
best time for 400000 iterations: 0.001s (604.2M/s)
plum%

Can be done in a follow-up PR in a couple lines :)

@k0kubun k0kubun changed the title Rewrite Symbol#empty? in Ruby Annotate Symbol#empty? as leaf Jun 25, 2026
@k0kubun

k0kubun commented Jun 25, 2026

Copy link
Copy Markdown
Member

Can you name these PRs "Annotate XXX as leaf" going forward? "Rewrite in Ruby" is a misleading subject for this change. Until you stop using Primitive.cexpr!, the implementation is still written in C. We do this in Ruby source files only because this is the only way we can annotate C code in CRuby, and we don't call it a rewrite in Ruby.

Move Symbol#empty? from the C sym_empty into symbol.rb, implemented as `RBOOL(RSTRING_LEN(rb_sym2str(self)) == 0)`, mirroring the existing Symbol#to_s and #name leaf builtins.
@sampokuokkanen

Copy link
Copy Markdown
Contributor Author

@k0kubun
Thanks and sorry about that, I will do that from now on. I updated the git commit summary to match.

@XrXr @tekknolagi
Thanks for looking into this! So the consensus is to keep this PR as is, then later add something like static VALUE empty_symbol;? To make the comparison just RBOOL(self == empty_symbol).

@tekknolagi Interested to know what kind of a trick you used to get that kind of performance! 😁

@sampokuokkanen sampokuokkanen requested review from XrXr and tekknolagi July 2, 2026 02:28
@tekknolagi tekknolagi enabled auto-merge (squash) July 2, 2026 04:09
@tekknolagi tekknolagi merged commit 439c06b into ruby:master Jul 2, 2026
131 of 133 checks passed
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.

4 participants