will Ruby 2.3 make our Rails apps faster?

13 views
Skip to first unread message

Colin Kelley

unread,
Dec 2, 2015, 1:56:01 AM12/2/15
to sbonrails
Hi SB on Rails folks,

Ruby 2.3 is out in preview.  We're really happy to see it!


First off, the magic comment to make string literals immutable that we've been lobbying for made it in, with a plan for immutable string literals to be the default in Ruby 3.0.  The magic comment ultimately chosen was:

# frozen_string_literal: true

Why should you care?  Because it will make your Ruby code faster.  (And it might save you chasing after a bizarre bug where a shared string reference was mutated.[2])

In the discussion in issue 8976, Rafael Franca reported[1] an 11% performance improvement on a sample Rails app.  Apps should have significant reduction in the amount of garbage collection they do too.

If you get a chance to try out 2.3 in a benchmark, we'd love to hear what kind of improvement you measure.  You'll need to mark all your files--and your most important gems like Rails itself--with the above pragma, which you can do with this handy command line gem.


Also, Ruby 2.3 has a handy new `dig` method on Hash and Array to make it easier to dig values out of parsed JSON for example.  If you'd like to use that method in advance of moving your app to 2.3, try out the ruby_dig gem.  There's more background on that here.

-Colin


[1]

 Updated by Rafael França 3 months ago

Here you can see more information about the actual effect of frozen string on Ruby on Rails https://github.com/rails/rails/pull/21057. It is 11% in a relative small application, in big applications this improvement can be bigger.

[2]
DEFAULT_NAME = "JOHN DOE"

class A
  def initialize(name)
    @upcase_name = name.upcase!
  end
end

name = DEFAULT_NAME
=> "JOHN DOE"

a = A.new(
DEFAULT_NAME)

name
=> "john doe" # Global constant mutated silently! All shared references changed.

Colin Kelley

unread,
Dec 2, 2015, 2:18:15 AM12/2/15
to sbonrails
[correcting an upcase->downcase typo in this example--thanks Amir]

[2]
DEFAULT_NAME = "JOHN DOE"

class A
  def initialize(name)
    @upcase_name = name.downcase!

  end
end

name = DEFAULT_NAME
=> "JOHN DOE"

a = A.new(
DEFAULT_NAME)

name
=> "john doe" # Global constant mutated silently! All shared references changed.

Andrew Le

unread,
Dec 2, 2015, 3:34:09 AM12/2/15
to Colin Kelley, sbonrails
Thanks, Colin! I remember you mentioning this a while back. Nice to see it happen finally.

Rather, than tagging all your files with the magic comment, I believe you can use the RUBYOPT environment variable to enable this option and magically get it for all processes in started in the that shell environment.

RUBYOPT="--enable-frozen-string-literal" 

//A

--
You received this message because you are subscribed to the Google Groups "sbonrails" group.
To unsubscribe from this group and stop receiving emails from it, send an email to sbonrails+...@googlegroups.com.
To post to this group, send email to sbon...@googlegroups.com.
Visit this group at http://groups.google.com/group/sbonrails.
For more options, visit https://groups.google.com/d/optout.

Colin Kelley

unread,
Dec 2, 2015, 3:56:28 AM12/2/15
to Andrew Le, sbonrails
Hi Andrew, yes, you can set that global option to mimic Ruby 3.0 behavior.  But only do it when you're confident that all your code and every library and gem you use does not mutate string literals.  (For example, don't set that option if your code--or any gem you use--calls URI#to_s!)  You could give that global a shot for a benchmark, but it's probably too soon for any code in production.  For production, I recommend the magic comment to mark the repos that have been tested/updated.  Expect to see a flurry of gem revisions with the magic comment at the top as the maintainers get around to reviewing/testing them.  [And hopefully we'll stop seeing the flurry of gem revisions adding ".freeze" after every string literal.  That was untenable.]

-Colin

Andrew Le

unread,
Dec 2, 2015, 4:04:48 AM12/2/15
to Colin Kelley, sbonrails
So... we're certain that Rails doesn't mutate string literals anywhere? ;-P

//A

Colin Kelley

unread,
Dec 2, 2015, 10:29:22 AM12/2/15
to Andrew Le, sbonrails
So... we're certain that Rails doesn't mutate string literals anywhere? ;-P

Sure... once all the tests are green with that magic comment at the top. :)

By inspection I can see at least a handful of cases of mutation like this:

 
BTW the fix is simply to change line 171 to

    text = ''.dup

or, my preference because it is more intention-revealing:

    text = String.new

-Colin
Reply all
Reply to author
Forward
0 new messages