Ruby未来缓冲区?

时间:2015-03-30 10:19:40

标签: ruby multithreading concurrency celluloid

我想获得一堆XML并解析它们。它们有点大。 所以我想我可以在未来这样得到并解析它们:(我目前使用赛璐珞)

country_xml = {}
country_pool = GetAndParseXML.pool size: 4, args: [@connection]
countries.each do |country|
   country_xml[country] = country_pool.future.fetch_xml country
end
countries.each do |country|
xml = country_xml[country]
# Do stuff with the XML!
end

如果它在实际需要之前占用大量内存,那就没问题了。 理想情况下,我希望它可以缓冲3个XML文件停止并等待至少处理1个然后继续。我该怎么办?

2 个答案:

答案 0 :(得分:0)

第一个问题是:什么是占用记忆?我将假设它是受欢迎的XML文档,因为这似乎是我最有可能的。

我认为最简单的方法是创建一个可以获取和处理XML的actor。如果您随后创建了一个由3个这样的参与者组成的池,则一次最多可以处理3个请求。

含糊不清(假设您没有使用Celluloid注册表):

class DoStuffWithCountryXml
    include Celluloid
    exclusive :do_stuff_with_country

    def initialize(fetcher)
        @fetcher = fetcher
    end

    def do_stuff_with_country(country)
        country_xml = fetcher.fetch_xml country
        # Do stuff with country_xml
    end

end

country_pool = GetAndParseXML.pool size: 4, args: [@connection]
country_process_pool = DoStuffWithCountryXml.pool size: 3, args: [country_pool]

countries_futures = countries.map { |c| country_process_pool.future.do_stuff_with_country(c) }

countries_stuff = countries_futures.map { |f| f.value }

请注意,如果这是唯一使用GetAndParseXML的地方,那么池大小可能与DoStuffWithXmlActor相同。

答案 1 :(得分:0)

我根本不会使用Pool。你没有从中受益。很多人似乎觉得一起使用FuturePool是一个好主意,但通常比使用其中一个更糟糕。

在您的情况下,请使用Future ...但您也将受益于即将推出的Multiplexer功能。在此之前,请执行此操作...使用与尝试或建议完全不同的策略:

class HandleXML
    include Celluloid
    def initialize(fetcher)
        @fetcher = fetcher
    end
    def get_xml(country)
        @fetcher.fetch_xml(country)
    end
    def process_xml(country, xml)
        #de Do whatever you need to do with the data.
    end
 end

 def begin_processor(handler, countries, index)
     data = handler.future.get_xml(countries[index])
     index += 1
     data
 end

 limiter = 3 #de This sets your desired limit.
 country_index = 0
 data_index = 0
 data = {}
 processing = []
 handler = HandleXML.new(@connection)

 #de Load up your initial futures.
 limiter.times {
     processing << begin_processor(handler, countries, country_index)
 }

 while data_index < countries.length
     data[countries[data_index]] = processor.shift.value
     handler.process_xml(countries[data_index],data[countries[data_index]])
     #de Once you've taken out one XML set above, load up another.
     if country_index < countries.length
         processing << begin_processor(handler, countries, country_index)
     end
 end

以上只是一个示例,说明如何仅使用Future,一次处理3。我没有运行它可能会有错误,但这个想法已经为你证明了。

代码加载3组Country XML,然后开始处理该XML。一旦它处理了一组XML,它就会加载另一组XML,直到处理完所有国家的XML。