Skip to content

Instantly share code, notes, and snippets.

@SamSaffron SamSaffron/bench.rb
Created Apr 27, 2016

Embed
What would you like to do?
require 'benchmark/ips'
LONG_STRING = " this is a longer test
this is a longer test
this is a longer test
this is a longer test
this is a longer test"
class String
def original_blank?
/\A[[:space:]]*\z/ === self
end
def original_blank_with_empty?
empty? || (/\A[[:space:]]*\z/ === self)
end
def new_blank?
empty? || !(/[[:^space:]]/ === self)
end
end
Benchmark.ips do |x|
x.report('original blank no internal loop') do
/\A[[:space:]]*\z/ === LONG_STRING
end
x.report('original blank with empty no internal loop') do
LONG_STRING.empty? || (/\A[[:space:]]*\z/ === LONG_STRING)
end
x.report('new blank with empty no internal loop') do
LONG_STRING.empty? || !(/[[:^space:]]/ === LONG_STRING)
end
x.report('original blank times loop') do |t|
t.times do
/\A[[:space:]]*\z/ === LONG_STRING
end
end
x.report('original blank with empty times loop') do |t|
t.times do
LONG_STRING.empty? || (/\A[[:space:]]*\z/ === LONG_STRING)
end
end
x.report('new blank with empty times loop') do |t|
t.times do
LONG_STRING.empty? || !(/[[:^space:]]/ === LONG_STRING)
end
end
x.report('original blank while loop') do |t|
i = 0
while i < t
/\A[[:space:]]*\z/ === LONG_STRING
i += 1
end
end
x.report('original blank with empty while loop') do |t|
i = 0
while i < t
LONG_STRING.empty? || (/\A[[:space:]]*\z/ === LONG_STRING)
i += 1
end
end
x.report('new blank with empty while loop') do |t|
i = 0
while i < t
LONG_STRING.empty? || !(/[[:^space:]]/ === LONG_STRING)
i += 1
end
end
x.report('patched string original blank while loop') do |t|
i = 0
while i < t
LONG_STRING.original_blank?
i += 1
end
end
x.report('patched string original blank with empty while loop') do |t|
i = 0
while i < t
LONG_STRING.original_blank_with_empty?
i += 1
end
end
x.report('patched string new blank with while loop') do |t|
i = 0
while i < t
LONG_STRING.new_blank?
i += 1
end
end
x.compare!
end
@SamSaffron

This comment has been minimized.

Copy link
Owner Author

SamSaffron commented Apr 27, 2016

Results:

-------------------------------------------------
original blank no internal loop
                          3.364M (± 2.2%) i/s -     16.822M
original blank with empty no internal loop
                          3.221M (± 2.2%) i/s -     16.112M
new blank with empty no internal loop
                          3.711M (± 3.0%) i/s -     18.558M
original blank times loop
                          3.809M (± 2.0%) i/s -     19.124M
original blank with empty times loop
                          3.656M (± 2.5%) i/s -     18.356M
new blank with empty times loop
                          4.293M (± 3.3%) i/s -     21.446M
original blank while loop
                          4.197M (± 2.3%) i/s -     21.109M
original blank with empty while loop
                          4.042M (± 3.9%) i/s -     20.273M
new blank with empty while loop
                          4.846M (± 2.0%) i/s -     24.284M
patched string original blank while loop
                          3.773M (± 2.1%) i/s -     18.954M
patched string original blank with empty while loop
                          3.645M (± 2.9%) i/s -     18.363M
patched string new blank with while loop
                          1.985M (± 5.0%) i/s -      9.971M

Comparison:
new blank with empty while loop:  4846442.9 i/s
new blank with empty times loop:  4293406.6 i/s - 1.13x slower
original blank while loop:  4197128.9 i/s - 1.15x slower
original blank with empty while loop:  4042239.5 i/s - 1.20x slower
original blank times loop:  3808940.4 i/s - 1.27x slower
patched string original blank while loop:  3773147.8 i/s - 1.28x slower
new blank with empty no internal loop:  3711448.5 i/s - 1.31x slower
original blank with empty times loop:  3656175.9 i/s - 1.33x slower
patched string original blank with empty while loop:  3645082.5 i/s - 1.33x slower
original blank no internal loop:  3363782.7 i/s - 1.44x slower
original blank with empty no internal loop:  3220765.0 i/s - 1.50x slower
patched string new blank with while loop:  1984885.6 i/s - 2.44x slower
@SamSaffron

This comment has been minimized.

Copy link
Owner Author

SamSaffron commented Apr 27, 2016

So:

Fastest is code is:

  x.report('new blank with empty while loop') do |t|
    i = 0
    while i < t
      LONG_STRING.empty? || !(/[[:^space:]]/ === LONG_STRING)
      i += 1
    end
  end

BUT this is the slowest!

class String
  def original_blank?
    /\A[[:space:]]*\z/ === self
  end

  def original_blank_with_empty?
    empty? || (/\A[[:space:]]*\z/ === self)
  end

  def new_blank?
    empty? || !(/[[:^space:]]/ === self)
  end

end

 x.report('patched string new blank with while loop') do |t|
    i = 0
    while i < t
      LONG_STRING.new_blank?
      i += 1
    end
  end
@SamSaffron

This comment has been minimized.

Copy link
Owner Author

SamSaffron commented Apr 27, 2016

reason appears to be that new regex allocates a lot more bytes than old regex

https://gist.github.com/SamSaffron/f73fd0395e050e927d1a3137373eeaee

@schneems

This comment has been minimized.

Copy link

schneems commented Apr 28, 2016

It looks like the memory use is larger because a character is matched and a MatchData object is created, if you make the string empty LONG_STRING = " " then the old regex will generate and return a match which will allocate a MatchData. It will then be larger if you evaluate with MemoryProfiler

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.