Linux pagecache и kswapd

Решение проблемы с высокой загрузкой процессора сервисом kswapd в Linux, очистка pagecache

После поднятия очередного сервиса я, внезапно, обнаружил «тормоза» при попытке работы с другими сервисами, поднятыми на той же виртуалке. Естественно, первым делом я посмотрел, а что же происходит. Команда top в этом деле часто оказывает неоценимую помощь:

Как видим, все довольно очевидно, но что такое этот самый kswapd0? Нет, название, конечно, говорящее, то есть, из него можно предположить, что процесс занимается, скорее всего, swap-ом — кэширует данные из памяти на диск, чтобы освободить хотя бы чуточку этого ценного и такого востребованного ресурса. Но… Во-первых, загрузка не изменилась и через полчаса, а во-вторых, она не изменилась даже тогда, когда я принудительно остановил почти все поднятые в контейнерах сервисы.

И именно тут меня настигло дежавю, так сильно эта ситуация напоминала ругаемую сторонниками Linux Windows — там тоже время от времени может выявиться какой-нибудь странный процесс, который, ни с того ни с сего, возьмет и отъест всю мощь CPU. Но в Windows, за долгие годы, я к этому привык и даже знаю, что и в каком случае надо делать. А тут я новичок, тут знания надо нарабатывать. Да и потом, Linux, вроде, должен был быть лишен такого рода заморочек, разве нет? 😜

Первый вопрос, который требует ответа: что такое этот процесс, насколько верна моя догадка, что он связан со swap-ом? Надо сказать, что найти описание процесса kswapd оказалось не так-то просто. Большинство предлагаемых ответов на запрос к Google сразу ведут на статьи о проблемах с этим процессом и путях их решения, и да, в основном — это проблема с высокой нагрузкой на CPU. В выборке, все же, нашлось краткое описание этого демона, а так же более подробное описание самой задачи, для решения которой и предназначен kswapd.

Если подытожить то, что удалось почитать, то получается, что этот процесс стартует во время запуска системы и большую часть времени проводит в «спячке». Информация о том, чем и когда этот демон «пробуждается» немного противиречива: в одних источниках указывается, что «просыпается» он по таймеру, в других — что его «дергает» распределитель физических страниц памяти (physical page allocator). В любом случае, если количество свободных страниц физической памяти меньше определенного порога (этим параметром можно управлять), то процесс начинает сохранять наименее используемые страницы во вторичной памяти, обычно, на диск. На самом деле, алгоритм работы сложнее, например, используются кэши swap-а, ну и все в таком роде, но самое главное, все должно работать без тех самых сторонних эффектов, которые происходят у меня, и которые описывают многочисленные пострадавшие в своих вопросах/комментариях в интернете.

Почему мы имеем то, что имеем, для меня остается пока тайной. В треде по похожей проблеме в Ubuntu писали, что во всем виновата ошибка в коде ядра, и что в новых версиях ситуация должна быть исправлена. Но! Запись эта старая, а есть вопросы, заданные уже для более современных версий. Так что, тайна не раскрыта. Но, что интересно, есть рабочее решение.

Лучше всего, на мой взгляд, как разобраться с проблемой описано вот по этой ссылке: A solution for kswapd0 going haywire on #Linux. Надо сказать, что мне пока довелось пару раз опробовать только вторую часть — сиюминутную очистку pagecache:

echo 1 > /proc/sys/vm/drop_caches

Выполнять эту команду следует из под суперпользователя (речь про root-а, естественно), или же воспользоваться такой модификацией:

echo 1 | sudo tee /proc/sys/vm/drop_caches

Если, кончено, пользователю системы, под которым вы работаете, разрешено пользоваться командой sudo. Так вот, я работал под root-ом и все замечательно разрешилось!

Но все же, что это за волшебные манипуляции? Вот выдержка из документации, касающаяся данной команды:

drop_caches‌‌‌‌

Writing to this will cause the kernel to drop clean caches, as well as reclaimable slab objects like dentries and inodes.  Once dropped, their memory becomes free.

‌‌‌‌To free pagecache:
‌‌echo 1 > /proc/sys/vm/drop_caches

‌‌‌‌To free reclaimable slab objects (includes dentries and inodes):
‌‌echo 2 > /proc/sys/vm/drop_caches‌‌‌‌

To free slab objects and pagecache:
echo 3 > /proc/sys/vm/drop_caches

‌‌‌‌This is a non-destructive operation and will not free any dirty objects. To increase the number of objects freed by this operation, the user may run `sync’ prior to writing to /proc/sys/vm/drop_caches.  This will minimize the number of dirty objects on the system and create more candidates to be dropped.

‌This file is not a means to control the growth of the various kernel caches (inodes, dentries, pagecache, etc…)  These objects are automatically reclaimed by the kernel when memory is needed elsewhere on the system.

‌‌Use of this file can cause performance problems.  Since it discards cached objects, it may cost a significant amount of I/O and CPU to recreate the dropped objects, especially if they were under heavy use.  Because of this, use outside of a testing or debugging environment is not recommended.

‌‌‌‌You may see informational messages in your kernel log when this file is used

:‌‌cat (1234): drop_caches: 3

‌‌‌‌These are informational only.  They do not mean that anything is wrong with your system.  To disable them, echo 4 (bit 2) into drop_caches.

Если излагать вкратце, то эта команда позволяет очистить всевозможные кэши и, таким образом, освободить память, которой так не хватает системе. Какие кэши должны быть очищены определяется записываемым значением. Надо также отметить, что важен сам факт записи данных в файл /proc/sys/vm/drop_caches — запись данных вызывает немедленную реакцию системы, но, в дальнейшем, записанное значение не влияет на ее работу.

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

Как я уже писал выше, запись в файл /proc/sys/vm/drop_caches вызывает немедленную реакцию системы, после которой, лично у меня, kswapd переставал «грузить» систему. Есть утверждение, что если выполнить следующую команду под root-ом:

echo vm.swappiness=0 >> /etc/sysctl.conf

или, если работать под пользователем, которому разрешено использовать sudo:

echo vm.swappiness=0 | sudo tee -a /etc/sysctl.conf

или же просто отредактировать файл /etc/sysctl.conf каким-нибудь редактором (например, nano), добавив строку vm.swappiness=0 (как вы уже, наверное, догадались, редактор тоже надо вызывать из под root-а или при помощи sudo), то можно будет избавиться от описываемой мною проблемы на постоянной, так сказать, основе. Естественно, после того, как в файл /etc/sysctl.conf одним из вышеприведенным способом будут внесены нужные изменения, систему следует перезагрузить, ну или выполнить команду:

sysctl -p

для обновления параметров без перезагрузки. Конечно, из под root-а, или при помощи sudo.

На самом деле, пока я разбирался с этой задачкой, я научился некоторым новым приемам и узнал много нового. О некоторых вновь приобретенных знаниях я, скорее всего, расскажу чуть позже, когда все немного утрясется и уложится. А пока — все…