Удалить конкретный файл из кэша файловой системы Linux?

23

Я знаю, что могу удалить все из кэша файловой системы Linux , но есть ли способ удалить только один конкретный файл? Или предотвратить кеширование файла? Или сказать процессу не кэшировать какие-либо файлы, которые он пишет?

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

Джей Хакер
источник
1
Что касается награды, меня особенно интересует вопрос заголовка: удаление определенного файла из кэша (в отличие от предотвращения его попадания в первую очередь).
Жиль "ТАК - перестань быть злым"

Ответы:

21

Потенциальный метод № 1 - F_DROP_CACHES

Я нашел метод 2012 года, в котором обсуждается предложенный патч для ядра Linux в этой почтовой ветке под названием: Re: [RFC Patch] fs: реализовать кеши для каждого файла .

выдержка

Cong> Это черновой патч реализации кеша для каждого файла.

Интересный. Так я могу сделать это извне процесса? Я являюсь системным администратором, поэтому мой POV заключается в том, чтобы замечать, находить и устранять проблемы с производительностью, когда система находится под давлением.

Cong> It introduces a new fcntl command  F_DROP_CACHES to drop  
Cong> file caches of a specific file. The reason is that currently  
Cong> we only have a system-wide drop caches interface, it could  
Cong> cause system-wide performance down if we drop all page caches  
Cong> when we actually want to drop the caches of some huge file.

Как я могу сказать, сколько кеша используется файлом? И как это влияет на производительность при работе в загруженной системе? И что этот патч купит нам, так как я полагаю, что виртуальная машина уже должна сбрасывать кэши, как только система оказывается под давлением mem ...

Cong> Ниже приведен небольшой тестовый пример для этого патча:

Поток включает в себя как тестовый случай, так и реальный патч для нескольких файлов в ядре Linux, что добавляет к fs/drop_caches.cвызываемой дополнительную функцию drop_pagecache_file(struct file *filp). Затем эта функция доступна через инструмент внешнего интерфейса, fnctl.cчерез команду F_DROP_CACHES. Этот случай вызывает эту функцию:

file_drop_caches(filp, arg);

Который обрабатывает удаление всех кэшей, связанных с данным файлом. Из файла include/linux/mm.h:

void file_drop_caches(struct file *filp, unsigned long which);
Так это можно использовать?

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

Потенциальный метод № 2 - Использование дд

В той же теме другой пользователь упоминает совершенно другую методологию, которая использует dd.

Ниже приводится выдержка из этого письма

Это полезный функционал. Хотя это уже не обеспечено POSIX_FADV_DONTNEED? Эта функциональность была добавлена ​​в GNU dd (8.11) год назад .

Вот примеры из этого патча:
  • Посоветуйте сбросить кеш для всего файла

     $ dd if=ifile iflag=nocache count=0
    
  • Обеспечить удаление кэша для всего файла

     $ dd of=ofile oflag=nocache conv=notrunc,fdatasync count=0
    
  • Удалить кеш для части файла

     $ dd if=ifile iflag=nocache skip=10 count=10 of=/dev/null
    
  • Потоковые данные, используя только кэш опережающего чтения

     $ dd if=ifile of=ofile iflag=nocache oflag=nocache
    
Тестирование это

Я не был на 100% уверен, как это проверить, но я придумал следующий подход.

  1. сделать файл размером 100 МБ

    $ dd if=/dev/urandom of=sample.txt bs=100M count=1
    
  2. доступ к файлу трассировки с использованием fatrace

    $ sudo fatrace | grep sample.txt
    
  3. запустить, topчтобы мы могли контролировать использование памяти, обратите внимание, количество свободных.

    $ top
    
  4. откройте файл, отметьте количество свободной памяти сейчас. Обратите внимание fatraceна файл sample.txt.

    $ cat sample.txt > /dev/null
    
  5. удалите файл из памяти, запишите количество свободной памяти сейчас. Обратите внимание на вывод fatrace.

    $ sudo dd of=/home/saml/tst/162600/sample.txt \
        oflag=nocache conv=notrunc,fdatasync count=0
    

