diff options
author | Xavier Noria <fxn@hashref.com> | 2016-04-20 16:08:47 +0200 |
---|---|---|
committer | Xavier Noria <fxn@hashref.com> | 2016-04-20 16:28:54 +0200 |
commit | 697384df36a939e565b7c08725017d49dc83fe40 (patch) | |
tree | 688e284a508a243165ca154e3c41cecb7978fc29 /activesupport/lib/active_support | |
parent | a3c8a8ee9951969f31ef8fa5955e08513842cfaa (diff) | |
download | rails-697384df36a939e565b7c08725017d49dc83fe40.tar.gz rails-697384df36a939e565b7c08725017d49dc83fe40.tar.bz2 rails-697384df36a939e565b7c08725017d49dc83fe40.zip |
~3.5x speedup of String#blank? for empty strings
See the rationale in the comment in this patch.
To benchmark this I ran a number of variations, ultimately narrowing to
require 'benchmark/ips'
str = ''
regexp = /\A[[:space:]]*\z/
Benchmark.ips do |x|
x.report('regexp') { regexp === str }
x.report('empty') { str.empty? || regexp === str }
x.compare!
end
This benchmark has consistently reported speedups around 3.5x:
Calculating -------------------------------------
regexp 69.197k i/100ms
empty 115.468k i/100ms
-------------------------------------------------
regexp 2. 6.3%) i/s - 13.839M
empty 9. 8.8%) i/s - 47.804M
Comparison:
empty: 9642607.6 i/s
regexp: 2768351.9 i/s - 3.48x slower
Sometimes even reaching 4x.
Running the same bechmark on strings of 10 or 100 characters (with
whitespace or present) has shown a slowdown of just about 1.01/1.02.
Marginal, we seem to have a worthwhile trade-off here.
Diffstat (limited to 'activesupport/lib/active_support')
-rw-r--r-- | activesupport/lib/active_support/core_ext/object/blank.rb | 7 |
1 files changed, 6 insertions, 1 deletions
diff --git a/activesupport/lib/active_support/core_ext/object/blank.rb b/activesupport/lib/active_support/core_ext/object/blank.rb index 039c50a4a2..71d411b6d6 100644 --- a/activesupport/lib/active_support/core_ext/object/blank.rb +++ b/activesupport/lib/active_support/core_ext/object/blank.rb @@ -112,7 +112,12 @@ class String # # @return [true, false] def blank? - BLANK_RE === self + # In practice, the majority of blank strings are empty. As of this writing + # checking for empty? is about 3.5x faster than matching against the regexp + # in MRI, so we call the predicate first, and then fallback. + # + # The penalty for blank strings with whitespace or present ones is marginal. + empty? || BLANK_RE === self end end |