Я пишу сценарий импорта, который обрабатывает файл, который потенциально имеет сотни тысяч строк (файл журнала). Использование очень простого подхода (см. Ниже) заняло достаточно времени и памяти, и я чувствовал, что он может вывести мой MBP в любой момент, поэтому я остановил процесс.
#...
File.open(file, 'r') do |f|
f.each_line do |line|
# do stuff here to line
end
end
В этом файле, в частности, 642 868 строк:
$ wc -l nginx.log /code/src/myimport
642868 ../nginx.log
Кто-нибудь знает более эффективного (память / процессор) способа обработки каждой строки в этом файле?
UPDATE
Код внутри f. each_line
сверху просто сопоставляет регулярное выражение со строкой. Если совпадение не удается, я добавляю строку в массив @skipped
. Если он проходит, я форматирую совпадения в хэш (с ключом «поля» совпадения) и добавляю его в массив @results
.
# 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
Я полностью согласен с тем, что это неэффективный процесс. Я мог бы заставить код внутри convert_to_hash
использовать предварительно вычисленную лямбду вместо того, чтобы каждый раз выяснять вычисления. Думаю, я просто предположил, что проблема была в самой итерации строки, а не в построчном коде.