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.
gegroet,
Erik V. - http://www.erikveen.dds.nl/
PS: The circumstances are a bit different, compared to my
previous post. Different environment, different numbers.
···
----------------------------------------------------------------
$ cat test.rb
require "ev/ruby"
GC.disable
hash = {}
1000.times do |n|
hash[n] = n*n
end
case ARGV.shift
when "traditional"
bm do
1000.times do
keys = hash.keys
values = hash.values
end
end
when "transpose"
bm do
1000.times do
keys, values = hash.to_a.transpose
end
end
when "inject"
bm do
1000.times do
keys, values = hash.inject([,]){|(ks,vs),(k,v)| [ks <<
k, vs << v]}
end
end
when "inject2"
bm do
1000.times do
keys, vals = ,
hash.each {|k,v| keys << k; vals << v}
end
end
else
raise "uh?"
end
puts meminfo
$ ruby test.rb traditional
VmSize: 14296 kB
CPU ELAPSED COUNT CPU/COUNT LABEL
0.300000 0.310413 1 0.300000 "test.rb:13"
$ ruby test.rb transpose
VmSize: 58280 kB
CPU ELAPSED COUNT CPU/COUNT LABEL
0.760000 0.861536 1 0.760000 "test.rb:20"
$ ruby test.rb inject
VmSize: 146676 kB
CPU ELAPSED COUNT CPU/COUNT LABEL
3.190000 3.331201 1 3.190000 "test.rb:26"
$ ruby test.rb inject2
VmSize: 55244 kB
CPU ELAPSED COUNT CPU/COUNT LABEL
1.690000 1.819222 1 1.690000 "test.rb:32"
----------------------------------------------------------------