пример

В терминале № 1:
$ dd if=/dev/urandom of=sample.txt bs=100M count=1
1+0 records in
1+0 records out
104857600 bytes (105 MB) copied, 7.37996 s, 14.2 MB/s

$ ls -l sample.txt 
-rw-rw-r--. 1 saml saml 104857600 Oct 17 22:54 sample.txt
В терминале № 2:
$ top
...
KiB Mem:   7968336 total,  6900956 used,  1067380 free,   267080 buffers
...
В терминале № 3:
$ sudo fatrace | grep sample.txt
Теперь откройте файл sample.txtи запишите объем оперативной памяти. В терминале № 1.
$ cat sample.txt > /dev/null
В терминале № 2:
KiB Mem:   7968336 total,  7011896 used,   956440 free,   267336 buffers
Обратите внимание на вывод fatraceв терминале № 3:
cat(25940): R /home/saml/tst/162600/sample.txt
cat(25940): R /home/saml/tst/162600/sample.txt
cat(25940): RC /home/saml/tst/162600/sample.txt
Теперь удалите файл из ОЗУ в терминале № 4:
$ sudo dd of=/home/saml/tst/162600/sample.txt \
    oflag=nocache conv=notrunc,fdatasync count=0
Обратите внимание на вывод fatraceв терминале № 2:
dd(26229): O /home/saml/tst/162600/sample.txt
dd(26229): CW /home/saml/tst/162600/sample.txt
Обратите внимание на оперативную память в терминале № 3:
KiB Mem:   7968336 total,  6908364 used,  1059972 free,   267364 buffers

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

Потенциальный метод № 3 - python-fadvise

Благодаря комментарию @frostchutz появился еще один инструмент, скрипт Python, [pyadvise][4]который предоставляет гораздо более простой интерфейс, чем описанные выше ddметоды. Этот скрипт использует тот же posix_fadvise(2)интерфейс.

пример
$ sudo pyadvise --help
Usage: 
    pyadvise [options] [FILE]..

Options:
  -h, --help        show this help message and exit
  -w, --willneed    The specified files will be accessed in the near future
  -s, --sequential  The application expects to access the specified files
                    sequentially (with lower offsets read before higher ones)
  -d, --dontneed    The specified files will not be accessed in the near
                    future
  -r, --random      The specified files will be accessed in random order
  -o, --noreuse     The specified files will be accessed only once. Under
                    Linux, this operation is a no-op; see contrib/copyfileobj-
                    fadvise.py in the python-fadvise source tree for an
                    example on how to achieve approximately the same effect
  -n, --normal      Indicates that the application has no advice to give about
                    its access pattern for the specified files. If no advice
                    is given for an open file, this is the default assumption
  -v, --verbose     Explain what is being done

И если мы повторим вышеупомянутый тест и используем pyadviseвместо dd:

$ pyadvise -d /home/saml/tst/162600/sample.txt

Я заметил такое же падение потребления оперативной памяти, как и раньше, когда я использовал dd.

SLM
источник
ddработает для меня. Я закончил с chris-lamb.co.uk/projects/python-fadvise, что то же самое в более очевидной команде.
frostschutz
@frostschutz - очень круто. Я не слышал об этом, пока Жиль не спросил, знает ли кто-нибудь, как это сделать в чате. python-fadviseгораздо проще, я добавил пример показа dd.
SLM
Ссылка на скрипт на python должна быть перенесена в основную часть вопроса. Комментарии могут исчезнуть без следа. Редактирование в худшем случае все еще останется в истории. Сказав, что, поиск Google находит это легко, так что не имеет большого значения.
Фахим Митха
Кажется, что он работает даже без sudo, поэтому любой, кто видит файл (даже без разрешения на запись), может сбросить его кеш, это ... интересно.
frostschutz
1
В os.posix_fadvise()стандартной версии Python есть библиотека.
kawing-
3

