From: redstun Date: 2011-01-27T09:42:01+09:00 Subject: Re: Enumerable.inject_with_index? --001485f6d05096cb5e049ac937d3 Content-Type: text/plain; charset=UTF-8 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.) > > --001485f6d05096cb5e049ac937d3--