1
0
Fork 0
mirror of https://github.com/rails/rails.git synced 2022-11-09 12:12:34 -05:00
rails--rails/activemodel/lib/active_model
schneems 5bb1d4d288 Freeze string literals when not mutated.
I wrote a utility that helps find areas where you could optimize your program using a frozen string instead of a string literal, it's called [let_it_go](https://github.com/schneems/let_it_go). After going through the output and adding `.freeze` I was able to eliminate the creation of 1,114 string objects on EVERY request to [codetriage](codetriage.com). How does this impact execution?

To look at memory:

```ruby
require 'get_process_mem'

mem = GetProcessMem.new
GC.start
GC.disable
1_114.times { " " }
before = mem.mb

after = mem.mb
GC.enable
puts "Diff: #{after - before} mb"

```

Creating 1,114 string objects results in `Diff: 0.03125 mb` of RAM allocated on every request. Or 1mb every 32 requests.

To look at raw speed:

```ruby
require 'benchmark/ips'

number_of_objects_reduced = 1_114

Benchmark.ips do |x|
  x.report("freeze")    { number_of_objects_reduced.times { " ".freeze } }
  x.report("no-freeze") { number_of_objects_reduced.times { " " } }
end
```

We get the results

```
Calculating -------------------------------------
              freeze     1.428k i/100ms
           no-freeze   609.000  i/100ms
-------------------------------------------------
              freeze     14.363k (± 8.5%) i/s -     71.400k
           no-freeze      6.084k (± 8.1%) i/s -     30.450k
```

Now we can do some maths:

```ruby
ips = 6_226k # iterations / 1 second
call_time_before = 1.0 / ips # seconds per iteration 

ips = 15_254 # iterations / 1 second
call_time_after = 1.0 / ips # seconds per iteration 

diff = call_time_before - call_time_after

number_of_objects_reduced * diff * 100

# => 0.4530373333993266 miliseconds saved per request
```

So we're shaving off 1 second of execution time for every 220 requests. 

Is this going to be an insane speed boost to any Rails app: nope. Should we merge it: yep. 

p.s. If you know of a method call that doesn't modify a string input such as [String#gsub](b0e2da69f0/lib/let_it_go/core_ext/string.rb (L37)) please [give me a pull request to the appropriate file](b0e2da69f0/lib/let_it_go/core_ext/string.rb (L37)), or open an issue in LetItGo so we can track and freeze more strings. 

Keep those strings Frozen

![](https://www.dropbox.com/s/z4dj9fdsv213r4v/let-it-go.gif?dl=1)
2015-07-19 17:45:10 -05:00
..
locale Move the validate! method to ActiveModel::Validations. 2015-02-20 16:05:26 -02:00
serializers Use Active Model, not ActiveModel in plain English 2015-01-02 14:19:21 -08:00
validations Freeze string literals when not mutated. 2015-07-19 17:45:10 -05:00
attribute_assignment.rb Follow-up to #10776 2015-02-26 15:40:03 +01:00
attribute_methods.rb Freeze string literals when not mutated. 2015-07-19 17:45:10 -05:00
callbacks.rb Fix description for AM::Callbacks 2015-01-31 11:59:02 +05:30
conversion.rb Use Active Model, not ActiveModel in plain English 2015-01-02 14:19:21 -08:00
dirty.rb minor rdoc syntax fix [ci skip] 2015-05-08 14:45:32 -07:00
errors.rb formatting changes 2015-05-29 16:27:23 -04:00
forbidden_attributes_protection.rb Check attributes passed to create_with and where 2014-08-18 14:07:37 -03:00
gem_version.rb Use Active Model, not ActiveModel in plain English 2015-01-02 14:19:21 -08:00
lint.rb Better docs for AM::Lint::Tests 2015-01-07 09:15:47 -08:00
model.rb use attribute assignment module logic during active model initialization 2015-01-23 14:42:47 -08:00
naming.rb Freeze string literals when not mutated. 2015-07-19 17:45:10 -05:00
railtie.rb
secure_password.rb Fix spelling error in has_secure_password documentation [ci skip] 2015-03-03 20:05:02 -05:00
serialization.rb Revert "Add code example for include option of AM::Serialization#serializable_hash" 2015-06-10 08:50:39 -03:00
test_case.rb
translation.rb
validations.rb Revert "Revert "Reduce allocations when running AR callbacks."" 2015-07-16 01:02:15 +08:00
validator.rb Change the deprecation messages to show the preferred way to work with 2015-02-20 20:58:58 -02:00
version.rb Use Active Model, not ActiveModel in plain English 2015-01-02 14:19:21 -08:00