Развернув ответ @ geekosaur, вы можете принудительно использовать его O_DIRECTс помощью LD_PRELOAD и программы здесь: http://arighi.blogspot.com/2007/04/how-to-bypass-buffer-cache-in-linux.html

Этот код действует O_DIRECTдля всех файлов. Однако, просто добавив еще немного логики strncmp, __do_wrap_openвы можете выборочно применить O_DIRECT.

Отказ от ответственности: я не проверял это.

Марк Вагнер
источник
2

Вы можете открывать отдельные файлы с O_DIRECTфлагом (см. man 2 open) - внимательно прочитайте раздел NOTES на этой man-странице и подумайте, хотите ли вы или нуждаетесь O_SYNC.

geekosaur
источник
1
Ну, мой процесс cat, и я бы не стал его переписывать. :) Я надеялся на инструмент командной строки или /proc/sysкнопку.
Джей Хакер
2
Хуже того, я подозреваю, что вы действительно имеете в виду, что вы используете перенаправление, поэтому ваш процесс - это оболочка. Я не знаю отдельного способа контролировать это, кроме openфлага; вам действительно нужно написать программу для этого. ( cat -uотключает только stdioбуферизацию, но не буферизацию ОС.)
geekosaur
-2

Если вы хотите, чтобы файл всегда использовал O_SYNC, вы можете пометить его в расширенных атрибутах следующим образом chattr +S $file:

man chattr:

Когда файл с набором атрибутов 'S' изменяется, изменения записываются синхронно на диск; это эквивалентно опции монтирования 'sync', применяемой к подмножеству файлов.

O_SYNC заставляет данные + метаданные записываться в дисковые буферы, но все равно проходит через кеш страниц. O_DIRECT обходит кеш страницы.

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

Если у вас есть оперативная память для хранения всех маленьких файлов, вы можете решить проблему другим способом. Убедитесь, что небольшие файлы всегда находятся в оперативной памяти, и я бы предложил скопировать их в tmpfs :

tmpfs помещает все во внутренние кеши ядра, увеличивается и уменьшается для размещения содержащихся в нем файлов.

Хорхе Нерин
источник
chattr +Sэто не то же самое O_DIRECT, это то же самое, что O_SYNC. O_DIRECTприводит к тому, что операции чтения не кэшируются (о чем этот вопрос), а операции записи не буферизируются без гарантии. O_SYNCзаставляет только записи не буферизироваться.
Жиль "ТАК - перестань быть злым"
@ Жиль, ты прав, я прочитал вопрос и подумал о том, чтобы сбросить данные на диск, как я делал это раньше. И есть еще одна тонкая, но важная в этом случае разница между O_DIRECT и O_SYNC, O_DIRECT обходит кеш страницы, но O_SYNC нет, это заставляет данные (и метаданные) быть сброшены на диск, но проходит через кеш страницы и хранится там для ускорения чтения. Должен ли я изменить O_DIRECT на O_SYNC в своем ответе, чтобы не допустить неправильного подтверждения?
Хорхе Нерин
Этот вопрос задает вопрос о сохранении большого файла, который был записан из кэша. Я думаю, что открытие его с помощью O_DIRECT пагубно скажется на производительности, и если большой файл просто добавляется, разница может быть небольшой. Но если большой файл перезаписывается в случайных местах, O_DIRECT будет очень сильно влиять на производительность, даже принимая во внимание, что он может вытеснить из кэша некоторые из небольших файлов для чтения.
Хорхе Нерин
Изменение , O_DIRECTчтобы O_SYNCбы ваш ответ внутренне непротиворечивой, но все - таки неправильно рассматривать вопрос.
Жиль "ТАК - перестань быть злым"