Каковы наиболее эффективные идиомы для потоковой передачи данных с диска с постоянным использованием пространства? - PullRequest
2 голосов
/ 08 декабря 2009

Описание проблемы

Мне нужно для потоковой передачи больших файлов с диска. Предположим, что файлы больше, чем помещаются в памяти. Кроме того, предположим, что я делаю некоторые вычисления с данными, и результат достаточно мал, чтобы поместиться в памяти. В качестве гипотетического примера предположим, что мне нужно вычислить сумму md5 для файла объемом 200 ГБ, и мне нужно сделать это с гарантиями того, сколько оперативной памяти будет использовано.

В итоге:

  • Требуется постоянное пространство
  • Быстро, насколько это возможно
  • Предположим, очень большие файлы
  • Результат помещается в память

Вопрос

Каковы самые быстрые способы чтения / потоковой передачи данных из файла с использованием постоянного пространства?

Идеи, которые у меня были

Если файл был достаточно мал, чтобы поместиться в памяти, то mmap в системах POSIX будет очень быстрым, к сожалению, это не тот случай. Есть ли какое-либо преимущество в производительности при использовании mmap с небольшим размером буфера для буферизации последовательных фрагментов файла? Преобладают ли системные накладные расходы на перемещение буфера mmap вниз по файлу, какие-либо преимущества или я должен использовать фиксированный буфер, в который я прочитал с fread?

Ответы [ 3 ]

3 голосов
/ 08 декабря 2009

Я бы не был уверен, что mmap будет очень быстрым (где очень быстрый определяется как значительно более быстрый, чем fread).

Grep использовал для использования mmap, но переключился обратно на fread. Одной из причин была стабильность (странные вещи случаются с mmap, если файл сжимается во время отображения или возникает ошибка ввода-вывода). Эта страница обсуждает некоторые истории об этом.

Вы можете сравнить производительность вашей системы с параметром --mmap для grep. В моей системе разница в производительности файла размером 200 ГБ незначительна, но ваш пробег может отличаться!

Короче, я бы использовал fread с буфером фиксированного размера. Проще кодировать, легче обрабатывать ошибки и почти наверняка будет достаточно быстро.

0 голосов
/ 08 декабря 2009

MJV правильно. Вы можете использовать двойной буфер и перекрывающийся ввод / вывод. Таким образом, ваш хруст и чтение с диска могут происходить одновременно. Затем я бы профилировал или суммировал хруст, чтобы сделать его как можно быстрее. Если повезет, он будет быстрее, чем ввод-вывод, поэтому вы в конечном итоге будете выполнять ввод-вывод на максимальной скорости без пауз. Затем такие вещи, как фрагментация файла, входят в картину.

0 голосов
/ 08 декабря 2009

В зависимости от языка, который вы используете, цикл типа fread (), подобный C, основанный на файле, для которого вы объявили определенный размер буфера, будет требовать именно этого размера буфера, не больше, не меньше.

Обычно мы выбираем размер буфера от 4 до 128 кБайт, при больших буферах прирост будет незначительным.

Если производительность была чрезвычайно важна, с относительно небольшим выигрышем (и с риском переизобретения чего-либо), можно рассмотреть возможность использования двухпотоковой реализации, при которой один поток читает файл в виде набора из двух буферов, и другой поток выполняет вычисления последовательно в одном из буферов одновременно. Таким образом, задержки доступа к диску могут быть устранены.

...