Запись данных в файл: fflush () занимает много времени - PullRequest
3 голосов
/ 07 июля 2011

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

Теперь подводный камень в том, что пока я записываю данные в файл, другим потокам могут понадобиться эти «буферизованные» данные, и поэтому мне приходится очищать поток файлов каждый раз, когда я что-то записываю в него.Точно, данные - это видеокадры, которые я буферизирую как предварительно записанные данные (например, TiVo), и другие потоки могут или не могут захотеть записать их в любой данный момент времени, но когда они это делают, они fread из файлаи обработать кадры.

В общем случае комбо fwrite - fflush занимает около 150 человек, но иногда (и довольно регулярно) комбо занимает более 1,5 секунд.Я не могу себе этого позволить, поскольку мне приходится обрабатывать кадры в режиме реального времени.

У меня здесь много вопросов:

  1. Правильно ли мой подход к буферизации данных в файле?Какие у меня есть альтернативы?

  2. Есть идеи, почему в некоторых случаях операция fwrite-fflush иногда занимает больше времени?Обратите внимание, что он возвращается к 150 мкс после 1,5 секунд.

Ответы [ 2 ]

2 голосов
/ 07 июля 2011

Что касается # 2: большинство современных файловых систем используют подход btree для управления количеством каталогов и узлов данных в современных огромных HD. Как и у всех btrees, их иногда нужно сбалансировать. Пока это происходит, никаких изменений не должно произойти, поэтому система блокируется. Как правило, это не имеет большого значения из-за огромного объема кэша ОС, но вы находитесь в критическом случае, когда это больно.

Что вы можете с этим поделать? Есть два подхода:

  1. Используйте сокеты для связи и сохранения последних N кадров в ОЗУ (т.е. никогда не записывайте их на диск или не используйте независимый процесс для записи на диск).

  2. Не записывать новый файл, перезаписать существующий файл. Так как местоположение всех блоков данных известно заранее, во время записи в FS не будет повторной регистрации. Это также будет немного быстрее. Поэтому идея состоит в том, чтобы создать огромный файл или использовать необработанный раздел, а затем перезаписать его. Когда вы дойдете до конца файла, вернитесь к началу и повторите.

Недостатки:

При подходе № 1 вы можете потерять кадры. Кроме того, вы должны быть абсолютно уверены, что все клиенты могут читать и обрабатывать данные достаточно быстро, иначе сервер может заблокироваться.

С помощью # 2 вы должны найти способ сообщить читателям, где находится текущий «конец файла».

Так что, возможно, лучше использовать смешанный подход:

  1. Создать огромный файл (несколько ГБ). Если одного файла недостаточно, создайте несколько.
  2. Открыть розетку
  3. Запишите данные в файл. Если вы достигли конца файла, найдите позицию 0 и продолжайте запись в нее (например, циклический буфер).
  4. Сброс данных
  5. Отправка начала и количества новых данных читателям через сокет

Рассмотрите возможность использования файлов, отображаемых в память; это сделает все немного проще.

1 голос
/ 07 июля 2011

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

Дополнительное случайное время вполне может быть связано с тем, что файловая система ищет больше свободного места (она сохраняет короткий список, но при исчерпании необходим более дорогой поиск) и выделяет его в файл. Если это причина, предварительно выделите файл в максимальном размере и запишите в него, используя случайный ввод / вывод (fopen (fn, "r+")), чтобы он не усекал длину файла.

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

...