LINUX.ORG.RU
ФорумAdmin

Как огроничить io и кэш процессов пользователя в авторежиме?

 , , , ,


1

1

Типичная ситуация: какое-то приложение начинает бурно работать с большим количеством файлов, другие приложения начинают чуть-чуть притормаживать.

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

Каким образом это можно предотвратить? Как ограничить размер кэша для каждого приложения от одного пользователя, плюс ставить им самый низкий приоритет IO по-дефолту, а иксам, компизу, пульсу, плееру ставить самый высокий?

Ответ на: комментарий от ktulhu666

куда важнее кэш, чем само io

Тем более что зарезав процессу IO ты просто ускоришь сжирание кеша процессом. У вышекастуемого это где-то в ВиКи описано на примере флешек.

Критичные ко времени исполнения приложения не должны полагаться на кеш.

anonymous
()
Ответ на: комментарий от Lindows

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

Lindows
()

Создать отдельный демон, который откроет все нужные файлы и сделает им mmap + mlock, но это стремно. Можно написать маленький so'шник, который по определенному сигналу будет вызывать mlockall и запускать все нужные процессы с LD_PRELOAD'ом этой библиотеки.

red_eyed_peguin
()
Ответ на: комментарий от Lindows

А чего Вы вообще решили, что кэш как-то относится к памяти процесса? Бесспорно, есть возможность (но это изначальный вариант, и далеко не везде используется) отражения файлов в память процесса, но это связано с его виртуальной, а не реальной памятью (посмотрите через top, сколько Ваш firefox жрёт реальной и виртуальной памяти, а пульс Вас уж совсем удивит), к виртуальной памяти относится и общая память (что весьма важно, т.к. в линуксе и многих других юниксах многие либы подгружаются в память один раз, а затем используются через общую память многими приложениями).

Через cgouprs, limits, selinux, openvz обычно ограничивают размер именно реальной оперативы, потребляемой процессом (иначе (например) samba, которая решила отдать пользователю фильм в 20гб, из-за ограничений в 100мб на процесс очень быстро сделает аля-улю и сбросит копыта либо (если есть обработчик ошибок и ядро отказывает запросу выделения памяти, а не убивает процесс, что может быть и так), скажет до «свидание» пользователю, т.к. не сможет открыть файл), но этого не происходит.

В selinux и openvz (может и в других примочках безопасности тоже) можно контролировать и размер виртуальной памяти. Но в этом случае с приложением произойдут проблемы, написанные выше. Обычно, если ограничения на виртуальную память и ставятся, то они измеряются десятками или сотнями гигабайт, и нужны они, что не было DOS путём отжирания процессорного времени попытками захавать петабайты виртуальной памяти.

Мало того, Вы не понимаете сути отражения файла в память. Это абсолютно тоже самое, что swap, только отражает куски виртуальной памяти не в страницы swap'a, а файла. Сами куски файла не копируются (на самом деле часенько копируются, но только несколько или одна текущая страницы, что не более 8МБ и роли не играет) в реальную память, а происходит прерывание, вызывающее ядро для подмены нужного куска на кусок файла. ( На самом деле после использования кусок файла в реальной памяти по адресу виртуальной памяти, освобождается, и этому куску виртуальной памяти (как в случае со swap) опять ничего не принадлежит). Поскольку, коме текущий данных, ничего в реальной памяти нет (а что есть стремиться освободиться ядром при первой возможности), то и кэша (в смысле именно большого кэша), там нет.

Так вот, что касается кэша: что в случае в Вашим любимым отображением файла в виртуальную память, что в случае со стандартный POSIX-вызовом к ведру, кэш храниться вообще в отдельной области (ядерной), мало того, кэш (не буферы устройств) - это дочерняя сущность VFS. Поэтому его правильнее называть VFS cache, а не disk cache. С кэшем на запись всё очевидно: через несколько параметров dirty_page************ прямо через псевдофайлы всё можно настроить, можно смонтировать FS с опцией sync, использовать планировщики (кэш (грязные странцы) на запись становится кэшем чтения сразу после записи, и как кэш записи для нас исчезает.) и т.п.

Но вот с кэшем чтения проблема. Он не пропадает после того, как был считан приложением, он пропадает после того, как файл был закрыт всеми использующими его приложениями или был вытеснен жрущими оперативу процессами. Проблема в том, что если приложение забывает закрывать файлы или копирует большой файл, то оно засирает почти весь кэш VFS.

