rails/activesupport
Jean Boussier 8e0f88d558 Optimize humanize inflector
There a mixed bag of small optimizations here:

  - Since underscores are converted to spaces and that we remove all leading underscores. By changing the order of operations we can leverage the faster `.lstrip!`.
  - Corrected the gsub regexp to no longer match empty strings (`+` vs `*`).
  - Modify the matched strings in place to save on allocations

```ruby
require 'benchmark/ips'
require 'active_support/all'

module ActiveSupport
  module Inflector
    def humanize2(lower_case_and_underscored_word, capitalize: true, keep_id_suffix: false)
      result = lower_case_and_underscored_word.to_s.dup

      inflections.humans.each { |(rule, replacement)| break if result.sub!(rule, replacement) }

      result.tr!("_", " ")
      result.lstrip!
      unless keep_id_suffix
        result.delete_suffix!(" id")
      end

      result.gsub!(/([a-z\d]+)/i) do |match|
        match.downcase!
        inflections.acronyms[match] || match
      end

      if capitalize
        result.sub!(/\A\w/) do |match|
          match.upcase!
          match
        end
      end

      result
    end
  end
end

%w(foo foo_bar_id ____foo_bar).each do |str|
  puts "== Comparing with #{str.inspect} (#{RUBY_VERSION}) =="
  unless ActiveSupport::Inflector.humanize(str) == ActiveSupport::Inflector.humanize2(str)
    raise "#{ActiveSupport::Inflector.humanize2(str)} != #{ActiveSupport::Inflector.humanize(str)}"
  end

  Benchmark.ips do |x|
    x.report('humanize') { ActiveSupport::Inflector.humanize(str) }
    x.report('humanize2') { ActiveSupport::Inflector.humanize2(str) }
    x.compare!
  end
  puts
end
```

```
== Comparing with "foo" (2.7.2) ==
Warming up --------------------------------------
            humanize    25.593k i/100ms
           humanize2    29.256k i/100ms
Calculating -------------------------------------
            humanize    263.989k (± 1.9%) i/s -      1.331M in   5.043110s
           humanize2    299.883k (± 2.2%) i/s -      1.521M in   5.075478s

Comparison:
           humanize2:   299882.5 i/s
            humanize:   263989.1 i/s - 1.14x  (± 0.00) slower

== Comparing with "foo_bar_id" (2.7.2) ==
Warming up --------------------------------------
            humanize    18.187k i/100ms
           humanize2    25.678k i/100ms
Calculating -------------------------------------
            humanize    183.702k (± 1.5%) i/s -    927.537k in   5.050326s
           humanize2    250.470k (± 2.5%) i/s -      1.258M in   5.026682s

Comparison:
           humanize2:   250469.6 i/s
            humanize:   183702.3 i/s - 1.36x  (± 0.00) slower

== Comparing with "____foo_bar" (2.7.2) ==
Warming up --------------------------------------
            humanize    18.577k i/100ms
           humanize2    24.686k i/100ms
Calculating -------------------------------------
            humanize    188.868k (± 1.5%) i/s -    947.427k in   5.017524s
           humanize2    255.650k (± 1.8%) i/s -      1.284M in   5.022833s

Comparison:
           humanize2:   255649.8 i/s
```
2021-02-02 12:16:16 +01:00
..
bin Remove AS::Multibyte's unicode table 2018-02-20 03:58:22 +09:00
lib Optimize humanize inflector 2021-02-02 12:16:16 +01:00
test Update test helper to call parallelize according to fork support 2021-01-25 13:50:41 -06:00
.gitignore Clean up and consolidate .gitignores 2018-02-17 14:26:19 -08:00
activesupport.gemspec Don't make rexml an dependency of activesupport 2020-09-24 22:41:04 +00:00
CHANGELOG.md Merge pull request #40929 from ritikesh/redis_info 2020-12-29 14:29:14 -05:00
MIT-LICENSE Bump license years to 2021 [ci skip] 2021-01-01 12:21:20 +09:00
Rakefile allow running each test with pure ruby path/to/test.rb 2019-12-18 08:49:19 -06:00
README.rdoc Rename master to main in all code references 2021-01-19 20:46:33 +00:00

= Active Support -- Utility classes and Ruby extensions from Rails

Active Support is a collection of utility classes and standard library
extensions that were found useful for the Rails framework. These additions
reside in this package so they can be loaded as needed in Ruby projects
outside of Rails.

You can read more about the extensions in the {Active Support Core Extensions}[https://edgeguides.rubyonrails.org/active_support_core_extensions.html] guide.

== Download and installation

The latest version of Active Support can be installed with RubyGems:

  $ gem install activesupport

Source code can be downloaded as part of the Rails project on GitHub:

* https://github.com/rails/rails/tree/main/activesupport


== License

Active Support is released under the MIT license:

* https://opensource.org/licenses/MIT


== Support

API documentation is at:

* https://api.rubyonrails.org

Bug reports for the Ruby on Rails project can be filed here:

* https://github.com/rails/rails/issues

Feature requests should be discussed on the rails-core mailing list here:

* https://discuss.rubyonrails.org/c/rubyonrails-core