Я пишу сценарий импорта, который обрабатывает файл с потенциально сотнями тысяч строк (файл журнала). Использование очень простого подхода (см. Ниже) заняло достаточно времени и памяти, и я чувствовал, что в любой момент это может привести к потере 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
использовать предварительно вычисленную лямбду вместо того, чтобы вычислять вычисления каждый раз. Наверное, я просто предположил, что проблема заключалась в самой итерации строки, а не в коде для каждой строки.