On 11.06.2007 09:23, Anthony Martinez wrote:
> On Mon, Jun 11, 2007 at 04:05:10PM +0900, Robert Klemme wrote:
>> On 11.06.2007 07:41, Anthony Martinez wrote:
>>> So, I was tinkering with ways to build a hash out of transforming an
> [snip]
>>> Also, I just thought of a similar way to accomplish the same thing:
>>> x.report("zip")      { Hash[ *id_list.zip(id_list.collect {|e| e.object_id})] }
>>> Array#collect! won't work right with this, of course, but it seems to
>>> have equally-bad performance. Is Array#inject just optimized for this,
>>> or something?
>> The reason why you are seeing this (performance as well as timing) is
>> most likely caused by the different approach.  When you use #inject
>> you just create one copy of the Array (the Hash).  When you use
>> #collect you create at least one additional copy of the large array
>> plus a ton of two element arrays.  That's way less efficient
> 
> Ah. This does make sense. Now, I throw in the #zip variant!
> 
>> considering memory usage and GC.  You'll probably see much different
>> results if your input array is much shorter (try with 10 or 100
>> elements).
> 
> Well, the general trend is that any of the non-idiomatic solutions are
> pretty horrible, although the two-bang gets vaguely better than 0 or 1 on
> bigger arrays:
> 
> 1000 elements:
> Rehearsal --------------------------------------------
> inject     0.010000   0.000000   0.010000 (  0.007391)
> non-bang   0.000000   0.000000   0.000000 (  0.006602)
> bang       0.000000   0.000000   0.000000 (  0.008503)
> two-bang   0.010000   0.000000   0.010000 (  0.010136)
> zip        0.790000   0.220000   1.010000 (  1.202124)
> ----------------------------------- total: 1.030000sec
> 
>                user     system      total        real
> inject     0.010000   0.010000   0.020000 (  0.012621)
> non-bang   0.020000   0.000000   0.020000 (  0.022407)
> bang       0.020000   0.000000   0.020000 (  0.019274)
> two-bang   0.020000   0.000000   0.020000 (  0.027521)
> zip        2.240000   0.670000   2.910000 (  5.804656)
> 
> 
> 10000 elements:
> Rehearsal --------------------------------------------
> inject     0.050000   0.010000   0.060000 (  0.079325)
> non-bang   0.140000   0.010000   0.150000 (  0.265995)
> bang       0.150000   0.010000   0.160000 (  0.184713)
> two-bang   0.140000   0.020000   0.160000 (  0.202579)
> zip       77.510000  24.270000 101.780000 (134.493519)
> --------------------------------- total: 102.310000sec
> 
>                user     system      total        real
> inject     0.110000   0.030000   0.140000 (  0.146650)
> non-bang   0.450000   0.020000   0.470000 (  0.526816)
> bang       0.470000   0.020000   0.490000 (  0.583837)
> two-bang   0.440000   0.040000   0.480000 (  0.520914)
> zip      222.910000  69.370000 292.280000 (389.541023)
> 
> 
> Extra-ouch! This is what I get for trying to be clever.

:-)

I'd say figures for the 1000 elements array are not too meaningful.  You 
should probably wrap those tests in a repetition.  And if you are really 
trying to get the fastest solution I'd also try

h = {}
id_list.each {|e| h[e] = e.object_id }

This is usually the fastest in my experience (unless of course the 
timing is dominated by what you do in the block).

Kind regards

	robert