Как использовать пространство подкачки только для экстренных случаев?

41

У меня есть ноутбук Debian (Buster) с 8 ГБ оперативной памяти и 16 ГБ подкачки. Я выполняю очень долгое задание. Это означает, что мой ноутбук оставался включенным последние шесть дней, пока он работает.

При этом мне периодически нужно использовать свой ноутбук как ноутбук. Это не должно быть проблемой; долгосрочное задание связано с вводом / выводом, работает через что-то на жестком диске USB и не занимает много ОЗУ (<200 МБ) или ЦП (<4%).

Проблема в том, что когда я вернусь к своему ноутбуку через несколько часов, он будет очень вялым и может занять 30 минут, чтобы вернуться в нормальное состояние. Это настолько плохо, что краш-мониторы помечают свои приложения как замороженные (особенно окна браузера), и все начинает некорректно падать.

Если посмотреть на системный монитор, то из 2,5 ГБ, используемых примерно наполовину, происходит свопинг. Я подтвердил, что это проблема, удалив пространство подкачки ( swapoff /dev/sda8). Если я оставлю это без пространства подкачки, оно вернется к жизни почти мгновенно, даже через 24 часа. Со свопом это практически кирпич за первые пять минут, оставленный всего на шесть часов. Я подтвердил, что использование памяти никогда не превышает 3 ГБ, даже когда я в отъезде.

Я попытался уменьшить swappiness ( см. Также: Википедия ) до значений 10и 0, но проблема все еще сохраняется. Похоже, что после дня бездействия ядро ​​считает, что весь графический интерфейс больше не нужен, и стирает его из оперативной памяти (подменяет его на диск). Долгосрочная задача - чтение огромного файлового дерева и чтение каждого файла. Так что ядро ​​может запутаться, думая, что кеширование поможет. Но на одном жестком диске объемом 2 ТБ USB HD с ~ 1 млрд. Имен файлов дополнительная ГБ ОЗУ не сильно повысит производительность. Это дешевый ноутбук с вялым жестким диском. Он просто не может загрузить данные обратно в оперативную память достаточно быстро.

Как я могу сказать Linux использовать пространство подкачки только в чрезвычайной ситуации? Я не хочу бежать без свопа. Если происходит что-то неожиданное, и ОС внезапно требуется несколько дополнительных ГБ, тогда я не хочу, чтобы задачи убивались, и предпочел бы начать использовать swap. Но в данный момент, если я оставлю swap включенным, мой ноутбук просто не сможет быть использован, когда мне это нужно.

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


Что такое чрезвычайная ситуация? - Тебе правда нужно спросить? ... Надеюсь, ты никогда не окажешься в горящем здании!

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


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

Филип Коуллинг
источник
11
Определите «чрезвычайную ситуацию» и расскажите о том, как это отличается от любой обычной ситуации, когда будет использоваться своп.
Кусалананда
4
Я хотел знать, хотите ли вы каким-либо образом определить специальный тип «экстренного события» за пределами допустимого диапазона, который позволил бы ядру использовать своп, но этот своп иначе не использовался бы. AFAIK - постраничная память - это что-то медленное и когда-либо выполняемое только «в экстренных случаях», и «подкачка» - единственное, что вы можете использовать для настройки этого поведения (но я не пользователь Linux).
Кусалананда
2
Нет, это не правильно. Это не только в чрезвычайных ситуациях. По крайней мере, я подумал, что мой вопрос прояснил, что я использовал только 3 ГБ из 8 ГБ ... Это вряд ли чрезвычайная ситуация, но ядро ​​все равно меняется. Я предлагаю вам прочитать о swappiness и окружающих темах. Существует довольно много дискуссий о различных причинах обмена. Вполне вероятно, что я спрашиваю о концепции, которой нет в ядре, но мои причины для этого достаточно обоснованы ..
Филип Коулинг,
4
Я признаю, что совет всегда был «никогда не бегать без обмена». Но размеры памяти превышают скорость чтения / записи масштабируемого жесткого диска (HDD, а не SSD), что означает, что подкачка становится все более плохой идеей. Некоторые считают, что 8 ГБ ОЗУ и 8 ГБ свопа будут выполнять 16 ГБ ОЗУ + 0 свопов. Если это действительно так, то с ядром Linux что-то не так.
Филипп Коулинг
7
@Philip Couling: Нет, дело в том, что 16 ГБ ОЗУ + 16 ГБ подкачки превзойдут 16 ГБ и 0 подкачки - особенно когда вашему коду требуется 17 ГБ памяти :-)
jamesqf

