.
Bitland.Net Security Notes            Comments? email jwilkins-at-bitland*net
More information on the author at Jonathan Wilkins's home page
RSS feed available at http://www.bitland.net/index.rss               Add to Google
Archives: 2007, 2006, 2005, 2004, 2003, 2002, 2001, 2000


Loop speed comparison  |  (2008/11/25 15:20)

I was optimizing some code recently and noticed that there was a huge difference in speed with certain types of loop. I'm running 1.8.6 on OS X.
ruby --version : ruby 1.8.6 (2008-03-03 patchlevel 114) [i686-darwin]
I was indexing into a string and using a counter variable with a while loop and it was absurdly slow. So I wrote a quick test program and ran it through ruby-prof and the while x < 99999999 style loop is 6 times slower than the alternatives.
require 'rubygems'
require 'ruby-prof'

$count = 99_999_999

def time_it(code, filename)
  RubyProf.start
  code.call
  prof_data = RubyProf.stop
  printer = RubyProf::FlatPrinter.new(prof_data)
  printer.print(open(filename, 'w+'), 0)
end

times = Proc.new { $count.times { |x| a = x } } 
time_it(times, 'loops-times.txt')

#Thread ID: 131970
#Total: 240.905949
#
# %self     total     self     wait    child    calls  name
#100.00    240.91   240.91     0.00     0.00        1  Integer#times (ruby_runtime:0}
#  0.00    240.91     0.00     0.00   240.91        1  Object#time_it (perf-loops.rb:8}
#  0.00    240.91     0.00     0.00   240.91        1  Proc#call (ruby_runtime:0}

#------------------------------------------------------------------------------

range_each = Proc.new { (0..$count).each { |x| a = x } }
time_it(range_each, 'loops-range_each.txt')

#Thread ID: 131970
#Total: 247.886152
#
# %self     total     self     wait    child    calls  name
#100.00    247.89   247.89     0.00     0.00        1  Range#each (ruby_runtime:0}
#  0.00    247.89     0.00     0.00   247.89        1  Object#time_it (perf-loops.rb:8}
#  0.00    247.89     0.00     0.00   247.89        1  Proc#call (ruby_runtime:0}
#  0.00      0.00     0.00     0.00     0.00        1  #allocate (ruby_runtime:0}

#------------------------------------------------------------------------------
upto = Proc.new { 0.upto($count) { |x| a = x } }
time_it(upto, 'loops-upto.txt')

#Thread ID: 131970
#Total: 245.206868
#
# %self     total     self     wait    child    calls  name
#100.00    245.21   245.21     0.00     0.00        1  Integer#upto (ruby_runtime:0}
#  0.00    245.21     0.00     0.00   245.21        1  Object#time_it (perf-loops.rb:8}
#  0.00    245.21     0.00     0.00   245.21        1  Proc#call (ruby_runtime:0}

#------------------------------------------------------------------------------
$i = 0
while_plus_equals = Proc.new { while $i < $count do a = $i; $i += 1; end }
time_it(while_plus_equals, 'loops-while_plus_equals.txt')

#Thread ID: 131970
#Total: 1270.530267
#
# %self     total     self     wait    child    calls  name
# 66.86   1270.53   849.47     0.00   421.06        1  Proc#call (ruby_runtime:0}
# 16.68    211.95   211.95     0.00     0.00 99999999  Fixnum#+ (ruby_runtime:0}
# 16.46    209.11   209.11     0.00     0.00 100000000  Fixnum#< (ruby_runtime:0}
#  0.00   1270.53     0.00     0.00  1270.53        1  Object#time_it (perf-loops.rb:8}


+digg  |  +del.icio.us   |    [Ruby ]   |   Permanent link

RSS feed available at http://www.bitland.net/index.rss