phdru.name / Russian / blog / 2012 / 09 / 20

Журнал: 20 сентября 2012: memory cgroup

Есть в Линуксе такая проблема -- работа с большими файлами забивает содержимым этих файлов все кеши и буфера, вытесняя оттуда более полезное содержимое. Скачал образ DVD -- в следующий раз любимый редактор будет подгружать свои плагины с диска, а не из памяти. Посмотрел этот DVD -- и опять всё тормозит по новой.

Я долго искал в Интернете какие-нибудь советы, как это вылечить, но всё найденное -- ulimit, ionice и т.п. -- помогало, как мёртвому припарки. Болезнь сидит глубоко в ядре, и лечить её надо там внутри.

И вот во время одного их таких регулярных вылазок за советами я нашёл... не совет даже, а намёк. Но я стал с этим намёком экспериментировать, и развил его до работающего решения. Проблема оказалась решаема, хотя и не вполне тривиально.

Ключевое слово того намёка было -- cgroup. А конкретней -- memory cgroup.

Я захотел с этим поэкспериментировать, и тут же упёрся в проблему -- в дебиановском ядре memory controller выключен. Он тормозит систему, даже если им не пользоваться.

Пришлось перекомпилировать ядро. Мне не впервой. Да что там "не впервой" -- я это регулярно вынужден делать.

Группы включаются в /etc/fstab:

none /sys/fs/cgroup cgroup memory 0 0

После перезагрузки я написал скрипт с несколькими вызовами sudo, который создавал memory cgroup на каждый вызов и засовывал текущий shell в эту группу (для этого надо ID процесса записать в файл tasks группы). Первый же эксперимент показал, что это действительно работает -- shell, запертый в ограниченной группе, скачивает файл, а кеши и буфера не теряются. И никакого торможения системы я не заметил.

Создавать memory cgroup на каждый чих, конечно, неправильно -- нет смысла создавать десяток групп, в каждой из которых ограничение по памяти полгигабайта -- у меня памяти всего 2 гига. Я создал 3 группы -- с ограничением 10 мегабайт, 100 и полгига. 10 мегабайт для скачивания и прочих мелких задачек, 100 для видеоплеера (mplayer) и задач покрупнее, 500 метров -- для браузера.

Группы создаются автоматом в /etc/rc.local, и там же файл tasks открывается на запись группе root -- sudo мне больше не нужен:

CGROUPS=/sys/fs/cgroup
for size in 10M 100M 500M; do
    mkdir $CGROUPS/$size && \
    echo $size > $CGROUPS/$size/memory.limit_in_bytes
done
find $CGROUPS -name tasks -exec chmod g+w '{}' \+

Для засовывания программ в группы -- вот такой скрипт:

#! /bin/sh

size="$1" # in megabytes
shift

CGROUPS=/sys/fs/cgroup
echo $$ > "$CGROUPS"/${size}M/tasks || exit 1

ulimit -d ${size}000
exec nice -20 ionice -c3 "${@:-$SHELL}"

Удалить программу из группы нельзя -- каждый процесс всегда принадлежит какой-нибудь группе. Можно переносить процессы из группы в группу путём записи ID процесса в соответствующий файл tasks группы. Можно перенести процесс в группу без ограничений (дефолтную группу я сделал без ограничений):

echo $$ > "$CGROUPS"/tasks

Теперь дождаться Debian 7.0 с ядром 3+, и урезать аппетит transmission-bt на сервере.


Теги: debian linux

Эта страница http://phdru.name/Russian/blog/2012/09/20/cgmem.html была сгенерирована 08.06.2014 в 20:52:05 из шаблона CheetahTemplate cgmem.tmpl; Некоторые права зарезервированы. Вы можете узнать о технических аспектах этого сайта.