Optimize humanize inflector#41305
Merged
Merged
Conversation
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
```
Contributor
|
Sweet! |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Followup: #41296, #41303
There a mixed bag of small optimizations here:
.lstrip!.+vs*).@kaspth @rafaelfranca @etiennebarrie