d36eb23976
Because `#present?` always resolve to `Object#present?`, it's an extremely polymorphic method, and inline cache hits are low. In addition, it requires an extra call to `self.blank?` which is an overhead. By specializing `present?` on common types, we avoid both of these slow-downs: ``` ruby 3.2.2 (2023-03-30 revision e51014f9c0) [arm64-darwin22] Warming up -------------------------------------- present? 198.028k i/100ms opt_present? 565.521k i/100ms Calculating ------------------------------------- present? 2.087M (± 8.8%) i/s - 10.297M in 5.028398s opt_present? 5.584M (± 8.6%) i/s - 27.711M in 5.023852s Comparison: present?: 2086621.6 i/s opt_present?: 5584373.5 i/s - 2.68x faster ``` ``` ruby 3.2.2 (2023-03-30 revision e51014f9c0) +YJIT [arm64-darwin22] Warming up -------------------------------------- present? 819.792k i/100ms opt_present? 1.047M i/100ms Calculating ------------------------------------- present? 12.192M (± 8.8%) i/s - 60.665M in 5.050622s opt_present? 16.540M (± 8.2%) i/s - 82.676M in 5.059029s Comparison: present?: 12192047.5 i/s opt_present?: 16539689.6 i/s - 1.36x faster ``` ```ruby require 'bundler/inline' gemfile do source 'https://rubygems.org' gem 'benchmark-ips' gem 'activesupport' end require 'active_support/all' class Object def opt_present? respond_to?(:empty?) ? !empty? : !!self end end class NilClass def opt_present? false end end class FalseClass def opt_present? false end end class TrueClass def opt_present? true end end class Array def opt_present? !empty? end end class Hash def opt_present? !empty? end end class Symbol def opt_present? !empty? end end class String def opt_present? !blank? end end class Numeric # :nodoc: def opt_present? true end end class Time # :nodoc: def opt_present? true end end array = [] hash = {} time = Time.now puts RUBY_DESCRIPTION Benchmark.ips do |x| x.report("present?") do true.present? false.present? 1.present? 1.0.present? array.present? hash.present? :foo.present? time.present? end x.report("opt_present?") do true.opt_present? false.opt_present? 1.opt_present? 1.0.opt_present? array.opt_present? hash.opt_present? :foo.opt_present? time.opt_present? end x.compare!(order: :baseline) end ``` |
||
---|---|---|
.. | ||
bin | ||
lib | ||
test | ||
.gitignore | ||
activesupport.gemspec | ||
CHANGELOG.md | ||
MIT-LICENSE | ||
Rakefile | ||
README.rdoc |
= 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://guides.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