你介意我告诉我是否在Ruby中正确地进行了线程化吗?
我有一个数组items
,我希望在16个线程中处理,等待所有线程完成,然后再做更多工作。
这是我的代码;
chunks = items.each_slice(items.count / 16).to_a
puts chunks.length
queue = Queue.new
semaphore = Mutex.new
threads = []
puts '[+] Building Queue'
chunks.each do |chunk|
threads << Thread.new {
chunk.each do |item|
array = []
metadata.each do |m|
array << m.evaluate(item) rescue ''
end
semaphore.synchronize {
queue << array.join(20.chr)
}
end
}
end
puts '[+] Running threads'
threads.each{|t|t.join; puts 'Threads done'}
#Do more work here, queue should be fully populated
puts '[+] Writing to file'
File.open('E:/Export.dat', 'wt', encoding: 'UTF-16LE') do |f|
until queue.empty?
unit = queue.pop(true) rescue nil
if unit
f.puts unit
end
end
end
代码运行,但是没有给出我期望的线程性能,这是正确的吗?
由于
答案 0 :(得分:0)
您不太可能看到性能提升,因为每个线程都阻止将结果添加到队列中。 Queue类是线程安全的,因此您不需要Mutex来保护它。
为了使多线程代码更好地工作,您希望每个线程尽可能独立地运行。以下实施应改善性能。
chunks = items.each_slice(items.count / 16).to_a
puts chunks.length
queue = Queue.new
threads = []
puts '[+] Building Queue'
chunks.each do |chunk|
threads << Thread.new do
chunk.each do |item|
array = []
metadata.each do |m|
array << m.evaluate(item) rescue ''
end
queue << array.join(20.chr)
end
end
end
puts '[+] Running threads'
threads.each{|t|t.join; puts 'Threads done'}
#Do more work here, queue should be fully populated
puts '[+] Writing to file'
File.open('E:/Export.dat', 'wt', encoding: 'UTF-16LE') do |f|
until queue.empty?
unit = queue.pop(true) rescue nil
if unit
f.puts unit
end
end
end
您还需要衡量代码中瓶颈的位置。简单的计时器(开始和结束时间之间的差异)很好。如果元数据的评估需要10毫秒的线程和100毫秒没有,并且写入文件需要1000毫秒。那么你不会注意到多线程的巨大差异。