2015-01-06 96 views
2

我必须从不同的来源查询一组模型对象。每个源都会返回一个带哈希像的对象的数组,但同一模型的布局(LogDoc)并不相同。红宝石阵列适配器

我的第一种方法是将查询结果对象包装到一个数组适配器中,该适配器基本上转换了每个提取的元素,每个元素都在#每个块中。这是我想出了:

class MongoQueryAdapter 
    extend Forwardable 

    def initialize(mongo_query) 
    @query_rows = mongo_query 
    ... 
    end 

    def_delegators :@query_rows, ... 

    def each(&block) 
    @query_rows.each do |raw| 
     log = LogDoc.new raw 
     block.call(log) 
    end 
    end 
end 

这是我认为的模式更适合我的使用情况,但我关心的性能,因为我听说,比起产量block.call是低效

是否可以使用收益率?还是性能影响真的值得考虑?

回答

3

您可以只需yield而不是调用该块,不需要其他更改。

def each 
    if block_given? 
    @query_rows.each do |raw| 
     yield LogDoc.new(raw) 
    end 
    else 
    # return Enumerator or raise 
    end 
end 

看代码,我觉得你其实可以简化这个有点:

def each(&block) 
    @query_rows.map { |raw| LogDoc.new(raw) }.each(&block) 
end 

是的,yield往往要快得多:

Calculating ------------------------------------- 
     bench_block 30.600k i/100ms 
     bench_yield 42.073k i/100ms 
------------------------------------------------- 
     bench_block 768.311k (± 6.0%) i/s -  3.825M 
     bench_yield  3.917M (± 2.8%) i/s -  19.564M 
+0

,你可以发表主旨你如何做基准? – SystematicFrank

+0

@SystematicFrank请参阅https://gist.github.com/jiripospisil/0774b7767d252d871992。你可能会得到更高的数字,因为我在一台相当老的笔记本电脑上运行这个数字。 –

+1

谢谢!良好的分析技能是一个往往被大大低估的金矿 – SystematicFrank