在Ruby的许多类实例中记忆数据的好方法是什么?
考虑:生成数据的对象的许多实例。 每次运行只生成一次数据会很棒。
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
HighOfNPeriods
不同实例有不同的params
和不同的@source_data
。
以下是指标的使用方法:
class Strategy attr_accessor :indicators def initialize params ... end
从Strategy
调用HighOfNPeriods.generate_data
方法。 每个Strategy
都会获得HighOfNPeriods
的新实例,因此不可能将其作为某种全局值来实现。 除此之外,它不应该是全球性的。
unless @indicator_data
不起作用,因为需要在HighOfNPeriods
许多实例之间共享数据。
所以,问题是:
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?
一种解决方案是使用ActiveRecord存储数据,但这不是我想要的方式,因为:
- 并非所有生成的数据都可以提前生成,因为params的排列太多。 更有意义的是看它之前是否已生成,然后根据需要生成(并保存)。
- 生成数据不需要很长时间。 它可以生成一次并且每次运行使用数百次。
- 从对象内部访问数据比从数据库中提取数据更快。
Ruby 1.9.3
创建一个类变量@@indicator_data
,它是一个哈希,以[@params,@source_data]
为键[@params,@source_data]
@indicator_data
为值。 然后,在创建时,在@@indicator_data[[@params,@source_data]]
。
class HighOfNPeriods < Indicator @@indicator_data = {} def generate_data @indicator_data = @@indicator_data[[@params, @source_data]] ||= DataStream.new ... end end
如果你不能在实例级别上记忆它,那么升级一级并使用类实例。
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