На данный момент я не нашел реализации на уровня ядра для ограничения per-process VFS кэша на чтение (за запись можно сделать для всех процессов (как итого, так и на процесс) через dirty_pages)). Но на уровне пользователя можно вызвать FADV_DONTNEED, что сбросит имеющийся VFS кэш для открытых файлов процесса. Развивая мысль, можно сделать LD_PRELOAD.

Погуглив, я наткнулся на http://code.google.com/p/pagecache-mangagement/ , что полность решает проблему именно так (но это не мешает злоумышленнику собрать ПО через собственные вызовы и нагнуть кэш).

Ещё интересное ПО (часть на уровне ядра) по поводу кэша: http://code.google.com/p/pagecache-tools/

Пока нет времени побывать, если будете, отпишитесь о результатах.

ktulhu666 ☆☆☆
() автор топика
Ответ на: комментарий от ktulhu666

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

Извини за недоверие, но можно ссылочку на это?

anonymous
()
Ответ на: комментарий от anonymous

Прошу прощения, я неправильно понял про кэши чтения. Они, таки, не удаляются сразу после закрытия файла всеми приложениями, а остаются.

ktulhu666 ☆☆☆
() автор топика
Ответ на: комментарий от ktulhu666

Вообще-то меня больше взволновало известие о том, что кеш ФС и кеш чтения процесса - это одно и то же и что кеш ФС не может быть очищен до закрытия файла.

anonymous
()
Ответ на: комментарий от anonymous

Вот тут Вы уже неправильно поняли мой текст. Я, наоборот, писал, что кэша у процесса (за исключением 4-8Мб, отраженных в память в данный момент или около метра, если через POSIX) вообще нет, только у VFS и её подуровней.

ktulhu666 ☆☆☆
() автор топика
Ответ на: комментарий от ktulhu666

Разве в дисковом кэше дисковые блоки хранятся в привязке к конкретным файлам?

anonymous
()
Ответ на: комментарий от ktulhu666

-_-'

Виртуальную память cgroups конечно не ограничивает. Я конечно не в курсе о таком глубоком управлении памятью.

В общем, я решил посмотреть более детально на cgroups, чтобы разобраться что к чему.

Обычная группа на 400метров.

# mkdir /sys/fs/cgroup/memory/dd
# echo 400M > /sys/fs/cgroup/memory/dd/memory.limit_in_bytes
# sync & echo 3 > /proc/sys/vm/drop_caches
# free -m
             total       used       free     shared    buffers     cached
Mem:          7907        737       7169          0          6        140
-/+ buffers/cache:        590       7317
Swap:         1999          0       1999

А дальше собственно добавление текущего шелла в группу

echo $$ > tasks

Тест на запись

# cat /dev/zero > /lol.desu
# du -h /lol.desu 
11G     /lol.desu
# free -m
             total       used       free     shared    buffers     cached
Mem:          7907       1190       6716          0         20        548
-/+ buffers/cache:        621       7285
Swap:         1999          0       1999
Записанный файл в 11G, cached стало больше на 400M, ровно как указано в memory.limit_in_bytes.

А теперь обратно..


# cat /lol.desu > /dev/null
# free -m
             total       used       free     shared    buffers     cached
Mem:          7907       6543       1364          0         20        558
-/+ buffers/cache:       5964       1943
Swap:         1999          0       1999
какая то хрень, cached не именился, но память сожрало. Хотя, очевидно, это все еще кеш, покрайней мере это можно сбросить через /proc/sys/vm/drop_caches. В /proc/meminfo тоже не видно, куда делась память. Значит это кеш, основанный на технологиях libastral.so =)

дальше запустил там файерфокс, открыл около 40 вкладок и залил пару фильмов(700м х2) в облачный сервис, а потом скачал их обратно.

# free -m
             total       used       free     shared    buffers     cached
Mem:          7907       1200       6706          0          7        162
-/+ buffers/cache:       1031       6876
Swap:         1999        231       1768

ФФ остался в рамках группы.

Да и с самого начала, мой задачей было ограничение делюги, ибо после 2-3 часов весь кеш забивается раздаваемыми торрентами. Собственно тут memory cgroup справился на отлично.

Вобщем, можно сделать два вывода:

1. я не понимаю, зачем тут два разных вида кеша и вообще не понимаю нифига

2. memory cgroup - полумера..

Ну чтож, придется сегодня ночью не спать, а читать об управлении памятью.. -_-

Lindows
()
Ответ на: -_-' от Lindows

