Что такое swap и зачем он нужен
Swap (подкачка) - это место, куда ядро может временно вытеснять страницы памяти, которые сейчас не нужны. Аналогия простая: оперативка - это рабочий стол, на нём лежит то, с чем работаешь прямо сейчас. Swap - это ящик стола: туда складываешь бумаги, которые давно не трогал, чтобы освободить место на поверхности. Когда бумага снова понадобится - достаёшь обратно.
Ключевая мысль для новичка: swap в linux - это не "дополнительная память". Классический дисковый swap в сотни и тысячи раз медленнее RAM по задержке. Подкачка нужна не для скорости, а для выживания и гигиены памяти: лучше медленно достать редкую страницу из swap, чем словить нехватку памяти и убийство процесса через OOM-killer (про OOM был отдельный разговор, тут только связь). Важный нюанс: в swap уходят только анонимные страницы (куча, стек процессов). Страницы, у которых есть копия на диске - код программ, mmap-нутые файлы, файловый кеш - в swap не пишутся, они просто сбрасываются и при нужде перечитываются из исходного файла.
Своп бывает двух видов:
- Раздел (partition) - отдельный кусок диска, размеченный под swap.
- Своп-файл (file) - обычный файл в файловой системе. Гибче: размер легко поменять, не нужно переразбивать диск. По скорости на современных ядрах разница несущественная. На btrfs своп-файл требует особой подготовки (без CoW и сжатия), на ext4/xfs работает из коробки.
Код: Выделить всё
$ swapon --show
NAME TYPE SIZE USED PRIO
/swapfile file 4G 512M -2
/dev/sda2 partition 2G 0B -3
Код: Выделить всё
$ cat /proc/swaps
Filename Type Size Used Priority
/swapfile file 4194300 524288 -2

