It was only 13000 records! I ran ruby-prof (for the first time ever) and spend a while looking at the results wondering what they meant :)
One thing I noticed was that there were quite a few bold lines in the result that were in OpenStruct (thanks for making this easy for me ruby-prof).
I concluded that calling OpenStruct in a loop was defining a brand new class and defining all the attr_accessors for each of the keys in the hash... in my reporting case, each row is converting to a hash, and each row has exactl the same keys.
I decided to run a small benchmark with OpenStruct against a class I built that lets you create a Class from a hash, which just adds all the attr_accessors then returns the type, which you can new up with the hash many times over.
class DynamicRow def self.with_keys(keys) result = Class.new result.class_eval do keys.each { |k| attr_accessor k } def initialize(hash) hash.each { |k, v| instance_variable_set :"@#{k}", v } end end result end def self.benchmark require 'benchmark' sample_hash = {:a => "hello", :b => 3} Benchmark.bm do|b| b.report("OpenStruct ") do 50_000.times { OpenStruct.new(sample_hash) } end b.report("DynamicRow ") do row_type = DynamicRow.with_keys(sample_hash.keys) 50_000.times { row_type.new(sample_hash) } end end end end
Running the benchmark gave me some convincing results
user system total real OpenStruct 13.400000 0.080000 13.480000 ( 13.572973) DynamicRow 0.570000 0.010000 0.580000 ( 0.584201)
Well, thats a nice improvement. But the difference there isn't going to bring the processing down that much is it? The other factor I thought might be playing a role was the number of keys, so I increased this from 2 as shown above in sample_hash to 4.
user system total real OpenStruct 25.750000 0.160000 25.910000 ( 26.117587) DynamicRow 0.790000 0.010000 0.800000 ( 0.809647)
So, with OpenStruct, the time taken increases equal to the number of keys.. with DynamicRow it's not so bad.
My report now runs in about 1 minute, instead of most part of an hour.
Hope the experience I've gained today helps someone else :)
Wow, nice analysis, and a good warning for users considering OpenStruct.
ReplyDelete