
я знаю что могуудалить все из кэша файловой системы 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% уверен, как это проверить, но придумал следующий подход.
сделать файл размером 100 МБ
$ dd if=/dev/urandom of=sample.txt bs=100M count=1
трассировка доступа к файлам с использованием
fatrace
$ sudo fatrace | grep sample.txt
запустить
top
, чтобы мы могли контролировать использование памяти, отметить свободный объем.$ top
открыть файл, отметить объем свободной памяти сейчас. Обратите внимание
fatrace
на файлsample.txt
.$ cat sample.txt > /dev/null
удалите файл из памяти, обратите внимание на объем свободной памяти сейчас. Обратите внимание на вывод
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_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.
Отказ от ответственности: я это не проверял.
решение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 помещает все во внутренние кэши ядра и увеличивается и уменьшается для размещения содержащихся в них файлов