Что касается двух кэшей, то, как я и говорил, есть кэш VFS (причём для директорий, inode и страниц файлов, для каждого отдельно, можно отдельно очистить), а есть кэш блочного устройства. Это разные вещи, одна под другой. Что касается других буферов, то (за исключением специальных надстроек), можете не беспокоиться: буферы есть почти везде, они нужны для «склейки» разного ПО (например, есть буферы сокета для обмена информацией процесса с ядром), они пренебрежительно малы.

Весьма интересно, получается, что crgoups и кэш ограничивает, иначе cached заняло бы всю память. Попробуй сделать тоже самое без занесения в группу, посмотри, как изменится кэш.

Не забудьте прочитать:
http://logicalshift.blogspot.com/2010/06/linux-virtual-file-system-vfs.html (обязательно, там про кэш)
http://monolight.cc/2011/06/barriers-caches-filesystems/
http://tldp.org/LDP/khg/HyperNews/get/fs/vfstour.html

И да: вышеуказанная програмулина (коротая ограничивает кэш на запись и на чтение) весьма успешно работает, free -m показывает как надо (т.е. отжирается только указанный кэш или 4Мб, если не указано), плюс там есть разные параметры у скрипта запуска.

В общем, качай http://code.google.com/p/pagecache-mangagement/ и пробуй (сначала читай txt, затем компиль, затем ставь, затем читай главный *.sh).

ktulhu666 ☆☆☆
() автор топика
Ответ на: -_-' от Lindows

И да, я надеюсь Вы прочли моё сообщение анонимусу, где я поправил себя, касательно того, что VFS cache автоматически не очищается, т.к. он является lazy delete (удаляется при первой необходимости)?


И да - для очистки кэша выполняйте: sync && echo 1 > /proc/sys/vm/drop_caches && echo 2 > /proc/sys/vm/drop_caches && echo 3 > /proc/sys/vm/drop_caches

sync обязательно нужен, иначе могут не сброситься dirty_pages.

ktulhu666 ☆☆☆
() автор топика
Ответ на: комментарий от ktulhu666

Что касается двух кэшей, то, как я и говорил, есть кэш VFS (причём для директорий, inode и страниц файлов, для каждого отдельно, можно отдельно очистить), а есть кэш блочного устройства. Это разные вещи, одна под другой.

Начинаю понимать +)(честно говоря, сначала предыдущий пост мне показался набором букв, но сейчас получше)

Весьма интересно, получается, что crgoups и кэш ограничивает, иначе cached заняло бы всю память. Попробуй сделать тоже самое без занесения в группу, посмотри, как изменится кэш.

Да, разумеется, во приведенных мной примерах я проверял что будет без занесения в группу - результат очевиден: вся память занимается кешем во всех трех случаях.

Тоесть получается что memory cgroups может контролировать только vfs cache, но не может кеш блочного устройства?

В общем, качай http://code.google.com/p/pagecache-mangagement/ и пробуй (сначала читай txt, затем компиль, затем ставь, затем читай главный *.sh).

Уже смотрю..

Lindows
()
Ответ на: комментарий от ktulhu666

И да, я надеюсь Вы прочли моё сообщение анонимусу, где я поправил себя, касательно того, что VFS cache автоматически не очищается, т.к. он является lazy delete (удаляется при первой необходимости)?

Ну, это я уже и так знал +)

А вот зачем три раза писать в drop_caches? echo 3 > /proc/sys/vm/drop_caches сбрасывает сразу все ведь...

Lindows
()
Ответ на: комментарий от Lindows

А вот зачем три раза писать в drop_caches? echo 3 > /proc/sys/vm/drop_caches сбрасывает сразу все ведь...

На всякий случай :)

А чего удивительного, что cgroups не контролирует кэш блочного устройства? Подумайте внимательнее: какой процесс открыл блочное устройство? Ядро (точнее модуль FS). И только уже над уровнем модуля FS идёт VFS. Очевидно, что «клиент» тут - модуль ядра, поэтому Вы можете урезать кэш блочного устройства только глобально :) Но чего он Вам сдался то? Он занимает не более 10мб обычно, причём сбрасывается весьма часто для консистентности ФС.

Таки попробуйте то приложение, ссылку на которое я Вам дал.

ktulhu666 ☆☆☆
() автор топика
Ответ на: комментарий от Lindows

Да, разумеется, во приведенных мной примерах я проверял что будет без занесения в группу - результат очевиден: вся память занимается кешем во всех трех случаях.

