2015-10-28 1 views
1

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

cat file_larger_than_ram.bin | ./simple-process

Моей теория состоит в том, что это приводит к ядру Linux, чтобы отменить кэш файлов, которые он провел до сих пор в неиспользуемой части ОЗУ. В то же время процессам необходимо получить доступ к данным, над которыми они работают, поэтому после выполнения вышеприведенной команды им необходимо снова загрузить свои файлы. Учитывая, что я только собираюсь использовать file_larger_than_ram.bin один раз, есть ли способ намекнуть, что ядро ​​не кэширует файл? Я слышал, что я мог бы использовать fadvise для этого, но я не уверен, учитывая то, что fadvise64(2) говорит:

POSIX_FADV_DONTNEED пытается освободить кэшировать страницы, связанные с указанной области. Это полезно, например, при потоках больших файлов. Программа может периодически запрашивать ядро ​​ для освобождения кэшированных данных, которые уже были использованы, поэтому вместо использования кэшированных страниц более полезны .

Будет ли применяться fdadvise (input_desc, 0, 0, POSIX_FADV_DONTNEED); действительно вести себя так, как я ожидаю, и решить проблему здесь?

+0

Какие-либо проблемы с проверкой? Из описания кажется, что он должен работать –

+0

Тестирование всех альтернатив потребует много времени, поэтому я решил, что попрошу, если кто-то уже знает ответ. Похоже, что «dd» может быть полезен здесь - я предложил добавить к 'cat': https://lists.gnu.org/archive/html/coreutils/2015-10/msg00111.html и обнаружил, что он уже был отклонен один раз , – d33tah

+1

Вы видели это http://unix.stackexchange.com/questions/36907/drop-a-specific-file-from-the-linux-filesystem-cache? –

ответ

2

Учитывая, что я только собираюсь использовать file_larger_than_ram.bin один раз, есть способ намекнуть, что ядро ​​не кэширует файл?

Насколько я знаю, это возможно с флагом O_DIRECT к системному обеспечению open. Но флаг имеет дополнительные ограничения (например, смещение файла и выравнивание буфера памяти пользовательского пространства), что может вызвать проблемы. В тестах они не вызывали проблем, но в документации говорится, что поведение является специфичным для устройства/файловой системы. Таким образом, я изменил свой код, чтобы использовать fadvise().

(Кроме того, я заметил некоторые нарушения характеристик (read()/write() слишком быстро), который предположил, что даже с O_DIRECT некоторые данные иногда становились кэшируются. YMMV.)

Я слышал, что я мог бы использовать fadvise для этого, но я не уверен [...]

Мне тоже было непонятно, поэтому я проверил исходный код ядра. Эффект вызова fadvise() с POSIX_FADV_DONTNEED заключается в удалении соответствующих данных из кеша. Я не видел ничего, чтобы предположить, что флаг равен sticky и применяется ко всем файлам. (Вот почему я проверил исходный код: я знаю, что Linux выполняет I/O всегда через кеш, причем альтернативой является O_DIRECT. Липкий POSIX_FADV_DONTNEED не вписывался в парадигму.)

Другими словами, чтобы освободить кэш во время чтения вам нужно:

  • держать след смещения файла перед read()

  • после read(), вызовите fadvise(POSIX_FADV_DONTNEED) на интервале данные, которые вы только что прочитали.

  • Для получения наилучших результатов вам необходимо прочитать данные в блоках, выровненных по страницам. Кэш ввода-вывода основан на странице, а fadvise() отображает указанный диапазон данных в список страниц. Неправильное смещение вызовет дополнительные read() с (и вред), но в остальном безвредно.

Для написания это является немного более сложным: я заметил, что fadvise(POSIX_FADV_DONTNEED) не имеет никакого эффекта, если вызывается сразу после write(). Нужно называть fsync()/, чтобы заставлять записывать данные, тем самым отбрасывая записи кэша и только затем вызываем fadvise(POSIX_FADV_DONTNEED), чтобы освободить их.

P.S. Насколько я понял код ядра, трюк с dd, связанный с @AlexHoppus, должен работать. Например, cat file; dd if=file of=/dev/null iflag=nocache - вызов cat помещает файл в кеш, dd будет читать его из кеша, а затем отбрасывать его из кеша. fadvise(POSIX_FADV_DONTNEED) работает с глобальным кешем, и, следовательно, не имеет значения, кто/когда читает данные, он все равно их отбросит.

Смежные вопросы