Эксперименты и увлекательные манипуляции с дисковым кэшем Linux
Надеюсь, теперь вы убедились, что Linux не “съел” всю вашу оперативную память. Вот несколько интересных вещей, которые вы можете сделать, чтобы узнать, как работает дисковый кэш.
Примечание: Приведенные примеры относятся к оборудованию 2009 года без SSD. Возможно, вам придется умножить несколько приведенных здесь чисел на 10, чтобы оценить реальный эффект.
Влияние дискового кэша на аллокацию памяти приложениями
Поскольку я уже заверил, что дисковый кэш не мешает приложениям получать нужную им память, давайте с этого и начнем. Вот приложение на языке Си ( munch.c ), которое поглотит столько памяти, сколько сможет, или до заданного предела:
#include #include #include int main(int argc, char** argv) < int max = -1; int mb = 0; char* buffer; if(argc >1) max = atoi(argv[1]); while((buffer=malloc(1024*1024)) != NULL && mb != max) < memset(buffer, 0, 1024*1024); mb++; printf("Allocated %d MB\n", mb); >return 0; >
Закончившаяся память — это не очень весело, но механизм OOM (Out-Of-Memory) killer должен завершить только этот процесс и, надеюсь, остальные останутся нетронутыми. Мы определенно захотим отключить своп в данном случае, иначе приложение поглотит и его.
(обратите внимание, что ваш вывод free может быть другим, и иметь столбец ‘available’ (доступная) вместо строки ‘-/+’)
total used free shared buffers cached Mem: 1504 1490 14 0 24 809 -/+ buffers/cache: 656 848 Swap: 0 0 0 $ gcc munch.c -o munch $ ./munch Allocated 1 MB Allocated 2 MB (. ) Allocated 877 MB Allocated 878 MB Allocated 879 MB Killed $ free -m total used free shared buffers cached Mem: 1504 650 854 0 1 67 -/+ buffers/cache: 581 923 Swap: 0 0 0
Несмотря на то, что было указано 14 МБ «free» (свободная), это не помешало приложению захватить 879 МБ. После этого кэш практически пуст[2], но постепенно он снова заполнится по мере чтения и записи файлов. Попробуйте.
Влияние дискового кэша на свопинг
Я также сказал, что кеш диска не заставит приложения использовать своп (подкачку). Давайте попробуем и это, с тем же приложением munch, что и в предыдущем эксперименте. На этот раз мы запустим его с включенным свопом и ограничимся несколькими сотнями мегабайт:
$ free -m total used free shared buffers cached Mem: 1504 1490 14 0 10 874 -/+ buffers/cache: 605 899 Swap: 2047 6 2041 $ ./munch 400 Allocated 1 MB Allocated 2 MB (. ) Allocated 399 MB Allocated 400 MB $ free -m total used free shared buffers cached Mem: 1504 1090 414 0 5 485 -/+ buffers/cache: 598 906 Swap: 2047 6 2041
munch “съел” 400MB оперативной памяти, которая была взята из дискового кэша, не обращаясь к свопу. Аналогично, мы можем снова заполнить дисковый кэш, и он также не станет использовать своп. Если в одном терминале запустить watch free -m и find . -type f -exec cat <> + > /dev/null в другом, вы увидите, что «cached» (кэшированная) память будет расти, а «free» падать. Через некоторое время это замедляется, но своп так и остается нетронутым[1].
Очистка дискового кэша
При проведении экспериментов очень удобно иметь возможность сбросить дисковый кэш. Для этого мы можем использовать специальный файл /proc/sys/vm/drop_caches . Записав в него значение 3 , мы можем очистить большую часть дискового кэша:
$ free -m total used free shared buffers cached Mem: 1504 1471 33 0 36 801 -/+ buffers/cache: 633 871 Swap: 2047 6 2041 $ echo 3 | sudo tee /proc/sys/vm/drop_caches 3 $ free -m total used free shared buffers cached Mem: 1504 763 741 0 0 134 -/+ buffers/cache: 629 875 Swap: 2047 6 2041
Обратите внимание, что «buffers» (буфера. буферная память) и «cached» уменьшились, free mem (свободная память) увеличилась, а free+buffers/cache остались прежними.
Влияние дискового кэша на время загрузки
Давайте сделаем две тестовые программы, одну на Python, а другую на Java. И Python, и Java имеют довольно большие рантаймы, которые должны быть загружены для запуска приложения. Это идеальный сценарий для работы дискового кэша.
$ cat hello.py print "Hello World! Love, Python" $ cat Hello.java class Hello < public static void main(String[] args) throws Exception < System.out.println("Hello World! Regards, Java"); >> $ javac Hello.java $ python hello.py Hello World! Love, Python $ java Hello Hello World! Regards, Java
Наши приложения “hello world” работают. Теперь давайте сбросим дисковый кэш и посмотрим, сколько времени потребуется для их запуска.
$ echo 3 | sudo tee /proc/sys/vm/drop_caches 3 $ time python hello.py Hello World! Love, Python real 0m1.026s user 0m0.020s sys 0m0.020s $ time java Hello Hello World! Regards, Java real 0m2.174s user 0m0.100s sys 0m0.056s $
Ого. 1 секунда для Python и 2 секунды для Java? Это много, чтобы просто сказать «привет» (hello). Однако теперь все файлы, необходимые для их запуска, будут находиться в дисковом кэше, поэтому их можно будет получить прямо из памяти. Давайте попробуем еще раз:
$ time python hello.py Hello World! Love, Python real 0m0.022s user 0m0.016s sys 0m0.008s $ time java Hello Hello World! Regards, Java real 0m0.139s user 0m0.060s sys 0m0.028s $
Ура! Теперь Python запускается всего за 22 миллисекунды, в то время как java использует 139 мс. Это в 45 и 15 раз быстрее! Все ваши приложения получают этот буст автоматически!
Влияние дискового кэша на чтение файлов
Давайте создадим большой файл и посмотрим, как дисковый кэш влияет на скорость его считывания. Я делаю файл размером 200 МБ, но если у вас меньше свободной памяти, то можете изменить это значение.
$ echo 3 | sudo tee /proc/sys/vm/drop_caches 3 $ free -m total used free shared buffers cached Mem: 1504 546 958 0 0 85 -/+ buffers/cache: 461 1043 Swap: 2047 6 2041 $ dd if=/dev/zero of=bigfile bs=1M count=200 200+0 records in 200+0 records out 209715200 bytes (210 MB) copied, 6.66191 s, 31.5 MB/s $ ls -lh bigfile -rw-r--r-- 1 vidar vidar 200M 2009-04-25 12:30 bigfile $ free -m total used free shared buffers cached Mem: 1504 753 750 0 0 285 -/+ buffers/cache: 468 1036 Swap: 2047 6 2041
Поскольку файл был только что записан, он отправится в дисковый кэш. Файл размером 200 МБ привел к увеличению «cached» на 200 МБ. Давайте его прочтем, очистим кэш и прочитаем снова, чтобы посмотреть, насколько это быстро:
$ time cat bigfile > /dev/null real 0m0.139s user 0m0.008s sys 0m0.128s $ echo 3 | sudo tee /proc/sys/vm/drop_caches 3 $ time cat bigfile > /dev/null real 0m8.688s user 0m0.020s sys 0m0.336s $
Это более чем в пятьдесят раз быстрее!
Выводы
Дисковый кэш Linux очень ненавязчив. Он использует резервную память для значительного увеличения скорости доступа к диску, при этом не отнимая памяти у приложений. Полностью использованная память в Linux — это эффективное применение оборудования, а не сигнал тревоги.
В данном материале есть немного полезной информации:
- Хотя вновь аллоцированная память всегда (впрочем, см. пункт #2) будет браться из дискового кэша вместо свопа, Linux может быть сконфигурирован для предварительной выгрузки других неиспользуемых приложений в фоновом режиме, чтобы освободить память для кэша. Это настраивается с помощью параметра swappiness , доступного через /proc/sys/vm/swappiness . Сервер может захотеть выгрузить неиспользуемые приложения, чтобы ускорить доступ к диску для работающих программ («сделать систему быстрее»), в то время как десктопная система будет держать их в памяти, чтобы предотвратить задержку, когда пользователь наконец воспользуется ими («сделать систему более отзывчивой»). Данная тема вызывает много споров.
- Некоторые части кэша не могут быть сброшены, даже для размещения новых приложений. К ним относятся mmap-страницы, которые были заблокированы системным вызовом mlock какого-либо приложения, «грязные» страницы (dirty pages), пока не записанные в память, и данные, хранящиеся в tmpfs (включая /dev/shm , используемую для общей памяти). Заблокированные (mlocked) mmap-страницы застревают в кэше страниц. «Грязные» страницы в большинстве случаев будут быстро переписаны. Данные в tmpfs по-возможности будут выгружены.
На днях пройдет открытый урок «LVM для начинающих», на котором разберем основные моменты использования LVM для организации дисковой системы в Linux. На занятии узнаем, что такое LVM и когда он нужен, что в него входит (PV, VG, LV). А также научимся, что можно сделать с его использованием. Регистрация открыта по ссылке.