vm.swappiness: насколько агрессивно ядро вытесняет память
Главная ручка настройки подкачки - параметр ядра vm swappiness. ВАЖНО и часто устаревает в старых статьях: на современных ядрах (начиная с 5.8) диапазон не 0-100, а 0-200 плюс ключевое слово max. Значение регулирует, насколько охотно ядро вытесняет анонимные страницы в swap вместо того, чтобы сбрасывать страницы файлового кеша. По умолчанию в большинстве дистрибутивов значение 60.
При 100 ядро считает стоимость ввода-вывода в swap и в файловый кеш примерно равной. Значения выше 100 имеют смысл, когда swap БЫСТРЕЕ файловой системы - именно так и есть с zram/zswap (об этом ниже). Грубая формула из документации ядра: если случайный доступ к swap в 2 раза быстрее, чем к ФС, ставят swappiness около 133. Это актуальная на 2026 практика для in-memory swap.
Распространённое заблуждение: "swappiness - это процент RAM, после которого начинается своп". Это не так. Это не порог занятости, а вес в формуле баланса между "выкинуть файловый кеш" и "вытеснить страницы процессов". Чем выше значение - тем охотнее ядро трогает swap.
Смотрим и меняем:
Код: Выделить всё
$ cat /proc/sys/vm/swappiness
60
# временно, до перезагрузки
$ sudo sysctl vm.swappiness=10
# постоянно
$ echo 'vm.swappiness=10' | sudo tee /etc/sysctl.d/99-swap.conf
$ sudo sysctl --system
Практический ориентир: на сервере с СУБД снижают до 1-10 (база сама лучше знает, что держать в RAM, и плохо переносит вытеснение горячих страниц). На десктопе и на узлах с zram нередко наоборот поднимают (100-180). Значение 0 не отключает swap полностью - оно лишь говорит "тяни анонимные страницы до последнего"; при реальной нехватке ядро всё равно пойдёт в swap, иначе позовёт OOM. Менять вслепую не стоит: сначала измерь, потом крути.
Ещё одна свежая деталь 2026: на ядрах 6.1+ по умолчанию работает MGLRU (Multi-Gen LRU) - переработанный алгоритм старения страниц. Он точнее отличает горячие страницы от холодных, поэтому ненужное вытеснение случается реже, а реакция на скачок нагрузки мягче. Управляется через /sys/kernel/mm/lru_gen/enabled. Помнить про него полезно: поведение свопа на новом ядре заметно умнее, чем было пять лет назад.
Когда подкачка норма, а когда боль: si/so и thrashing
Сам факт, что в USED стоит ненулевое число, паниковать не повод. Если процесс что-то загрузил при старте и больше к этому не обращается, ядро спокойно вытеснит эти страницы в swap - и они будут там лежать без вреда. Это здоровое использование подкачки: освободили RAM под кеш и активную работу.
Боль начинается, когда система входит в thrashing (буксование). Это ситуация, когда страницы вытесняются в swap и тут же читаются обратно, по кругу, без остановки. Процессор простаивает, а всё упирается в диск. Внешне - "всё висит", хотя нагрузка по CPU небольшая.
Отличить одно от другого помогает поток: не сколько лежит в swap, а сколько туда пишется и читается в секунду. Это видно в vmstat:
Код: Выделить всё
$ vmstat 1 5
procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
r b swpd free buff cache si so bi bo in cs us sy id wa st
1 0 524288 102400 20480 512000 0 0 12 30 210 450 3 1 95 1 0
2 3 786432 51200 10240 300000 4096 8192 4200 8300 5200 9800 4 6 10 80 0
Запомни правило: разовый всплеск si/so - не страшно (что-то крупное запустилось). Постоянный, секунда за секундой - это и есть катастрофа. vmstat 1 показывает картину в динамике.
Современный и более прямой инструмент для этой же диагностики - PSI (Pressure Stall Information), штатный в ядрах 4.20+ и активно используемый в 2026. Он показывает, какую долю времени задачи реально стояли в ожидании памяти:
Код: Выделить всё
$ cat /proc/pressure/memory
some avg10=42.31 avg60=18.07 avg300=6.55 total=...
full avg10=12.04 avg60=5.11 avg300=1.90 total=...
Когда увидел беду по si/so или PSI - надо найти, КТО так свопится. Помогает pidstat из пакета sysstat:
Код: Выделить всё
$ pidstat -r 1
UID PID minflt/s majflt/s VSZ RSS %MEM Command
1000 8123 12.0 340.00 920000 410000 20.1 java
Если на машине есть современный стек eBPF (bcc/bpftrace, ядро 5.x+), можно ловить виновника точечно и почти без накладных расходов. Инструменты из bcc-tools: cachestat (промахи кеша), llcstat, а для свопа полезен однострочник на bpftrace, считающий, кто триггерит major faults. В 2026 eBPF - это уже зрелая основа продакшен-наблюдаемости, и для подобной точечной охоты он часто удобнее старого strace.
zram и zswap: сжатый своп в памяти
Раз диск медленный, родилась идея: а давай свопить не на диск, а в саму RAM, но в сжатом виде. Две технологии решают это по-разному, и их часто путают.
zram создаёт в оперативке отдельное блочное устройство /dev/zram0, которое работает как самостоятельный swap, только данные в нём лежат сжатыми. Бэкенд-диск ему не нужен вообще - это идеально, когда диска под своп нет или он совсем медленный (контейнеры, embedded, ВМ, ноутбуки). Платишь процессором за сжатие, выигрываешь скорость. zram свопит в linux буквально внутри памяти. Это дефолт во многих современных дистрибутивах: Fedora ставит zram через пакет zram-generator-defaults, в systemd для этого есть генератор и юнит-механика.
zswap устроен иначе: это сжатый кеш ПЕРЕД обычным дисковым свопом. Горячее держит сжатым в RAM, а что давно не трогали - дожимает на диск. Ему обязательно нужен backing swap (раздел или файл). zram и zswap вместе не включают - оба делают сжатый кеш и будут мешать друг другу.
Поднять zram руками можно так (на практике в 2026 пользуются zram-generator/systemd-zram-setup, но для понимания механики полезно собрать вручную):
Код: Выделить всё
$ sudo modprobe zram
$ sudo zramctl --find --size 2G --algorithm zstd
/dev/zram0
$ sudo mkswap /dev/zram0
$ sudo swapon --priority 100 /dev/zram0
Код: Выделить всё
$ zramctl
NAME ALGORITHM DISKSIZE DATA COMPR TOTAL STREAMS MOUNTPOINT
/dev/zram0 zstd 2G 680M 190M 210M 8 [SWAP]
Типичные грабли и заблуждения
- "Swap тормозит, давайте его отключим". Вечный спор. Без swap при нехватке памяти система не "ужмётся" - она сразу пойдёт убивать процессы через OOM-killer, нередко не тот, что нужно. Своп даёт буфер и время среагировать. Отключать имеет смысл осознанно. Современный компромисс для нагруженных нод - не отключать своп, а поставить небольшой zram: получаешь буфер от OOM без дисковой латентности.
- Путать USED и поток. Большой USED при нулевых si/so - это просто давно вытесненное старьё, оно не вредит. Маленький USED при зашкаливающих si/so - уже беда. Смотри на динамику (si/so, PSI), не на статику.
- Свопиться при живой RAM и думать, что это глюк. При swappiness 60 ядро может вытеснять холодные страницы заранее, даже когда RAM ещё есть. Это штатно, а с MGLRU - ещё и аккуратнее. Не нравится - снижай swappiness.
- Огромный swap "чтобы хватило". Своп размером в полтерабайта не спасёт - до того как он кончится, система уже будет в безнадёжном thrashing. Своп лечит короткие пики, а не системную нехватку RAM.
- "swappiness можно крутить только до 100". Устаревшая информация. На современном ядре диапазон 0-200, и для zram/zswap значения выше 100 - норма.
- Выполни swapon --show и cat /proc/swaps. Есть ли своп? Какого типа, какой PRIO, сколько в USED? Сверь с free -h.
- Посмотри текущую агрессивность: cat /proc/sys/vm/swappiness. Помни: предел теперь 200, а не 100.
- Запусти vmstat 1 на 10 секунд в покое. Убедись, что si и so в нуле. Это твоя "норма" - запомни, как выглядит здоровая система.
- Посмотри cat /proc/pressure/memory. В покое avg10 в строке some должен быть близок к нулю.
- Запусти pidstat -r 1 и найди процесс с самым большим RSS и majflt/s.
- (Осторожно, на тестовой машине) подними swappiness повыше через sudo sysctl и понаблюдай, не начнёт ли расти USED и шевелиться so.
- Чем колонки si/so в vmstat принципиально полезнее, чем колонка USED в swapon --show?
- Что такое thrashing и по каким трём цифрам (si/so, wa, id) ты его опознаешь? Как тут помогает /proc/pressure/memory?
- В чём ключевая разница между zram и zswap, и почему их не включают одновременно?
- Параметр vm.swappiness равен 0 - означает ли это, что система не будет свопиться вообще? И каков верхний предел этого параметра на ядре 2026 года?
Swap - это страховка от OOM, а не быстрая память. Сам по себе занятый swap (USED) не страшен - страшен поток подкачки. Главный индикатор здоровья - колонки si/so в vmstat и метрика /proc/pressure/memory: ноль в покое хорошо, постоянные тысячи КБ/с и высокий PSI - это thrashing, система буксует. Виновника ищи через pidstat -r по majflt/s, на современных ядрах - точечно через eBPF. Агрессивность регулируется через vm.swappiness (дефолт 60, диапазон 0-200, для zram можно выше 100), а в cgroup v2 - ещё и пер-группно. Если диск медленный - сжатый swap через zram (а на нагруженных нодах часто просто zram вместо дискового свопа) снимает боль почти даром.