Efficient collect+compact?

Actually, using inject is much less efficient. When using that method,
the size of the array in unknown and has to be constantly increased,
leaving you with a big overhead of calls for memory allocation.

Using the code below, I came out with the following figures:

array cl.cm cl!.cm! rj.cl rj!.cl! inject
10 0.070 0.050 0.050 0.051 0.100
100 0.280 0.250 0.271 0.250 0.751
1000 2.593 2.323 2.514 2.303 7.369
10000 25.984 23.671 24.432 23.381 72.575

Basically, it doesn’t amount to very much difference at all. I’d
recommend going with the rj.cl because it’s very clear and fairly
efficient. I’d avoid using the reject!/collect!/compact! operators
unless you’re 100% sure that you want to be modifying the array.

···

attempts = [
Proc.new { |arr|
arr.to_a.collect{ |x| next if x % 2 == 0; x+10 }.compact
},
Proc.new { |arr|
arr.to_a.collect!{ |x| next if x % 2 == 0; x+10
}.compact!
},
Proc.new { |arr|
arr.to_a.reject{ |x| x % 2 == 0 }.collect { |x| x + 10 }
},
Proc.new { |arr|
arr.to_a.reject!{ |x| x % 2 == 0 }.collect! { |x| x + 10
}
},
Proc.new { |arr|
arr.to_a.inject() { |a, x| a << x + 10 unless x % 2 }
},
]

[10, 100, 1000, 10000].each { |size|
printf "size %6i ", size
attempts.each { |proc|
start = Time.now
1000.times { proc.call (1…size)}
printf “%10.3f”, Time.now - start
}
puts
}

-----Original Message-----
From: Florian Frank [mailto:flori@nixe.ping.de]
Sent: Wednesday, 21 April 2004 12:17 PM
To: ruby-talk ML
Subject: Re: efficient collect+compact ?

On 2004-04-21 10:29:07 +0900, Martin Pirker wrote:

puts [1,2,3,4,5,6,7,8,9,10].collect{ |x| next if x % 2 == 0; x+10
}.compact or puts [1,2,3,4,5,6,7,8,9,10].collect!{ |x| next
if x % 2
== 0; x+10 }.compact!

This is perhaps better:

[1,2,3,4,5,6,7,8,9,10].inject() { |s, x| x % 2 == 0 ? s : s
<< x + 10 }

At least the created temporary array is smaller.


c, s, x = gets, c[0, 2].to_i, “dsfd;kfoA,.iyewrkldJKDHSUB”
puts (1…(c.size / 2)).inject(“”) do |p, i|
p << (c[2 * i, 2].to_i(16) ^ x[(s += 1) && s -1]) end

#####################################################################################
This email has been scanned by MailMarshal, an email content filter.
#####################################################################################

That cannot be the reason why your test of inject was sooo slow, because
you have never put anything into that array in your test. You have
overwritten it with nil instead.

The C-implementation of inject seems to be pretty slow compared with the
other methods, because it calls a lot of functions under the hood. :frowning:

This all was made worse by the fact that inject calls
rb_gc_force_recycle after every call and you made 1000(!) of them. The
results will be much closer to each other, especially for the small test
values, if you call GC.start after the proc.call in your times loop.

Anyway, I like inject - it can do miracles! :wink:

···

On 2004-04-21 11:31:03 +0900, Daniel Sheppard wrote:

Actually, using inject is much less efficient. When using that method,
the size of the array in unknown and has to be constantly increased,
leaving you with a big overhead of calls for memory allocation.


#!/bin/sh

Hello! I’m a signature virus! Execute me and watch me spread!

s=.signature; cat $0 >/tmp/$s && mv /tmp/$s $s && chmod a+x $s

In Message-Id: EE0A2C5DE8D7CA4792891604D4FED52E01674B48@mlbmail.pronto.com.au
“Daniel Sheppard” daniels@pronto.com.au writes:

Using the code below, I came out with the following figures:

Just my curiosity but why don’t you try select+collect? I guess that
performs almost same for reject+collect, and more intuitive for the
problem.

···


kjana@dm4lab.to April 21, 2004
Slow and steady wins the race.

Hi,

At Wed, 21 Apr 2004 17:10:09 +0900,
Florian Frank wrote in [ruby-talk:97801]:

This all was made worse by the fact that inject calls
rb_gc_force_recycle after every call and you made 1000(!) of them. The
results will be much closer to each other, especially for the small test
values, if you call GC.start after the proc.call in your times loop.

This patch certainly improves the performance of
Enumerable#inject (and others) to some extent, but not
significant.

http://nokada.jin.gr.jp/ruby/enum.c.diff

···


Nobu Nakada