Ответы:

11

В наше время такой огромный обмен часто является плохой идеей. К тому времени, когда ОС поменяла местами всего несколько ГБ памяти, ваша система уже ползла до смерти (как вы видели)

Лучше использовать zramс небольшим резервным разделом подкачки . Многие операционные системы, такие как ChromeOS, Android и различные дистрибутивы Linux, позволяют zram по умолчанию годами, особенно для систем с меньшим объемом оперативной памяти. Это гораздо быстрее, чем подкачка на жестком диске, и в этом случае вы четко чувствуете реакцию системы. Меньше так на SSD, но в соответствии с результатами тестов здесь все еще кажется быстрее даже с алгоритмом lzo по умолчанию. Вы можете перейти на lz4 для еще лучшей производительности с немного меньшей степенью сжатия. Скорость декодирования почти в 5 раз выше, чем у lzo, согласно официальному тесту

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

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

дальнейшее чтение

phuclv
источник
Просто чтобы я понял, вы говорите, что я могу создать zramблочное устройство, использовать его в качестве свопа, с свопом с более низким приоритетом в качестве раздела жесткого диска?
Филипп Коулинг
@PhilipCouling, если вы используете жесткий диск, тогда да, безусловно, вы должны использовать Zram или аналогичные решения. Приоритет подкачки должен быть ниже, чем у zram, так что Linux сначала пытается использовать zram, а затем рассмотрит своп. Если вы используете Ubuntu, тогда пакет zram-config уже позаботится о настройках приоритетов для вас
phuclv
3
Я принимаю этот ответ, потому что он, кажется, делает именно то, что я просил. Если у меня по-прежнему включен своп на 16 ГБ с пониженным приоритетом, то ядро ​​будет использовать его только после исчерпания zswap. IE: «в чрезвычайной ситуации». Обратите внимание на debian-buster, это очень легко установить, просто установив zram-tools.
Филипп Коулинг
25

Одно из исправлений заключается в том, чтобы убедиться, что контроллер памяти cgroup включен (я думаю, что он используется по умолчанию даже cgroup_enable=memoryв самых последних версиях ядра, в противном случае вам нужно будет добавить его в командную строку ядра). Затем вы можете запустить интенсивную задачу ввода-вывода в cgroup с ограничением памяти, что также ограничивает объем кеша, который он может использовать.

Если вы используете systemd, вы можете установить +MemoryAccounting=yesи MemoryHigh/ MemoryMaxилиMemoryLimit (зависит от того, используете ли вы cgroup v1 или v2) в модуле или фрагмент, содержащий его. Если это срез, вы можете использовать systemd-runдля запуска программы в срезе.

Полный пример с одной из моих систем для запуска Firefox с ограничением памяти. Обратите внимание, что здесь используется cgroups v2, и он настроен как мой пользователь, а не как root (одно из преимуществ v2 по сравнению с v1 заключается в том, что делегирование этого не-root безопасно, поэтому systemd делает это).

$ systemctl --user cat mozilla.slice 
# /home/anthony/.config/systemd/user/mozilla.slice
[Unit]
Description=Slice for Mozilla apps
Before=slices.target

[Slice]
MemoryAccounting=yes
MemoryHigh=5G
MemoryMax=6G

$ systemd-run --user --slice mozilla.slice --scope -- /usr/bin/firefox &
$ systemd-run --user --slice mozilla.slice --scope -- /usr/bin/thunderbird &

Я нашел, чтобы заставить пользователя работать, я должен был использовать часть. Система первая работает, просто помещая опции в сервисный файл (или используя systemctl set-propertyсервис).

Вот пример сервиса (с использованием cgroup v1), обратите внимание на последние две строки. Это часть системного (pid = 1) экземпляра.

[Unit]
Description=mount S3QL filesystem
Requires=network-online.target
After=network-online.target

[Install]
WantedBy=multi-user.target

[Service]
Type=forking
User=s3ql-user
Group=s3ql-user
LimitNOFILE=20000
ExecStartPre=+/bin/sh -c 'printf "S3QL_CACHE_SIZE=%%i\n" $(stat -c "%%a*%%S*.90/1024" -f /srv/s3ql-cache/ | bc) > /run/local-s3ql-env'
ExecStartPre=/usr/bin/fsck.s3ql  --cachedir /srv/s3ql-cache/fs1 --authfile /etc/s3ql-authinfo  --log none «REDACTED»
EnvironmentFile=-/run/local-s3ql-env
ExecStart=/usr/bin/mount.s3ql --keep-cache --cachedir /srv/s3ql-cache/fs1 --authfile /etc/s3ql-authinfo --cachesize ${S3QL_CACHE_SIZE} --threads 4
ExecStop=/usr/bin/umount.s3ql /mnt/S3QL/
TimeoutStopSec=2m
MemoryAccounting=yes
MemoryLimit=1G

