From: Daniel Sheppard Date: 2004-04-16T12:07:35+09:00 Subject: Performance of Hash.inject I was doing some playing with some implementations for Hash#== and ended up with some very counterintuitive timings. I have four equals methods, and I would have expected their performance to run (from best to worst): directInject - stops evaluating == after first bad match, no intermediate arrays keysInject - as above, but must create keys array directCollect - evaluated == for all items all the time, intermediate array of results keysCollect - as above, but must create keys array. Actually running the code however, I ended up with the following timings: keysCollect equal 0.18 not equal 0.11 directCollect equal 0.221 not equal 0.24 directInject equal 0.31 not equal 0.221 keysInject equal 0.24 not equal 0.15 Can anybody shed any light on why it's not performing as I would assume? ----- def keysCollect(hash1, hash2) hash1.size == hash2.size && !(hash1.keys.collect{|k| !hash2[k].nil? && hash1[k] == hash2[k] }.include?(false)) end def directCollect(hash1, hash2) hash1.size == hash2.size && !(hash1.collect{|k,v| hash2[k] == v }.include?(false)) end def directInject(hash1, hash2) hash1.size == hash2.size && hash1.inject(true) { |val, kv| val && hash2[kv[0]] == kv[1] } end def keysInject(hash1, hash2) hash1.size == hash2.size && hash1.keys.inject(true) { |val, k| val && hash1[k] == hash2[k] } end def time(p, *args) time = Time.now 1000.times { p.call *args} Time.now - time end hash1 = Hash.new hash2 = Hash.new xx = 'a' 50.times { hash1[xx] = xx; xx = xx.next } 50.times { hash2[xx] = xx; xx = xx.next } [:keysCollect, :directCollect, :directInject, :keysInject].each { |s| puts s puts "equal #{time(method(s), hash1, hash1)}" puts "not equal #{time(method(s), hash1, hash2)}" } ##################################################################################### This email has been scanned by MailMarshal, an email content filter. #####################################################################################