Performance Gains in Ruby 3.3- String.dup vs. String#+

Ruby has a lot of methods available for the String class for the various use cases, and one of them is to freeze/unfreeze string.

Two commonly used methods for unfreezing string literals are String#+(unary plus) and String#dup.

While both of them can be used to unfreeze the string String#+ was preferred over String#dup because it’s faster than the latter.

Before

In versions before 3.3 String#+ was almost two times faster than the much easier to read and convenient String.dup method.

The performance improvement comes from the fact that String#+@ can directly go through rb_str_dup (a specific method for duplicating strings) instead of using the more generic and slower rb_obj_dup (a more general method for duplicating objects).

We can compare the performance metrics of both methods by using benchmark-ips gem.

require "bundler/inline"

gemfile(true) do
  source "https://rubygems.org"

  gem "benchmark-ips"
end

Benchmark.ips do |x|
  x.report('+@') { +"Saeloun Blog" }
  x.report('dup') {"Saeloun Blog".dup }
  x.compare!
end

From the benchmark test, we can observe that the Unary plus method is faster as compared to String.dup.

It also led to the Performance/UnfreezeString cop which encourages the performance-oriented developers to prefer String#+ over much more readable String.dup

After

From Ruby 3.3 onwards, the String.dup has been optimized to be as efficient as String#+.

It means that now developers can choose the method based on readability and preference without sacrificing performance.

We can confirm the same by performing a benchmark test with Ruby version 3.3

From the above benchmark test it is confirmed that the String.dup is now as fast as String#+

To know more about this, please refer to this PR.

Need help on your Ruby on Rails or React project?

Join Our Newsletter