Документация находится в systemd.resource-control(5).

derobert
источник
1
Разве вы не можете сделать что-то сопоставимое и портативное, просто используя ulimit?
Old Pro
1
@OldPro не совсем. Во-первых, AFAIK не ограничивает общее использование памяти, включая кэш страниц (это чрезмерное использование). Во-вторых, ulimit для памяти зависит от процесса, cgroups работают, даже если долгосрочная задача разветвляется.
Дероберт
Я думал, что причина учета памяти по умолчанию на более новых системах связана с изменением в systemdверсии 238 .
Sourcejedi
1
@sourcejedi, это относительно недавно. Когда контроллер памяти был впервые представлен, просто иметь его (даже не использовать) было достаточно дорого, так как некоторые дистрибутивы по крайней мере отключили его по умолчанию, и вам пришлось передать этот аргумент командной строки ядра, чтобы включить его. Проблемы с производительностью были исправлены, так что изменились, и в последнее время systemd тоже активирует его по умолчанию.
Дероберт
14

Похоже, что после дня бездействия ядро ​​считает, что весь графический интерфейс больше не нужен, и стирает его из оперативной памяти (подменяет его на диск).

Ядро делает правильную вещь, веря в это. Почему он хранит неиспользуемую 1 память в ОЗУ и, таким образом, тратит ее впустую вместо того, чтобы использовать ее как кеш или что-то еще?

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

Если вы знаете, когда вам нужно будет повторно использовать свой ноутбук заранее, вы можете использовать atкоманду (или crontab), чтобы запланировать очистку подкачки ( swapoff -a;swapon -a).

Поскольку очистка подкачки может быть излишней, и даже вызвать убийцу OOM, если по какой-то причине не все умещается в ОЗУ, вы можете просто «отменить» 2 все, что связано с запущенными приложениями, которые вы хотите восстановить.

Один из способов сделать это - подключить отладчик, подобный gdbкаждому из затронутых процессов, и запустить генерацию дампа ядра:

# gdb -p <pid>
...
generate-core-dump /dev/null
...
quit

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

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

Посмотрите, как вы очищаете буферы и кеш в системе Linux? для деталей.

1 Неиспользуемый в том смысле, что более активно не используется в течение значительного периода времени, память по-прежнему актуальна для своих владельцев.
2 Верните обратно страницы ОЗУ, хранящиеся в области подкачки.

jlliagre
источник
2
Спасибо за мысль о возможных причинах. Я добавил немного к вопросу, так как это может быть актуально. Интересно, есть ли способ снизить приоритет кэширования по сравнению с собственной памятью приложения.
Филипп Коулинг
5
«Я не думаю, что ядро ​​Linux безвозмездно или упреждающе выгружает страницы, поэтому, если оно это делает, это должно означать сохранение чего-то другого в ОЗУ, что повышает производительность». - Я думаю, что эта формулировка немного двусмысленна. Ядро определенно будет записывать страницы для свопинга, когда у него есть такая возможность (например, имеется небольшой дисковый ввод-вывод). Однако он не удалит их из оперативной памяти. Таким образом, вы получаете лучшее из обоих миров: если вам снова понадобятся эти страницы, они уже находятся в оперативной памяти, и ничего не поделаешь. Если возникает чрезвычайная ситуация (как выразился ОП), вам просто нужно освободить эти страницы в ОЗУ, потому что
Jörg W Mittag
3
... они уже в обмене. И именно поэтому вы не хотите использовать своп «только в чрезвычайных ситуациях», потому что во время чрезвычайной ситуации система уже находится в состоянии стресса, и последнее, что вам нужно, это добавить к этому большое количество дискового ввода-вывода.
Йорг Миттаг
2
То, что заставляет его поменяться, это, вероятно, длительный процесс: он обращается к файлам на диске. Эти файлы в памяти будут использоваться более недавно, чем память графического интерфейса.
jpmc26
3
@ JörgWMittag У вас есть доказательства того, что ядро ​​Linux, когда использование ввода-вывода низкое, предпочтительно записывает страницы в область подкачки «на всякий случай», то есть не освобождая их из ОЗУ?
июля
10

