Видалити певний файл із кешу файлової системи Linux?


23

Я знаю, що можу скинути все з кешу файлової системи Linux , але чи є спосіб видалити лише один конкретний файл? Або запобігти кешування файлу? Або скажіть процесу не кешувати файли, які він пише?

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


1
Щодо баунті, мене спеціально цікавить заголовке питання: викидання певного файлу з кеша (на відміну від того, щоб запобігти йому потрапляння туди в першу чергу).
Жил 'SO- перестань бути злим'

Відповіді:


21

Потенційний метод №1 - F_DROP_CACHES

Я знайшов метод з 2012 року, який обговорює запропонований патч до ядра Linux у цій поштовій нитці під назвою: Re: [RFC Patch] fs: реалізувати кеш-пам’яті для кожного файлу .

витяг

Cong> Це проектний патч реалізації кеш-файлів падіння файлів.

Цікаво. То чи можу я це зробити поза процесом? Я SysAdmin, тому мій 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.

Як я можу сказати, скільки кешу використовується файлом? І який вплив це на ефективність роботи при запущеній системі? І що нам купує цей патч, оскільки я вважаю, що VM вже має скидати кеші, коли система потрапляє під тиск пам'яті ...

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.

Нижче наведено уривок із цього електронного листа

Це корисна функціональність. Хоча це вже не забезпечено 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 - пітон-фадвіс

Завдяки коментарю @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.


ddпрацює для мене. Я закінчив chris-lamb.co.uk/projects/python-fadvise себе, що те саме в більш очевидній команді.
frostschutz

@frostschutz - дуже круто. Я не чув про це, поки Жилл запитав, чи хтось знає, як це зробити в чаті. python-fadviseнабагато простіше, я додав приклад, що показує dd.
slm

Посилання на скрипт python слід перенести в основну частину питання. Коментарі можуть зникнути безслідно. Правка в гіршому випадку все ще залишиться в історії. Сказавши це, пошук в Google знайде це легко, тому не велика справа.
Faheem Mitha

Це навіть здається, що працює без судо, тому кожен, хто може бачити файл (навіть без дозволу на запис), може скинути кеш, це ... цікаво.
frostschutz

1
Зараз є os.posix_fadvise()в стандартній бібліотеці Python.
kawing-chiu

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) - уважно прочитайте розділ ПРИМІТКИ цієї сторінки та обміркуйте, чи ви теж хочете / потребуєте O_SYNC.


1
Ну, мій процес є cat, і я краще не переписую його. :) Я сподівався на інструмент командного рядка або /proc/sysручку.
Джей Хакер

2
Гірше за це, я підозрюю, що ви справді маєте на увазі, що ви використовуєте перенаправлення, тому ваш процес є оболонкою. Я не знаю способу керування цим файлом окрім openпрапора; вам дійсно потрібно було б написати програму, щоб це зробити. ( cat -uвимикає лише stdioбуферизацію, не буферизацію ОС.)
geekosaur

-2

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

man chattr:

Коли файл із набором атрибутів 'S' модифікується, зміни записуються синхронно на диск; це еквівалентно параметру монтажу «синхронізація», застосованому до підмножини файлів.

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

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

Якщо у вас є оперативний пам'ять, щоб зберігати там всі невеликі файли, ви можете підійти до проблеми іншим способом. Переконайтеся, що маленькі файли завжди є в операційній пам’яті, тоді я б запропонував скопіювати їх у tmpfs :

tmpfs вкладає все у внутрішні кеші ядра та росте та скорочується, щоб вмістити файли, які він містить


chattr +Sце не те саме, що O_DIRECT, це те саме, що O_SYNC. O_DIRECTпризводить до того, що читання не кешується (про що йдеться в цьому питанні) і пише, що його не потрібно забудувати, не маючи гарантії. O_SYNCпричини лише запису не буферизовані.
Жил "ТАК - перестань бути злим"

@Gilles ти маєш рацію, я прочитав запитання і подумав про те, як передати дані на диск, як я це робив раніше. І є ще одна тонка, але важлива в цьому випадку різниця між O_DIRECT та O_SYNC, O_DIRECT обходить кеш сторінки, але O_SYNC ні, він змушує дані (та метадані) бути переданими на диск, але він проходить через кеш сторінки та зберігається там, щоб прискорити читання. Чи повинен я змінити O_DIRECT на O_SYNC у своїй відповіді, щоб не допустити, щоб воно залишалося з неправильним твердженням?
Хорхе Нерін

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

Зміна , O_DIRECTщоб O_SYNCб ваша відповідь внутрішньо несуперечливої, але все - таки неправильно розглядати питання.
Жил "ТАК - перестань бути злим"
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.