Skip to content

Optimize ripper translator - #3862

Merged
eregon merged 1 commit into
ruby:mainfrom
Earlopain:optimize-ripper
Jan 19, 2026
Merged

Optimize ripper translator#3862
eregon merged 1 commit into
ruby:mainfrom
Earlopain:optimize-ripper

Conversation

@Earlopain

Copy link
Copy Markdown
Collaborator

Ref #3859 (comment). I was interested in how big the impact is and turns out it is a lot.

Creating state classes is pretty expensive. Since they are not modifiable, we can reuse them instead.

Benchmark script:

require"ripper"require"prism"require"benchmark/ips"codes=Dir["**/*.rb"].map{File.read(it)}Benchmark.ipsdo |x|
x.config(time: 10)x.report("prism"){codes.each{Prism::Translation::Ripper.lex(it)}}x.report("ripper"){codes.each{Ripper.lex(it)}}x.compare!end

Before:

ruby 4.0.0 (2025-12-25 revision 553f1675f3) +PRISM [x86_64-linux]
Warming up --------------------------------------
prism 1.000 i/100ms
ripper 1.000 i/100ms
Calculating -------------------------------------
prism 0.293 (± 0.0%) i/s (3.42 s/i) - 3.000 in 10.248348s
ripper 0.633 (± 0.0%) i/s (1.58 s/i) - 7.000 in 11.055687s
Comparison:
ripper: 0.6 i/s
prism: 0.3 i/s - 2.16x slower

After

ruby 4.0.0 (2025-12-25 revision 553f1675f3) +PRISM [x86_64-linux]
Warming up --------------------------------------
prism 1.000 i/100ms
ripper 1.000 i/100ms
Calculating -------------------------------------
prism 0.486 (± 0.0%) i/s (2.06 s/i) - 5.000 in 10.280413s
ripper 0.635 (± 0.0%) i/s (1.58 s/i) - 7.000 in 11.027169s
Comparison:
ripper: 0.6 i/s
prism: 0.5 i/s - 1.31x slower

@eregoneregon left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice, thank you, it seems my performance guess was good then :)

Comment threadlib/prism/translation/ripper/lexer.rb Outdated
Creating state classes is pretty expensive.
Since they are not modifiable, we can reuse them instead.
Benchmark script:
```rb
require "ripper"
require "prism"
require "benchmark/ips"
codes = Dir["**/*.rb"].map { File.read(it) }
Benchmark.ips do |x|
x.config(time: 10)
x.report("prism") { codes.each { Prism::Translation::Ripper.lex(it) } }
x.report("ripper") { codes.each { Ripper.lex(it) } }
x.compare!
end
```
Before:
```
ruby 4.0.0 (2025-12-25 revision 553f1675f3) +PRISM [x86_64-linux]
Warming up --------------------------------------
prism 1.000 i/100ms
ripper 1.000 i/100ms
Calculating -------------------------------------
prism 0.293 (± 0.0%) i/s (3.42 s/i) - 3.000 in 10.248348s
ripper 0.633 (± 0.0%) i/s (1.58 s/i) - 7.000 in 11.055687s
Comparison:
ripper: 0.6 i/s
prism: 0.3 i/s - 2.16x slower
```
After
```
ruby 4.0.0 (2025-12-25 revision 553f1675f3) +PRISM [x86_64-linux]
Warming up --------------------------------------
prism 1.000 i/100ms
ripper 1.000 i/100ms
Calculating -------------------------------------
prism 0.486 (± 0.0%) i/s (2.06 s/i) - 5.000 in 10.280413s
ripper 0.635 (± 0.0%) i/s (1.58 s/i) - 7.000 in 11.027169s
Comparison:
ripper: 0.6 i/s
prism: 0.5 i/s - 1.31x slower
```
@eregon
eregon merged commit 3e29586 into ruby:mainJan 19, 2026
66 checks passed
@Earlopain
Earlopain deleted the optimize-ripper branch February 20, 2026 12:42
Sign up for freeto 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.

Ripper translation layer relies on upstream Ripper and is not fully compatible

2 participants

@Earlopain@eregon