From: Robert Klemme Date: 2006-08-15T16:10:09+09:00 Subject: Re: hash.keys and hash.values --------------030804050006010507080807 Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 7bit On 14.08.2006 21:01, Erik Veenstra wrote: >> Your test doesn't prove higher memory usage for the inject >> version. The problem with the transpose approach is that you >> need an additional copy of the complete hash in mem which is >> not needed for inject. However, inject version is likely to >> cause more GC because of all the two element arrays created. >> You could retest this: >> >> keys, vals = [], [] hash.each {|k,v| keys << k; vals << v} >> >> This should be the most efficient approach - memory and >> performance wise. > > Hihi... ;] > > Remember, both to_a and transpose are implemented in C. Yes, right. Still some remarks - by not using GC you will see the memory used in total but this does not give a realistic result because it omits GC times and it does make a difference whether you only allocate small chunks and release them again or whether you need a copy of the whole data structure in memory, so - memory wise approach "each" is the most efficient - "traditional" is not semantically identical to the other approaches because it's not guaranteed that both are in the same order Some more figures: 08:58:59 [Temp]: ./test2.rb Rehearsal ----------------------------------------------- traditional 1.375000 0.000000 1.375000 ( 1.375000) transpose 11.203000 0.000000 11.203000 ( 11.203000) inject 45.188000 0.000000 45.188000 ( 45.187000) each 20.140000 0.000000 20.140000 ( 20.157000) ------------------------------------- total: 77.906000sec user system total real traditional 1.391000 0.000000 1.391000 ( 1.390000) transpose 11.281000 0.000000 11.281000 ( 11.282000) inject 45.219000 0.000000 45.219000 ( 45.234000) each 19.813000 0.000000 19.813000 ( 19.812000) Cheers robert --------------030804050006010507080807 Content-Type: text/plain; name="test2.rb" Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename="test2.rb" #!/usr/bin/env ruby require 'benchmark' REPEAT = 1_00_000 REP = 10_000 hash = {} 1000.times do |n| hash[n] = n*n end Benchmark.bmbm do |bm| bm.report "traditional" do REP.times do keys = hash.keys values = hash.values end end bm.report "transpose" do REP.times do keys, values = hash.to_a.transpose end end bm.report "inject" do REP.times do keys, values = hash.inject([[],[]]){|(ks,vs),(k,v)| [ks << k, vs << v]} end end bm.report "each" do REP.times do keys, vals = [], [] hash.each {|k,v| keys << k; vals << v} end end end --------------030804050006010507080807--