В смысле во всех трёх? cached - это кэш VFS, buffers - это кэш блочного устройства. Если Вы всё скопипастили верно, то у Вам всё очень хорошо ограничивается, т.к. память засралась кэшем ровно насколько, сколько памяти было выделено приложению.

ktulhu666 ☆☆☆
() автор топика
Ответ на: комментарий от ktulhu666

Эм...

Во втором примере, который я приводил, где чтение из файла в /dev/null, кеш забит полностью, несмотря на то, что процесс лежит в группе, но кеш тут в used, и прекрасно сбрасывается через echo 3 > /proc/sys/vm/drop_caches.

# free -m
             total       used       free     shared    buffers     cached
Mem:          7907       6543       1364          0         20        558

Но почему не в cached ? Вообще, чем отличается чтение файла файерфоксом и заливкой его в сеть от `cat file > /somewhere` ?

Почему фф не выходит из cgroups, а банальное чтение/копирование с помощью cat/dd может так делать, после чего память оказывается не в cached?

Как я уже говорил при всех тестах без использования cgoup такой картины не было и cached забивался до максимума как и положено.

Теперь pagecache managment.. для начала простое чтение и запись

Эталон памяти

# free -m
             total       used       free     shared    buffers     cached
Mem:          7906        145       7761          0          0         14
-/+ buffers/cache:        130       7775
Swap:         1999          0       1999     1999          0       1999

простое чтение и запись, без контрльных групп или скриптов с гуглокода )

запись
# cat /dev/zero > /desu
# free -m
             total       used       free     shared    buffers     cached
Mem:          7906       7665        240          0         13       7317
-/+ buffers/cache:        334       7571
Swap:         1999          0       1999
//чтение
cat /desu > /dev/null
# free -m
             total       used       free     shared    buffers     cached
Mem:          7906       6983        922          0          0       6838
-/+ buffers/cache:        144       7761
Swap:         1999          0       1999
обычная ситуация, вся память забита кешем

Чтение и запиись с pm, без cg

# pagecache-management.sh cat /dev/zero > /desu
# free -m
             total       used       free     shared    buffers     cached
Mem:          7906        163       7743          0          3         26
-/+ buffers/cache:        133       7773
Swap:         1999          0       1999
с записью все круто, скрипт работает

теперь чтение

# pagecache-management.sh cat /desu > /dev/null
# free -m
             total       used       free     shared    buffers     cached
Mem:          7906       4266       3639          0          0         15
-/+ buffers/cache:       4250       3655
Swap:         1999          0       1999

и опять какая то хрень, почему оно в used полезло ?! libastral cache system.

теперь обе, шибко инновационные технологии вместе. в группе 400 метров рамы.

запись

# pagecache-management.sh cat /dev/zero > /desu
# free -m
             total       used       free     shared    buffers     cached
Mem:          7906        157       7748          0          1         23
-/+ buffers/cache:        133       7773
Swap:         1999          0       1999
запись не кешируется.

ну и последниее чтение -_-

# pagecache-management.sh cat /desu > /dev/null
# free -m
      total       used       free     shared    buffers     cached
Mem:          7906       4551       3354          0          1         16
-/+ buffers/cache:       4534       3372
Swap:         1999          0       1999

Ну и что это за ерунда ?) И если это не кеш блочного устройства и не page-cache, то что же это?

В любом случае, этот скрипт работает так же, как и memory cgroup.

Lindows
()
Ответ на: комментарий от ktulhu666

эм.. ну да, более того, я похожий предмет пару часов назад съел +)

Lindows
()
Ответ на: комментарий от Lindows

Так

Последний тест на сегодня:

# free -m
             total       used       free     shared    buffers     cached
Mem:          7906        729       7176          0          0        125
-/+ buffers/cache:        603       7302
Swap:         1999          0       1999

# du -h /mnt/desu 
13G     /mnt/desu

# cat /mnt/desu > /dev/null

# free -m
             total       used       free     shared    buffers     cached
Mem:          7906       1113       6792          0          1        507
-/+ buffers/cache:        605       7301
Swap:         1999          0       1999

отлично, cgroups работает как надо и ограничивает кеш )

В чем секрет?)

Файловая система тут не ext4. Я проверил на nilfs2 и btrfs, все работает как надо.

Так что можно сделать следующие выводы:

1. ext4 слинковано с libastral.so, что дает возможность в некоторых случаях кешировать файлы при чтении даже под контролем memory cgroup и гиперкостылей.

2. memory cgroup отлично ограничивает кеш и нет необходимости во всяких костылях. грубо говоря размер кеша = лимит на память в группе - занятая память процессами в группе

