🧊🧶 Rails with Frozen Strings
Chill out and freeze your strings
I’ve had a version of this post in draft mode for over a year, but today Jean Boussier (@byroot) has a great post about Frozen String Literals in Ruby. Seriously, go read it.
I do want to comment on this particular line:
as far as I know, basically no one was trying to run their application with
--enable-frozen-string-literal, and few even knew about it.
🙋
I do! We’ve been running every project for the last few years with RUBYOPT=--enable=frozen-string-literal. What follows is my unedited draft post, that I really should have published a long time ago:
–
I saw this post this week where Ben Sheldon writes,
Super proud of my team at GitHub: our Rails Monolith is now freezing all Ruby strings by default 🧊
We submitted patches for a ton of community gems too. Better together!
This is something we’ve been doing for a couple years now, and I highly recommend it. Here’s why you should care, and how to go about it.
What are we talking about?
We’re talking about running Ruby with RUBYOPT=--enable=frozen-string-literal
Why would I do that?
Memory! Every time you create a string literal (most often a thing in double quotes), that takes up some memory. If you end up creating the same string many times in the code, it is a new memory allocation. Frozen strings are considered the same object, so it can re-use the memory. The garbage collector doesn’t have to do as much work, and you might avoid some memory leaks.
Go read this post from Write Software, Well for more.
Oh, and frozen strings are going to be the default in Ruby 3.4
How do I do it?
You might have seen files with the magic comment # frozen_string_literal: true at the top. This freezes strings in the current file. This is good for gems, but can clutter up your code.
We want to go all-in and do it to the entire project. We do that by setting RUBYOPT=--enable=frozen-string-literal which is like doing the magic comment on everything (including gems).
Oh no, my code broke!
That’s ok! Now you can fix it. Most of the time, fixes are easy. The most common case is where you’re building a string:
data = ""
data << "foo is true" if foo?
data << "bar" if bar.baz?
There, change "" to String.new or +"".
That’s it!
Ease into it
I’d recommend running with frozen strings locally and in your CI environment. Do that today and see how far you get.
You might encounter gems that don’t play nice with frozen strings. We have, and sounds like GitHub did too. We had to submit PRs to handfuls of them, and they were usually accepted readily. And you can always use a fork until they are.
Start new projects with frozen strings
It is much easier to begin a new project with frozen strings than try to update an old one. Start running in all environments with them and see how far you get!
You can do it!
We’ve been running some large, complex Rails apps with frozen strings for over a year. Trust me, you can make it happen!
Comments