proposed Ruby 2.1.1 magic comment 'immutable: string' yields 1.64X speedup!

18 views
Skip to first unread message

Colin Kelley

unread,
Dec 29, 2013, 11:22:11 PM12/29/13
to sbon...@googlegroups.com
Hey everyone,

Did you realize that Ruby string literals are allocated every time the enclosing code runs, just in case they might later be mutated?  I didn't until this year.  For example, this code will allocate (and then garbage collect) the "Hello, world!" string [cue Dr. Evil accent] 1 million times:

1_000_000.times do 
  LOGGER.info("Hello, world!")
end

Ruby 2.1 originally had an innovative--but ugly--feature to make string literals immutable by putting a trailing `f` after the string, as in

LOGGER.info("Hello, world!"f)

1. That got interesting when several Rails core members implemented the optimizations to allocate the frozen string literal just once at parse time and share it across the whole file.

The above change makes this benchmark run 1.64X faster!  (This is partly because the shared literal strings have the same object_id which makes == on equality return in O(1) time--basically instantly.)

2. Charles Nutter undid the ugly `fsyntax with a cleaner variation that is backward-compatible:

LOGGER.info("Hello, world!".freeze)

But still, to get the speed improvement you'd have to write .freeze after every string literal in your code.  IMO that's a non-starter.  Therefore...

3. We've submitted this pull request (and matching Ruby issue) that adds a magic comment, inspired by the Ruby 1.9's # -*- encoding: utf8 -*- comment:

# -*- immutable: string -*-

Put that at the top of all the files in your project and voilà:  same code speedup with nothing but a magic comment.  (And the magic comment can be automatically added to your files by this fork of the magic_encoding gem called, naturally, magic_immutable_string.)

BTW if any of your tests fail because you actually need to mutate a string literal (this is rare) you can address that by calling

String.new('')   # or ''.dup

If you'd like to see Ruby run faster (and be more functional), please help lobby to get this pull request accepted.  We will all benefit.

For more details , we have several articles on our development blog.

-Colin
Colin Kelley, CTO/co-founder, Invoca, (formerly RingRevenue), Inc.
Reply all
Reply to author
Forward
0 new messages