//по хорошему надо бы сделать багрепорт... хотя, может это фича такая?

//ушел спать -_-

Lindows
()
Ответ на: комментарий от Lindows

Обновите ядро до последнего. Аномалии ext4 точно были не раз подтверждены? Для других FS были абсолютно те же условия? Не имею пока возможности проверить на ext4, т.к. использую сейчас только рейзер и не дома.

И да - Вы сказали, что использовали nilfs2. Вы её только сейчас использовали или вообще ей пользовались? Насколько она готова? Уже нормально после аварийного отключения работает? Как с производительностью? Они уже сделали нормальную автоочистку, блокировку очистки и дефрагмегментацию (или как бы это назвать... деснапшетизацию :) ) для конкретных файлов?

ktulhu666 ☆☆☆
() автор топика

Как ограничить размер кэша для каждого приложения от одного пользователя, плюс ставить им самый низкий приоритет IO по-дефолту, а иксам, компизу, пульсу, плееру ставить самый высокий?

Ограничить кэширование невозможно, но можно, если есть исходники, добавить вызовы posix_fadvise() с POSIX_FADV_DONTNEED

плюс ставить им самый низкий приоритет IO по-дефолту

man ionice

juk4windows
()
Ответ на: комментарий от ktulhu666
./pagecache-management.sh mc
./pagecache-management.so

Aborted

MC под этим не пашет, пичалька.

juk4windows
()
Ответ на: комментарий от ktulhu666

Ядро и так последнее

Для других FS были абсолютно те же условия?

создал lv на 15 гигов и по почереди форматировал его в nilfs2, btrfs и ext4. Сейчас еще на xfs проверил.

Но вот на убунтушном ядре 3.2 не воспроизводится.

nilfs2 юзал полгода назад «на посмотреть», ext4 без журнала оказалась быстрее на еммц. очистку делал вообще вручную, да и то всего 2-3 раза.

Lindows
()
Ответ на: комментарий от Lindows

Т.е. баг только c ext4 и только на новом ядре? А после сброса кэш уходит из памяти или она засраной остаётся?

Ну и как показалал себя nilfs2? Вы на генте сидите?

ktulhu666 ☆☆☆
() автор топика
Ответ на: комментарий от ktulhu666

Т.е. баг только c ext4 и только на новом ядре?

Сейчас еще проверил на арме с ядром 3.1, тут воспроизводится, правда тут ядро сильно патченое, так что не все так просто..

А после сброса кэш уходит из памяти или она засраной остаётся?

Сбрасывается как обычно.

Ну и как показалал себя nilfs2?

Я им не долго пользовался, около месяца, но фс работала и вроде не падала +)

Вы на генте сидите?

Ну а где ж еще..

Lindows
()
Ответ на: комментарий от Lindows

В общем, я нашел в чем причина, это оказался zcache.

Пересобрал ведро на нетбуке и десктопе с отключенным zcache и память больше не уходит в либастрал с ext4 =)

В любом случае, самое главное что memory cgroup ограничивает кеш как и обычную память и это Ъ !

//надо почаще юзать всякую ерунду из staging ...

Lindows
()
Ответ на: комментарий от Lindows

Прочитал, не знал, что такое вообще есть. Думаю, должен быть весьма полезным, если верить описанию. Его можно как-то отключить без перекомпиляции? Или это вообще модуль ядра и его тупо не подгружать?

Используете ли Вы ещё какие-то интересные фитчи?

ktulhu666 ☆☆☆
() автор топика
Ответ на: комментарий от Lindows

Как я понял, zcache часть cleancache. Последний нужен как фреймфорк для доступа других (как zcache) подсистем кэширования к кэшу, который заменяет (или не заменяет, а дополняет (частично дублирует)!?) кэш VFS. При этом он использует собственную память, поэтому и видится, как used (фактически, это видится, как ядро, отжирающее память). Можете как-то протетить, как он себя ведет п?

Кстати, можете использовать /dev/mem для получения небольшого, но очень быстрого псевнослучайного файла.

Для заполнения памяти (чтобы проверить автовытеснение zcache) можно использовать команду python -c «some_str = ' ' * ( 1524 * 1000000 / 32 )» ,где 1524 количество мегабайт. (Внимание: при активированных технологиях дедубликации памяти или zram результат будет неверный. В таком случае нужно создать ramdisk или memdisk и кинуть туда /dev/urandom или /dev/mem, после чего замерить кол-во МБ. Но лучше отключить эти технологии на время.)

ktulhu666 ☆☆☆
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.