Что создает posix_fadvise() для записи последовательного файла?

Я работаю над приложением, которое последовательно пишет большой файл (и вообще не читает), и я бы хотел использовать posix_fadvise() для оптимизации поведения файловой системы.

Описание функции в manpage предполагает, что наиболее подходящей стратегией будет POSIX_FADV_SEQUENTIAL. Однако в описании реализации Linux сомневается, что:

В Linux POSIX_FADV_NORMAL устанавливает для окна readahead значение по умолчанию для поддерживающего устройства; POSIX_FADV_SEQUENTIAL удваивает этот размер, а POSIX_FADV_RANDOM полностью отключает readahead файла.

Поскольку я только пишу данные (возможно, перезаписываю файлы), я не ожидаю никакого чтения. Должен ли я придерживаться моего POSIX_FADV_SEQUENTIAL или скорее использовать POSIX_FADV_RANDOM, чтобы отключить его?

Как насчет других параметров, например POSIX_FADV_NOREUSE? Или, возможно, не использовать posix_fadvise() для записи вообще?

Ответы

Ответ 1

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

Ответ 2

Большинство флагов posix_fadvise() (например, POSIX_FADV_SEQUENTIAL и POSIX_FADV_RANDOM) являются подсказками о readahead, а не о записи.

Вот несколько советов от Linus здесь и здесь о обеспечивая хорошую последовательную производительность записи. Идея состоит в том, чтобы разбить файл на большие (8 МБ) окна, а затем выполнить цикл:

  • Записать окно N с помощью write();
  • Запросить асинхронную запись окна N с помощью sync_file_range(..., SYNC_FILE_RANGE_WRITE)
  • Дождитесь завершения записи окна N-1 с помощью sync_file_range(..., SYNC_FILE_RANGE_WAIT_BEFORE | SYNC_FILE_RANGE_WRITE | SYNC_FILE_RANGE_WAIT_AFTER)
  • Откроется окно N-1 из pagecache с помощью posix_fadvise(..., POSIX_FADV_DONTNEED)

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

Ответ 3

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

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

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