Is Ruby 2.3 Faster? Immutable (Frozen) String Literals Performance
Ruby 2.3 was released last month with yet another bunch of performance improvements. But is it really faster than 2.2? Let's take a look.
This is the fourth post in my series about Ruby 2.3 performance. This time we'll look at the immutable (aka frozen) string literals, the experimental feature that will be enabled by default in Ruby 3.0.
Nope, immutable/frozen string literals do not have a significant impact on Ruby performance. Here's why.
What's the Deal With Immutable Strings?
The idea is that every string literal cannot change after the creation. For example, you are not allowed to append to the string:
Note that I had to explicitly enable frozen string literal support by setting the
$RUBYOPT environment variable to
--enable-frozen-string-literal. Here's the ticket where Ruby team discusses the change and its implementation.
The change applies only to literals, meaning strings that appear in the code. String objects continue to be mutable. For example, this is allowed:
How Is That Faster?
The idea is that same string literals across your code will internally be represented with just one Ruby object. Think about hash keys, constants declared as strings, error messages, etc.
That in theory will reduce the number of allocations and the number of Ruby objects on the heap. This means less GC. And, as we all know, less GC is always good.
Read the first chapter from my Ruby Performance Optimization book to better understand the real effect of garbage collection on Ruby performance.
But the change applies only to string literals. Every other string that you use is not going to be immutable. Strings that you read from the file or the database? Nope. Strings that you generate from ERB templates? Nope. Strings you get as HTTP responses? Nope. Pretty much every string that you use as a data is not going to be immutable.
So what's the real world impact of this change in Ruby? Everything suggests it's going to be minimal. Unless there are tens of thousands of string literals somewhere in your code, you probably won't even see it.
An Unscientific Benchmark
Don't try to benchmark the effect of frozen string literals at home yet. Ruby itself, Rails, and many rubygems require patching to make them work with
In the end I got one of my Rails apps (that processes lots of strings) running. Then I issued one hundred of requests to the application and measured the execution time. Here's what I got:
|Mutable String Literals||209 ± 13 s||
171 MB at startup
276 MB afterwards
|Immutable String Literals||193 ± 11 s||
163 MB at startup
267 MB afterwards
As you can see, there's no statistically significant difference between the execution time results. We only see that Rails took 8 MB less memory at startup (good). Most likely this reduction in memory usage is the one promised by our immutable string literals theory. As I predicted, it's not enough to make a difference.
Verdict: Not Faster
Turning on immutable string literals support in Ruby 2.3 does not lead to significant performance improvements. Yes, the memory usage is slightly reduced. But that has little or no effect on execution time.
|Next:||Ruby Performance Optimization Book Tour, San Francisco Bay Area, March 21-28, 2016|
|Previous:||Is Ruby 2.3 Faster? Rails ERB Template Rendering Performance|