我有一個由文件名組成的大文件(數百個megs),每行一個。用紅寶石一次讀取一行文件N行
我需要遍歷文件名列表,併爲每個文件名分出一個進程。我一次最多需要8個分叉進程,我不想一次將整個文件名列表讀入RAM。
我甚至不知道從哪裏開始,任何人都可以幫助我?
我有一個由文件名組成的大文件(數百個megs),每行一個。用紅寶石一次讀取一行文件N行
我需要遍歷文件名列表,併爲每個文件名分出一個進程。我一次最多需要8個分叉進程,我不想一次將整個文件名列表讀入RAM。
我甚至不知道從哪裏開始,任何人都可以幫助我?
這聽起來像Process module將對此任務有用。這裏的東西我趕緊扔在一起作爲一個起點:
include Process
i = 0
for line in open('files.txt') do
i += 1
fork { `sleep #{rand} && echo "#{i} - #{line.chomp}" >> numbers.txt` }
if i >= 8
wait # join any single child process
i -= 1
end
end
waitall # join all remaining child processes
輸出:
hello goodbye test1 test2 a b c d e f g $ ruby b.rb $ cat numbers.txt 1 - hello 3 - 2 - goodbye 5 - test2 6 - a 4 - test1 7 - b 8 - c 8 - d 8 - e 8 - f 8 - g
其工作原理是:
File.foreach("large_file").each_slice(8) do |eight_lines|
# eight_lines is an array containing 8 lines.
# at this point you can iterate over these filenames
# and spawn off your processes/threads
end
這不會起作用,因爲它會產生N/8個進程(N是文件中的行數)。你可以改爲'each_slice(N/8)',但這需要將整個文件加載到一個數組中,這是OP想要避免的。 –
我假設在循環內,OP會產生8個進程並在繼續之前等待它們。我在鏈接可枚舉的方法,所以它不會一次讀取整個文件。 –
啊,對不起。但是這種方式效率不高,因爲程序必須等待所有八個過程才能在接下來的八個產卵之前完成,而且您將只有部分時間具有100%的流程利用率。在極端情況下,您可以快速完成七個過程,並且您必須等待一個長時間運行的左側。 –
這裏是馬克的解決方案包裹起來作爲ProcessPool
類,可能是有幫助的它周圍的(和請糾正我,如果我犯了一些錯誤):
class ProcessPool
def initialize pool_size
@pool_size = pool_size
@free_slots = @pool_size
end
def fork &p
if @free_slots == 0
Process.wait
@free_slots += 1
end
@free_slots -= 1
puts "Free slots: #{@free_slots}"
Process.fork &p
end
def waitall
Process.waitall
end
end
pool = ProcessPool.new 8
for line in open('files.txt') do
pool.fork { Kernel.sleep rand(10); puts line.chomp }
end
pool.waitall
puts 'finished'
標準庫文檔Queue已有
require 'thread'
queue = Queue.new
producer = Thread.new do
5.times do |i|
sleep rand(i) # simulate expense
queue << i
puts "#{i} produced"
end
end
consumer = Thread.new do
5.times do |i|
value = queue.pop
sleep rand(i/2) # simulate expense
puts "consumed #{value}"
end
end
consumer.join
雖然我確實發現它有點冗長。
維基百科將其描述爲一個thread pool pattern
ARR = IO.readlines(「文件名」)
這個問題的標題無關與問題本身。 –