rails--rails/activemodel/lib
Jonathan Hefner acbc39b663 Improve human_attribute_name performance
This reduces allocations and improves performance by ~35% when a
translation is defined and ~50% when a translation is not defined.

Benchmark script:

```ruby
require "benchmark/memory"
require "benchmark/ips"

class BaseModel
  extend ActiveModel::Translation
end

Person = Class.new(BaseModel)

module A
  Person = Class.new(BaseModel)

  module B
    Person = Class.new(BaseModel)
  end
end

I18n.backend.store_translations "en",
  activemodel: { attributes: { person: { has_translation: "translated" } } }

Benchmark.memory do |x|
  x.report("warmup") do
    Person.human_attribute_name("first_name")
    A::Person.human_attribute_name("first_name")
    A::B::Person.human_attribute_name("first_name")
    Person.human_attribute_name("has_translation")
  end

  x.report("no namespace") { Person.human_attribute_name("first_name") }
  x.report("1 namespace")  { A::Person.human_attribute_name("first_name") }
  x.report("2 namespaces") { A::B::Person.human_attribute_name("first_name") }

  x.report("has translation") { Person.human_attribute_name("has_translation") }
end

Benchmark.ips do |x|
  x.report("no namespace") { Person.human_attribute_name("first_name") }
  x.report("1 namespace")  { A::Person.human_attribute_name("first_name") }
  x.report("2 namespaces") { A::B::Person.human_attribute_name("first_name") }

  x.report("has translation") { Person.human_attribute_name("has_translation") }
end
```

Before:

```
Calculating -------------------------------------
              warmup   988.923k memsize (    24.587k retained)
                         2.441k objects (   339.000  retained)
                        50.000  strings (    50.000  retained)
        no namespace     6.416k memsize (     0.000  retained)
                        58.000  objects (     0.000  retained)
                        18.000  strings (     0.000  retained)
         1 namespace     6.416k memsize (     0.000  retained)
                        58.000  objects (     0.000  retained)
                        18.000  strings (     0.000  retained)
        2 namespaces     6.416k memsize (     0.000  retained)
                        58.000  objects (     0.000  retained)
                        18.000  strings (     0.000  retained)
     has translation     4.501k memsize (     0.000  retained)
                        46.000  objects (     0.000  retained)
                        18.000  strings (     0.000  retained)

Warming up --------------------------------------
        no namespace   567.000  i/100ms
         1 namespace   563.000  i/100ms
        2 namespaces   565.000  i/100ms
     has translation   839.000  i/100ms
Calculating -------------------------------------
        no namespace      5.642k (± 0.9%) i/s -     28.350k in   5.025255s
         1 namespace      5.652k (± 0.9%) i/s -     28.713k in   5.080325s
        2 namespaces      5.662k (± 1.1%) i/s -     28.815k in   5.090226s
     has translation      8.391k (± 1.6%) i/s -     42.789k in   5.100484s
```

After:

```
Calculating -------------------------------------
              warmup   982.803k memsize (    24.587k retained)
                         2.385k objects (   339.000  retained)
                        50.000  strings (    50.000  retained)
        no namespace     4.712k memsize (     0.000  retained)
                        44.000  objects (     0.000  retained)
                        13.000  strings (     0.000  retained)
         1 namespace     4.712k memsize (     0.000  retained)
                        44.000  objects (     0.000  retained)
                        12.000  strings (     0.000  retained)
        2 namespaces     4.712k memsize (     0.000  retained)
                        44.000  objects (     0.000  retained)
                        12.000  strings (     0.000  retained)
     has translation     3.493k memsize (     0.000  retained)
                        32.000  objects (     0.000  retained)
                        11.000  strings (     0.000  retained)

Warming up --------------------------------------
        no namespace   850.000  i/100ms
         1 namespace   846.000  i/100ms
        2 namespaces   842.000  i/100ms
     has translation     1.127k i/100ms
Calculating -------------------------------------
        no namespace      8.389k (± 0.9%) i/s -     42.500k in   5.066296s
         1 namespace      8.412k (± 0.6%) i/s -     42.300k in   5.028401s
        2 namespaces      8.423k (± 0.6%) i/s -     42.942k in   5.098322s
     has translation     11.303k (± 1.1%) i/s -     57.477k in   5.085568s
```
2022-02-02 11:50:29 -06:00
..
active_model Improve human_attribute_name performance 2022-02-02 11:50:29 -06:00
active_model.rb Bump license years to 2022 [ci-skip] 2022-01-01 15:22:15 +09:00