mirror of https://github.com/rails/rails
Optimize ActiveSupport::NumericWithFormat#to_s
`case format when nil` is very efficient because it end up calling `NilClass === nil` which pretty much translates to `nil.is_a?(NilClass)`. On the other hand `format.nil?` benefit from a dedicated op code, so it's quite faster. In this case `Integer#to_s` is much more often called without any arguments, so it's worth optimizing for the most common case. ```ruby class Integer alias_method :faster_to_s, :to_s end require 'active_support/all' require 'benchmark/ips' module FasterNumericWithFormat def faster_to_s(format = nil, options = nil) if format.nil? return super() end case format when Integer, String super(format) when :phone ActiveSupport::NumberHelper.number_to_phone(self, options || {}) when :currency ActiveSupport::NumberHelper.number_to_currency(self, options || {}) when :percentage ActiveSupport::NumberHelper.number_to_percentage(self, options || {}) when :delimited ActiveSupport::NumberHelper.number_to_delimited(self, options || {}) when :rounded ActiveSupport::NumberHelper.number_to_rounded(self, options || {}) when :human ActiveSupport::NumberHelper.number_to_human(self, options || {}) when :human_size ActiveSupport::NumberHelper.number_to_human_size(self, options || {}) when Symbol super() else super(format) end end end Integer.prepend(FasterNumericWithFormat) Benchmark.ips do |x| x.report('orig no-arg') { 42.to_s } x.report('fast no-arg') { 42.faster_to_s } x.compare! end Benchmark.ips do |x| x.report('orig :human') { 42.to_s(:human) } x.report('fast :human') { 42.faster_to_s(:human) } x.compare! end ``` Ruby 2.7.2 ``` Warming up -------------------------------------- orig no-arg 567.569k i/100ms fast no-arg 692.636k i/100ms Calculating ------------------------------------- orig no-arg 5.709M (± 1.3%) i/s - 28.946M in 5.070660s fast no-arg 6.892M (± 0.7%) i/s - 34.632M in 5.024961s Comparison: fast no-arg: 6892287.7 i/s orig no-arg: 5709450.0 i/s - 1.21x (± 0.00) slower Warming up -------------------------------------- orig :human 575.000 i/100ms fast :human 619.000 i/100ms Calculating ------------------------------------- orig :human 6.176k (± 1.6%) i/s - 31.050k in 5.028656s fast :human 6.179k (± 1.8%) i/s - 30.950k in 5.010372s Comparison: fast :human: 6179.1 i/s orig :human: 6176.3 i/s - same-ish: difference falls within error ```
This commit is contained in:
parent
6675f6b785
commit
31c20e248a
|
@ -107,9 +107,9 @@ module ActiveSupport
|
|||
# separator: ',',
|
||||
# significant: false) # => "1,2 Million"
|
||||
def to_s(format = nil, options = nil)
|
||||
return super() if format.nil?
|
||||
|
||||
case format
|
||||
when nil
|
||||
super()
|
||||
when Integer, String
|
||||
super(format)
|
||||
when :phone
|
||||
|
|
Loading…
Reference in New Issue