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

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

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

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

решение1

Возможный метод №1 — F_DROP_CACHES

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

выдержка

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

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

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.

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

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

Поток включает в себя как тестовый пример, так и фактический патч для нескольких файлов в ядре Linux, который добавляет дополнительную функцию к fs/drop_caches.cвызываемому drop_pagecache_file(struct file *filp). Эта функция затем доступна через frontend-инструмент 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

В той же теме другой пользователь упоминает совершенно иную методологию, использующую 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.

решение2

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

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

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

решение3

Вы можете открывать отдельные файлы с помощью O_DIRECTфлага (см. man 2 open) — прочитайтеПРИМЕЧАНИЯвнимательно прочитайте раздел этой страницы руководства и подумайте, хотите ли вы/нуждаетесь ли вы также в O_SYNC.

решение4

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

человек чат:

При изменении файла с установленным атрибутом «S» изменения синхронно записываются на диск; это эквивалентно применению параметра монтирования «sync» к подмножеству файлов.

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

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

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

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

Связанный контент