On Feb 20, 2008, at 15:12 , MenTaLguY wrote:

> # of iterations = 1000000
>                             user     system      total        real
> null_time               0.218000   0.000000   0.218000 (  0.219000)
> split/each/<<+         24.516000   0.140000  24.656000 ( 24.703000)
> split/map/<<+          26.109000   0.172000  26.281000 ( 26.281000)
> split/inject/<<+       30.797000   0.172000  30.969000 ( 31.000000)
>
> Being an FP nut used to using folds, I'm always a little annoyed that
> inject fares so poorly in these things; mainly we're just lacking a
> C implementation of Array#inject.

coming back to this point... what do you mean by we're missing a C  
impl of Array#inject? Granted, the impl is on Enumerable, but I  
wouldn't think it would make THAT much of a difference... But I try my  
best not to speculate (ever), so...

(my C coding skills absolutely suck these days, please point out  
improvements)

#!/usr/bin/env ruby -w

require 'benchmark'
require 'ipaddr'
$: << File.expand_path("~/Work/p4/zss/src/RubyInline/dev/lib")
require 'inline'

class Array
   inline do |builder|
     builder.c_raw <<-EOF
       VALUE new_inject(int argc, VALUE *argv, VALUE self) {
         long max = RARRAY(self)->len;
         long i     = argc ? 0       : 1;
         VALUE memo = argc ? argv[0] : RARRAY(self)->ptr[0];

         for (i; i < max; i++) {
           memo = rb_yield_values(2, memo, RARRAY(self)->ptr[i]);
         }

         return memo;
       }
     EOF
   end
end

p "127.0.0.1".split('.').inject(0) { |s,n| (s << 8) + n.to_i }
p "127.0.0.1".split('.').new_inject(0) { |s,n| (s << 8) + n.to_i }

max = (ARGV.shift || 1_000_000).to_i

# # of iterations = 1000000
#                             user     system      total        real
# null_time               0.130000   0.000000   0.130000 (  0.129965)
# split/each/<<          10.940000   0.010000  10.950000 ( 10.968329)
# split/inject/<<        15.280000   0.020000  15.300000 ( 15.330062)
# split/new_inject/<<    15.020000   0.070000  15.090000 ( 15.629343)

puts "# of iterations = #{max}"
Benchmark::bm(22) do |x|
   x.report("null_time") do
     for i in 0..max do
       # do nothing
     end
   end

   x.report("split/each/<<") do
     for i in 0..max do
       ip = 0
       "127.0.0.1".split('.').each { |n| ip = (ip << 8) + n.to_i }
       ip
     end
   end

   x.report("split/inject/<<") do
     for i in 0..max do
       "127.0.0.1".split('.').inject(0) { |s,n| (s << 8) + n.to_i }
     end
   end

   x.report("split/new_inject/<<") do
     for i in 0..max do
       "127.0.0.1".split('.').new_inject(0) { |s,n| (s << 8) + n.to_i }
     end
   end
end