fastruby / fast-ruby

:dash: Writing Fast Ruby :heart_eyes: -- Collect Common Ruby idioms.
https://github.com/fastruby/fast-ruby
5.67k stars 376 forks source link

Immutable vs Mutable strings #100

Closed avellable closed 8 years ago

avellable commented 8 years ago

Using 'freeze' increases performances for strings.

In Ruby 2.1, "str".freeze is optimized by the compiler to return a single shared frozen strings on every invocation. An alternative "str"f syntax was implemented initially, but later reverted.

Although the external scope of this feature is limited, internally it is used extensively to de-duplicate strings in the VM. Previously, every def method_missing(), the symbol :method_missing and any literal "method_missing" strings in the code-base would all create their own String objects. With Ruby 2.1, only one string is created and shared. Since many strings are commonly re-used in any given code base, this easily adds up. In fact, large applications can expect up to 30% fewer long-lived strings on their heaps in 2.1.

For 2.2, there are plans to expose this feature via a new String#f. There's also a proposal for a magic immutable: string comment to make frozen strings default for a given file.

Source: http://tmm1.net/ruby21-fstrings/

ixti commented 8 years ago

So, you created two String objects, and compare how fast Hash#[] works with strings... o_O What really makes sense in terms of immutable strings is:

# allocates new string over and over again
def slow
  "foobar"
end

# keeps and reuses shared string
def fast
  "foobar".freeze
end

Benchmark.ips do |x|
  x.report("slow") { slow }
  x.report("fast") { fast }
  x.compare!
end
nateberkopec commented 8 years ago

What @ixti said :+1:

avellable commented 8 years ago

Yeah, looks like that makes more sense.

ruby 2.2.1p85 (2015-02-26 revision 49769) [x86_64-darwin14]
Warming up --------------------------------------
      Without Freeze   106.961k i/100ms
         With Freeze   118.210k i/100ms
Calculating -------------------------------------
      Without Freeze      4.386M (± 6.1%) i/s -     21.927M
         With Freeze      6.893M (± 6.9%) i/s -     34.281M

Comparison:
         With Freeze:  6892639.5 i/s
      Without Freeze:  4386460.4 i/s - 1.57x slower

I updated the PR.

JuanitoFatas commented 8 years ago

@ixti @nateberkopec Thanks for review 🙇

@avellable Would you like to be a collaborator :) ?

avellable commented 8 years ago

@JuanitoFatas Sure!

JuanitoFatas commented 8 years ago

@JuanitoFatas Sure!

Added, welcome 😃

avellable commented 8 years ago

Thank you. :)