【发布时间】:2013-07-09 13:28:04
【问题描述】:
我正在编写一个程序,将数据从四个 XML 文件加载到四个不同的数据结构中。它有这样的方法:
def loadFirst(year)
File.open("games_#{year}.xml",'r') do |f|
doc = REXML::Document.new f
...
end
end
def loadSecond(year)
File.open("teams_#{year}.xml",'r') do |f|
doc = REXML::Document.new f
...
end
end
etc...
我原本只是用一个线程,一个接一个地加载文件:
def loadData(year)
time = Time.now
loadFirst(year)
loadSecond(year)
loadThird(year)
loadFourth(year)
puts Time.now - time
end
然后我意识到我应该使用多个线程。我的期望是,在单独的线程上从每个文件加载的速度几乎是顺序加载的四倍(我有一台配备 i7 处理器的 MacBook Pro):
def loadData(year)
time = Time.now
t1 = Thread.start{loadFirst(year)}
t2 = Thread.start{loadSecond(year)}
t3 = Thread.start{loadThird(year)}
loadFourth(year)
t1.join
t2.join
t3.join
puts Time.now - time
end
我发现使用多线程的版本实际上比另一个慢。这怎么可能?差别在 20 秒左右,每次大约需要 2 到 3 分钟。
线程之间没有共享资源。每个都打开不同的数据文件并将数据加载到与其他数据不同的数据结构中。
【问题讨论】:
-
您使用的是哪个版本的语言和哪个虚拟机?我相信大多数 ruby 运行时仍在使用“绿色”线程(阅读:实际上不是多线程,而是在单个线程中模拟)
-
经典 ruby 有一个 GIL - 你不会得到计算并行性,因为通常一次只运行一个线程(IO 和其他一些情况除外)。用 jruby 试试你的代码
-
也许您可以编写程序打印出每个线程开始和结束时的当前时间(必要时最多使用 sec)。然后你会更好地了解正在发生的事情。特别是,你应该能够看到第n+1个线程是否在第n个线程结束之前开始。
-
请参阅this link 了解有关各种 ruby 运行时中线程实现的详细信息。您实际上并没有使用 Ruby 1.9.3 获得并发执行。这是一门很棒的语言,但在某些方面实现还有些年轻。
-
我的猜测是有多个线程会导致某种交换争用被添加。我想你可以分析它......
标签: ruby multithreading performance concurrency