Faster counting in ruby 2

Angelegt von andi Sun, 03 Oct 2010 15:40:00 GMT

Assuming you want to do something 100.000 times.

The usual way is, to run a loop and use an counter

i =0 while i < 100000 do #DO something i = i+1 # in some languages you have i++ instead end

this sets i to it’s former value plus one after every loop.

I did a benchmark between Integer#+1 and Integer#next

Integer next is the favourite, because it knows, that it needs to count plus one already.

Here is the result:

jrw@sublime:~$ ruby integer_next_against_plus_1.rb 
using i.next 100 times
1
101
  0.000000   0.000000   0.000000 (  0.000115)
using i+1 100 times
1
101
  0.000000   0.000000   0.000000 (  0.000108)
using i.next 1000 times
101
1101
  0.000000   0.000000   0.000000 (  0.000881)
using i+1 1000 times
101
1101
  0.000000   0.000000   0.000000 (  0.001130)
using i.next 10000 times
1101
11101
  0.020000   0.000000   0.020000 (  0.011330)
using i+1 10000 times
1101
11101
  0.000000   0.000000   0.000000 (  0.011211)
using i.next 100000 times
11101
111101
  0.080000   0.020000   0.100000 (  0.118224)
using i+1 100000 times
11101
111101
  0.080000   0.010000   0.090000 (  0.110932)
using i.next 1000000 times
111101
1111101
  0.690000   0.230000   0.920000 (  0.998541)
using i+1 1000000 times
111101
1111101
  0.800000   0.180000   0.980000 (  1.051063)
using i.next 10000000 times
1111101
11111101
  7.000000   2.060000   9.060000 (  9.769309)
using i+1 10000000 times
1111101
11111101
  7.630000   2.110000   9.740000 ( 10.480469)
using i.next 100000000 times
11111101
111111101
 68.130000  19.560000  87.690000 ( 89.887507)
using i+1 100000000 times
11111101
111111101
 76.420000  19.240000  95.660000 ( 98.498498)
using i.next 1000000000 times
111111101

and here the code

require 'benchmark'


i1 = 1
i2 = 1
r1 = ""
r2 = ""

time = 100

while time < 100000000000000

puts "using i.next #{time} times"
puts i1
 r1 = Benchmark.measure do
  time.times do
    i1 = i1.next
  end
end
puts i1
puts r1

puts "using i+1 #{time} times"
puts i2
  r2 = Benchmark.measure do

time.times do

    i2 = i2+1
  end
end
puts i2
puts r2

time = time * 10
end

So, if you want to count, it’s alsmost 10% faster, to use builtin Integer.next

Trackbacks

Verwenden Sie den folgenden Link zur Rückverlinkung von Ihrer eigenen Seite:
http://praktikanten.brueckenschlaeger.org/trackbacks?article_id=298

Comments

Leave a comment

  1. niklas about {{count}} hours later:

    I think more considerable than the speed of incrementing number is the performance of different kinds of loops. I’d like to see measurements of:

    • Ranges w/ each: (0..10000).each {|i|}

    • Integer#upto: 0.upto(10000) {|i|}

    • Integer#times: 10000.times {|i|}

    • Enumerable#each_with_index (even though not applicable in this range of examples, this is probably the most widely used application of counting in our apps)

    All these are implemented in C, hence benefit from the optimization of incrementing done by the compiler.

    Anyway, nice work, thank you very much. (maybe I’ll do those benchmarks I suggested at some point myself…)

    Uh, one last thing: You can write numbers much readable by using underscores: 100000 == 100_000

  2. suung about {{count}} hours later:

    yes.

    i also did comparison of finding very long integers in a list against very short integers.

    I did it in a discussion, whether GUI (globally unique identifiers) are a good thing or not.

    The result was: Kind of equal, but of course slower. I will post this.

Comments