Как быстро нарезать и нарезать большие файлы данных? - PullRequest
5 голосов
/ 24 сентября 2008

Я хотел бы довольно быстро и эффективно нарезать и нарезать большие файлы данных, вплоть до концерта. Если я использую что-то вроде UNIX «CUT», это очень быстро, даже в среде CYGWIN.

Я пытался разработать и сравнить различные сценарии Ruby для обработки этих файлов, и всегда получал ледниковые результаты.

Что бы вы сделали в Ruby, чтобы сделать эту собаку не такой медленной?

Ответы [ 4 ]

2 голосов
/ 24 сентября 2008

Этот вопрос напоминает мне проект Wide Finder Тима Брея . Самый быстрый способ, которым он мог прочитать лог-файл Apache, используя Ruby и выяснить, какие статьи были выбраны больше всего, был с этим сценарием:

counts = {}
counts.default = 0

ARGF.each_line do |line|
   if line =~ %r{GET /ongoing/When/\d\d\dx/(\d\d\d\d/\d\d/\d\d/[^ .]+) }
     counts[$1] += 1
   end
end

keys_by_count = counts.keys.sort { |a, b| counts[b] <=> counts[a] }
keys_by_count[0 .. 9].each do |key|
    puts "#{counts[key]}: #{key}"
end

Этому коду потребовалось 7,5 секунд ЦП, по прошествии 13½ секунд, чтобы обработать миллион и изменить записи, примерно на четверть гигабайта, на прошлогодней PowerBook с частотой 1,67 ГГц.

1 голос
/ 24 сентября 2008

Почему бы не объединить их вместе - используя cut, чтобы делать то, что он делает лучше всего, и ruby, чтобы обеспечить добавление клея / ценности с результатами CUT? Вы можете запускать сценарии оболочки, помещая их в кавычки следующим образом:

puts `cut somefile > foo.fil`
# process each line of the output from cut
f = File.new("foo.fil")
f.each{|line|
}
1 голос
/ 24 сентября 2008

Я предполагаю, что ваши реализации Ruby читают весь файл перед обработкой. Обрезка Unix работает, читая вещи по одному байту за раз и немедленно сбрасывая в выходной файл. Конечно, требуется некоторая буферизация, но не более нескольких килобайт.

Мое предложение: попробуйте выполнить обработку на месте с как можно меньшим количеством подкачки или возврата.

0 голосов
/ 24 сентября 2008

Я сомневаюсь, что проблема в том, что ruby ​​читает весь файл в памяти. Посмотрите на использование памяти и диска при выполнении команды для проверки.

Я предполагаю, что основная причина в том, что cut написан на C и делает только одну вещь, поэтому он, вероятно, скомпилирован до самого металла. Вероятно, это не намного больше, чем вызов системных вызовов.

Однако версия ruby ​​делает много вещей одновременно. Вызов метода в ruby ​​намного медленнее, чем вызов функции C.

Помните, старость и предательство побеждают молодость и мастерство в Unix: http://ridiculousfish.com/blog/archives/2006/05/30/old-age-and-treachery/

...