Performance Improvements in Ruby 2.5

New Ruby versions keep improving & Ruby 2.5 is no different.

Ruby 2.5 introduces these optimizations:

  • String interpolation will be around 72% faster when a large string is created
  • String#prepend will be around 42% faster if only one argument is given
  • Enumerable#sort_by, Enumerable#min_by & Enumerable#max_by will be about 50% faster

Let's see some benchmarks!

String Interpolation Performance

I took the example code in the commit message for this optimization:

require 'benchmark/ips'

Benchmark.ips do |x| "Large string interpolation" do |t|
    a = "Hellooooooooooooooooooooooooooooooooooooooooooooooooooo"
    b = "Wooooooooooooooooooooooooooooooooooooooooooooooooooorld"

    t.times { "#{a}, #{b}!" }
  end "Small string interpolation" do |t|
    a = "Hello"
    b = "World"

    t.times { "#{a}, #{b}!" }

I ran this benchmark with the following results.

Ruby 2.4.1:

Small string interpolation:  3236291.1 i/s
Large string interpolation:  1711633.4 i/s - 1.89x  slower

Ruby 2.5:

Small string interpolation:  3125175.1 i/s
Large string interpolation:  2555782.6 i/s - 1.22x  slower

As you can see the difference for large strings is pretty remarkable!

String#prepend Performance

The prepend method allows you to insert some text in front of an array.

Ruby 2.5 optimizes for the most common case, prepending only one string to another.

Here are the benchmark results.

Ruby 2.4.1 results:

String#prepend  3.428M (± 3.2%) i/s - 17.159M in   5.011008s

Ruby 2.5 results:

String#prepend  4.638M (± 3.6%) i/s - 23.276M in   5.025562s

That's a pretty good improvement!

Enumerable Performance Improvements

A few Enumerable methods are getting a performance upgrade.

This particular optimization works because it skips method dispatching for the <=> method.

As described on the commit message:

"Use OPTIMIZED_CMP() to compare the objects instead of <=> method dispatching for Fixnum/Float/String object."

Here are my benchmark results.

Ruby 2.4.2:

Enumerable#sort_by    2.395k (± 6.7%) i/s - 11.952k in   5.014422s
Enumerable#min_by     8.244k (± 6.1%) i/s - 41.405k in   5.042327s
Enumerable#max_by     8.053k (± 6.7%) i/s - 40.180k in   5.015375s

Ruby 2.5:

Enumerable#sort_by    5.914k (± 6.7%) i/s  - 29.786k in   5.062584s
Enumerable#min_by     15.668k (± 3.0%) i/s - 78.888k in   5.039748s
Enumerable#max_by     15.544k (± 2.3%) i/s - 78.408k in   5.046709s

That's about a 50% improvement 🙂

Range#min & Range#max

I have two bonus performance optimizations for you!

One is about the Range#min & Range#max methods.

Here are the benchmarks:

Ruby 2.4.2

Range#min    7.976M (± 3.0%) i/s - 39.950M in   5.013242s
Range#max    7.996M (± 3.4%) i/s - 40.059M in   5.015984s

Ruby 2.5

Range#min   13.154M (± 3.0%) i/s -  65.731M in   5.002094s
Range#max  13.021M (± 2.6%) i/s  -  65.202M in   5.010924s

Find the commit here.

Improved String#scan

According to the commit message this improves performance by 50% for a string pattern & 10% for a regex pattern.

Let’s look at the benchmarks!

Ruby 2.4.2

String#scan - String pattern
       1.367M (±19.8%) i/s - 6.458M in   4.982047s
String#scan - Regex pattern
       1.228M (±17.0%) i/s - 5.881M in   4.983943s

Ruby 2.5

String#scan - String pattern
      3.944M (±24.4%) i/s - 17.739M in   4.977417s
String#scan - Regex pattern
      1.696M (±17.4%) i/s -  8.103M in   4.982614s

Happy faster scanning!


You learned about the new optimizations coming in Ruby 2.5, to be released on December 25.

These optimizations are about string interpolation, Enumerable methods, the String#prepend method, the String#scan method & the Range#max / Range#mix methods.

I hope you enjoyed this post!

Don't forget to share the post on your favorite social networks 🙂

8 thoughts on “Performance Improvements in Ruby 2.5”

  1. I’d like to translate the article and publish on our blog if you’re OK.
    I will make sure to indicate the link to original, author name, and your site.

    Best regards,

Comments are closed.