Yüz binlerce satır (günlük dosyası) içeren bir dosyayı işleyen bir alma komut dosyası yazıyorum. Çok basit bir yaklaşım kullanarak (aşağıda) MBP'yi her an alabileceğimi hissettiğim zaman ve bellek aldım, bu yüzden süreci öldürdüm. Ruby'de büyük metin dosyalarını verimli bir şekilde nasıl ayrıştırabilirim?
#...
File.open(file, 'r') do |f|
f.each_line do |line|
# do stuff here to line
end
end
özellikle Bu dosya 642868 hatları vardır:
$ wc -l nginx.log /code/src/myimport
642868 ../nginx.log
herkes bu dosyadaki her satır işlemek için daha verimli (bellek/cpu) yol biliyor mu?
GÜNCELLEME
yukarıdan f.each_line
iç kod basitçe çizgisine karşı bir normal ifade eşleştirme. Eşleşme başarısız olursa, satırı @skipped
dizisine ekliyorum. Geçerse, eşleşmeleri bir eşiğe (eşleşmenin "alanları" tarafından girilen) biçimlendirir ve onu bir @results
dizisine eklerim.
# regex built in `def initialize` (not on each line iteration)
@regex = /(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}) - (.{0})- \[([^\]]+?)\] "(GET|POST|PUT|DELETE) ([^\s]+?) (HTTP\/1\.1)" (\d+) (\d+) "-" "(.*)"/
#... loop lines
match = line.match(@regex)
if match.nil?
@skipped << line
else
@results << convert_to_hash(match)
end
Bunun için verimsiz bir süreç olana tamamen açıkım. convert_to_hash
'un içindeki kodu, her seferinde hesaplamayı bulmak yerine önceden oluşturulmuş bir lambda kullanabiliyordum. Sanırım sadece satır yinelemenin kendisinin sorun değil, satır kodunun kendisi olduğunu varsaydım.
Bir göz atın en bellek verimli yolu, her_line ile bunu yapıyoruz. Dosyayı daha hızlı olan bloklarda okuyabiliyordunuz, daha sonra blok sınırlarını aşan kısmi yüklü satırları yeniden birleştirmek için tek tek satırları kapmak için 'String # lines' kullanın. Çizgileri ayırmak ve kırık olanları yeniden birleştirmek için bir yıkama olur. –