Является ли процесс, которым вы управляете, чем-то, что вы создали сами?

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

Постарайтесь минимизировать эффекты кэширования ввода-вывода в этот файл и из него. В целом, это снижает производительность, но полезно в особых ситуациях, например, когда приложения выполняют свое собственное кэширование. Файловый ввод / вывод осуществляется непосредственно в / из буферов пространства пользователя. Флаг O_DIRECT сам по себе пытается передавать данные синхронно, но не дает гарантии флага O_SYNC, что данные и необходимые метаданные передаются. Чтобы гарантировать синхронный ввод-вывод, в дополнение к O_DIRECT необходимо использовать O_SYNC. Смотрите примечания ниже для дальнейшего обсуждения.

Уилл Кроуфорд
источник
1
Другой похожий (но, вероятно, более простой, так как я почти уверен, что O_DIRECT имеет ограничения на выравнивание, и вы будете снижать производительность, если ваши чтения не велики), является фальшивым, чтобы сообщить ядру, что вам больше не понадобятся эти данные, удалив их из кеш страниц. (по телефону или предоставлю ссылки, извините)
Дероберт
1
@derobert Во-первых, эта nocacheкоманда - удобный способ сделать это. (Он использует LD_PRELOAD для перехвата некоторых вызовов libc).
Sourcejedi
6

Вот идея, которую я сам не пробовал (и мне жаль, что сейчас у меня нет времени экспериментировать с этим).

Предположим, вы создали небольшую виртуальную машину с объемом памяти всего 512 МБ для фонового процесса. Я не уверен, что вы захотите, чтобы у вас был какой-либо обмен, ваш вызов и отключить обмен на вашей хост-системе.

X Тянь
источник
3

Удалите своп или уменьшите его примерно на 20% ( может варьироваться в зависимости от системы ), так как в последнее время ОС больше не используют своп так же, как это было несколько лет назад. Это, вероятно, отвечает на некоторые ваши вопросы:

-> Официальный redhat.com

некоторая информация о Red Hat ниже,

В прошлом некоторые поставщики приложений рекомендовали подкачку размером, равным ОЗУ, или даже вдвое больше ОЗУ. Теперь давайте представим вышеупомянутую систему с 2 ГБ оперативной памяти и 2 ГБ подкачки. База данных в системе была по ошибке настроена для системы с 5 ГБ ОЗУ. Как только физическая память израсходована, своп используется. Поскольку диск подкачки намного медленнее, чем ОЗУ, производительность снижается, и происходит перегрузка. На этом этапе даже вход в систему может стать невозможным. По мере того, как в память записывается все больше и больше памяти, в конечном итоге физическая память и память подкачки полностью истощаются, и запускается OOM-убийца, убивая один или несколько процессов. В нашем случае доступно довольно много свопов, поэтому время плохой работы очень велико.

а также

https://wiki.debian.org/Swap

часть ссылки на Debian выше,

Информация и соображения, связанные с объемом свопа:

«Рекомендованный объем пространства подкачки традиционно был вдвое больше объема системной памяти. Со временем он изменился в полтора раза, системная память, оба ответа являются приличными базовыми показателями, но с течением времени становятся все менее и менее полезными ответами на вопрос. Существует много переменных в вашей системе и предполагаемом использовании, которые будут определять доступный системный своп, который вы захотите получить ».

Вы можете попробовать:

«Лучший способ отключить своп в Linux»


Личная заметка:


Так как у меня 6 ГБ ОЗУ и во всех моих последних ОС Linux. Я никогда не видел никаких признаков использования свопа. Я определил, что должен отключить его либо из-за недостатка места (несколько гигабайт), а также из-за того, что это иногда замедляло мою систему.

Tyþë-Ø
источник
1
В прошлом некоторые поставщики приложений рекомендовали подкачку размером, равным ОЗУ, или даже вдвое больше ОЗУ. Я чувствую себя намного старше, видя это, каким-то образом ... Хотя у меня все еще есть один из жестких дисков с барьером ~ 528 МБ, а также 2,5 ГБ, как-то эта цитата - ну, это что-то очень давно ... Хотя интересная цитата и это может объяснить, почему я видел подобные проблемы несколько лет назад. Я полагаю, что использовал sysctl, чтобы исправить это, но я точно не помню, какие настройки были, если это было накануне.
Прифтан