From: Benoit Daloze Date: 2011-01-27T22:10:04+09:00 Subject: Re: Enumerable.inject_with_index? On 27 January 2011 01:42, redstun wrote: > Interesting, thanks Colin. > > As you said, the code you demonstrated, could performer better, meanwhile > it's somewhat less elegant. > > IMHO the code is ok, we just have more space inside the > interpreter/runtime to get improved, like in JVM, the JIT compiler could > compile all of the 4 lines of code in to the same machine instructions and > yield the same performance. > > The dynamic nature and elegance design of Ruby certainly sacrificed > performance at somewhat level, but  that doesn't stop you and me from using > it, right? :-) > > Anyway, thanks for the benchmark demo, I just ran it on my machine, with > both MRI and JRuby, > MRI 1.8.7 >                                user     system      total        real > each_with_index.inject(0)   4.930000   0.000000   4.930000 (  5.036288) > inject(0)                   3.088000   0.000000   3.088000 (  3.080176) > each_with_index             2.668000   0.000000   2.668000 (  2.668153) > each                        1.700000   0.000000   1.700000 (  1.713098) > > JRuby 1.5.6 >                                user     system      total        real > each_with_index.inject(0)   1.918000   0.000000   1.918000 (  1.918000) > inject(0)                   1.058000   0.000000   1.058000 (  1.058000) > each_with_index             0.979000   0.000000   0.979000 (  0.979000) > each                        0.624000   0.000000   0.624000 (  0.624000) > > Like your result the raw each runs the fastest, but we can also find that, > the result of each_with_index.inject with JRuby is already close to that of > raw each with MRI. > > > On Tue, Jan 25, 2011 at 5:43 AM, Colin Bartlett wrote: > >> I'm curious as to when and why people use each_with_index and/or >> inject, etc, instead of a somewhat less elegant, and admittedly >> possibly less flexible, more direct approach. (Which usually(?) takes >> about the same number of characters for the code.) >> >> ary = [3, 4, 5] >> rrr = ary.each_with_index.inject(0) { |sum, (v, index)| sum + v * index } >> p rrr #=> 14 >> index = -1; rrr = ary.inject(0) { |sum, v| index += 1; sum + v * index } >> p rrr #=> 14 >> rrr = 0; ary.each_with_index { |v, index| rrr += v * index }; rrr >> p rrr #=> 14 >> index = -1; rrr = 0; ary.each { |v| index += 1; rrr += v * index }; rrr >> p rrr #=> 14 >> >> require "benchmark" >> kt = 500_000 >> Benchmark.bmbm() do |bm| >>  bm.report( "each_with_index.inject(0)" ) { kt.times { >>   rrr = ary.each_with_index.inject(0) { |sum, (v, index)| sum + v * index } >>  } } >>  bm.report( "inject(0)"                 ) { kt.times { >>   index = -1; rrr = ary.inject(0) { |sum, v| index += 1; sum + v * index } >>  } } >>  bm.report( "each_with_index"           ) { kt.times { >>   rrr = 0; ary.each_with_index { |v, index| rrr += v * index } >>  } } >>  bm.report( "each"                      ) { kt.times { >>   index = -1; rrr = 0; ary.each { |v| index += 1; rrr += v * index } >>  } } >> end >> >> #=> >> Rehearsal ------------------------------------------------------------- >> each_with_index.inject(0)   2.410000   0.000000   2.410000 (  2.404242) >> inject(0)                   1.000000   0.000000   1.000000 (  1.000677) >> each_with_index             0.840000   0.010000   0.850000 (  0.846287) >> each                        0.640000   0.000000   0.640000 (  0.640142) >> ---------------------------------------------------- total: 4.900000sec >> >>                                user     system      total        real >> each_with_index.inject(0)   2.380000   0.020000   2.400000 (  2.392590) >> inject(0)                   1.000000   0.000000   1.000000 (  0.999785) >> each_with_index             0.850000   0.000000   0.850000 (  0.846178) >> each                        0.640000   0.000000   0.640000 (  0.639366) >> >> (My apologies if the benchmarks are ragged and unaligned.) >> >> > Just to complete with 1.9 (ruby 1.9.3dev (2011-01-26 trunk 30659) [x86_64-darwin10.6.0]) results: Rehearsal ------------------------------------------------------------- each_with_index.inject(0) 1.220000 0.000000 1.220000 ( 1.220411) inject(0) 0.560000 0.000000 0.560000 ( 0.568007) each_with_index 0.510000 0.010000 0.520000 ( 0.516797) each 0.400000 0.000000 0.400000 ( 0.405471) ---------------------------------------------------- total: 2.700000sec user system total real each_with_index.inject(0) 1.250000 0.000000 1.250000 ( 1.268727) inject(0) 0.570000 0.010000 0.580000 ( 0.582921) each_with_index 0.510000 0.000000 0.510000 ( 0.510591) each 0.390000 0.000000 0.390000 ( 0.401833) Only each_with_index.inject is notably slower, others are similar.