2010-10-25 19 views
6

我正在研究ruby的并行/异步处理功能并阅读大量文章和博文。我通过EventMachine的,纤维,Revactor的,区域环境影响评价,等等,等等看着不幸的是,我没能找到这个非常简单的用例的简单,有效的(和非IO-阻断)解决方案:Ruby并发/异步处理(使用简单用例)

File.open('somelogfile.txt') do |file| 
    while line = file.gets  # (R) Read from IO 
    line = process_line(line) # (P) Process the line 
    write_to_db(line)   # (W) Write the output to some IO (DB or file) 
    end 
end 

是你可以看到,我的小脚本执行三个操作[R),过程P)& W¯¯)。让我们假设 - 为了简单 - 每个操作需要的时间正好是1单位(例如10毫秒),因此当前的代码会做这样的事情(5号线):

Time:  123456789(15 units in total) 
Operations: RPWRPWRPWRPWRPW 

但是,我想它做的事像这样:

Time:  1234567 (7 units in total) 
Operations: RRRRR 
      PPPPP 
       WWWWW 

显然,我可以运行三个过程(读取器,处理器&作家),并通过读出从读取器线到处理器队列,然后通过加工线进入作家队列(经由例如RabbitMQ的所有协调) 。但是,用例非常简单,它感觉不对。

任何有关如何做到这一点的线索(无需从Ruby切换到Erlang,Closure或Scala)?

+1

是否应该按照读取的顺序调用写入? – 2010-10-25 12:41:35

+0

不,这就是他们可以完全异步的整点。 – Dim 2010-10-27 07:58:48

回答

1

退房桃子(http://peach.rubyforge.org/)。做一个平行的“每一个”不能简单一些。但是,正如文档所述,您需要在JRuby下运行才能使用JVM的本地线程。

查看Jorg Mittag对this SO question的回复,详细了解各种Ruby解释器的多线程功能。

+0

嗯,桃子不是我正在寻找的东西。我不想并行运行RPW,我想将这3个任务分开并异步运行。乔格米塔格的回应给出了一个很好的介绍。我非常了解所提供的选项,但他们似乎都没有解决我的问题。 – Dim 2010-10-27 08:09:17

3

如果您需要它真正平行(来自单个进程),我相信您必须使用JRuby才能获得真正的本机线程并且不需要GIL。

您可以使用类似于DRb的方法将处理分配到多个进程/核心,但对于您的用例,这有点多。相反,你可以尝试有多个进程使用管道通信:

$ cat somelogfile.txt | ruby ./proc-process | ruby ./proc-store 

在这种情况下每一块都是它自己的进程可以并行运行,但使用标准输入/输出的通信。这可能是解决问题最简单(最快)的方法。

# proc-process 
while line = $stdin.gets do 
    # do cpu intensive stuff here 
    $stdout.puts "data to be stored in DB" 
    $stdout.flush # this is important 
end 

# proc-store 
while line = $stdin.gets do 
    write_to_db(line) 
end 
+1

我以为Ruby 1.9的GIL允许你在一个线程中执行CPU资源,而另一个线程执行I/O - 也就是说,它只禁止两个线程执行CPU资源。 – 2010-10-25 22:47:53

+0

你在说纤维吗?我对Fibers的理解有限,不是每个线程都有共享的CPU时间,而是代码明确地将处理转交给可以处理阻塞IO操作并立即返回到调用代码的Fibre。这样可以减少等待的时间,但我认为这不会让您在每个进程中跨越多个CPU。我认为GIL意味着只有一个执行线程可以在任何时间点运行。 http://www.igvita.com/2009/05/13/fibers-cooperative-scheduling-in-ruby/ – JEH 2010-10-25 23:57:07

+2

使用管道是一个很好的解决方案,可以将问题分成3个独立的进程,但它不是异步的。这实际上是一种“Ruby解决方法”,因此在更大的应用程序范围内实现起来相当困难。我上面概述的“问题”是IO驱动处理的一个简单例子。我想了解Ruby在这方面的能力以及它可能缺乏的内容。 – Dim 2010-10-27 08:00:19