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