В ruby, файл.readlines.каждый не быстрее файла.открыть.каждая строчка, почему?
просто проанализировать мой журнал iis (бонус: случилось знать, что iislog закодирован в ASCII, errrr..)
вот мой код Рубина
1.readlines
Dir.glob("*.log").each do |filename|
File.readlines(filename,:encoding => "ASCII").each do |line|
#comment line
if line[0] == '#'
next
else
line_content = line.downcase
#just care about first one
matched_keyword = keywords.select { |e| line_content.include? e }[0]
total_count += 1 if extensions.any? { |e| line_content.include? e }
hit_count[matched_keyword] += 1 unless matched_keyword.nil?
end
end
end
2.открыть
Dir.glob("*.log").each do |filename|
File.open(filename,:encoding => "ASCII").each_line do |line|
#comment line
if line[0] == '#'
next
else
line_content = line.downcase
#just care about first one
matched_keyword = keywords.select { |e| line_content.include? e }[0]
total_count += 1 if extensions.any? { |e| line_content.include? e }
hit_count[matched_keyword] += 1 unless matched_keyword.nil?
end
end
end
"readlines" читать весь файл в mem, почему "открыть" всегда немного быстрее наоборот?? Я тестировал его пару раз на Win7 Ruby1.9.3
1 ответов
и readlines
и open.each_line
читать файл только один раз. И Ruby будет делать буферизацию на объектах ввода-вывода, поэтому он будет читать данные блока (например, 64KB) с диска каждый раз, чтобы минимизировать затраты на чтение диска. На шаге чтения диска должна быть небольшая разница во времени.
когда вы называете readlines
, Ruby создает пустой массив []
и неоднократно считывает строку содержимого файла и помещает ее в массив. И, наконец, он вернет массив, содержащий все строки файл.
когда вы называете each_line
, Ruby читает строку содержимого файла и передает ее вашей логике. Когда вы закончили обработку этой строки, ruby читает другую строку. Он многократно считывает строки, пока в файле больше нет содержимого.
разница между двумя методами заключается в том, что readlines
необходимо добавить строки в массив. Когда файл большой, Ruby может потребоваться дублировать базовый массив (уровень C), чтобы увеличить его размер на один или несколько раз.
копание в источнике,readlines
осуществляется io_s_readlines
которых звонки rb_io_readlines
. rb_io_readlines
звонки rb_io_getline_1
чтобы получить линию и rb_ary_push
для ввода результата в возвращаемый массив.
each_line
осуществляется rb_io_each_line
которых звонки rb_io_getline_1
чтобы получить строку так же, как readlines
и дайте строку вашей логике с rb_yield
.
таким образом, нет необходимости хранить результаты строки в растущем массиве для each_line
, нет изменение размера массива, проблема копирования.