Consider: many instances of an object that generates data. It would be great to only generate that data once per run.
class HighOfNPeriods < Indicator
def generate_data
@indicator_data = DataStream.new
(0..@source_data.data.count - 1).each do |i|
if i < @params[:n_days]
...
@indicator_data.add one_data
end
end
There are different instances of HighOfNPeriods
with different params
and different @source_data
.
Here is how the indicator is used:
class Strategy
attr_accessor :indicators
def initialize params
...
end
The method HighOfNPeriods.generate_data
is called from within Strategy
. Each Strategy
gets a new instance of HighOfNPeriods
, so it's not possible to pull it out as some kind of global value. Besides that, it should not be global.
unless @indicator_data
wouldn't work because the data needs to be shared across many instances of HighOfNPeriods
.
So, the question is:
What is a good way to memoize the instance variable `indicator_data`
or the object `HighOfNPeriods` when there are many different instances,
some of which have different data?
One solution is to store the data using ActiveRecord, but that's not really the way I want to do it at this time because:
Ruby 1.9.3
If you can't memoize it on instance level, go one level up and use class instance.
class Foo
# I used *args here for simplicity of the example code.
def generate_data *args
if res = self.class.cache[args]
puts "Data in cache for #{args.inspect} is #{res}"
return res
end
puts "calculating..."
p1, p2 = args
res = p1 * 10 + p2
self.class.cache[args] = res
res
end
def self.cache
@cache ||= {}
@cache
end
end
puts Foo.new.generate_data 1, 2
puts Foo.new.generate_data 3, 4
puts Foo.new.generate_data 1, 2
# >> calculating...
# >> 12
# >> calculating...
# >> 34
# >> Data in cache for [1, 2] is 12
# >> 12
Make a class variable @@indicator_data
that is a hash with [@params,@source_data]
as the key and the @indicator_data
as the value. Then, at creation, do a memoization on @@indicator_data[[@params,@source_data]]
.
class HighOfNPeriods < Indicator
@@indicator_data = {}
def generate_data
@indicator_data = @@indicator_data[[@params, @source_data]] ||= DataStream.new
...
end
end
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With