Swap и подкачка: swapon, swappiness, когда своп - это боль

Рейтинг: 70.2% · 15 голосов
Подробный курс по диагностике и производительности Linux для админов и DevOps: с чего начать, методология USE, логи (journalctl, dmesg), процессы, CPU, память и OOM, диск и IO (iostat), сеть (ss, tcpdump), системные вызовы и strace, ltrace, perf, флеймграфы, ftrace, eBPF и bpftrace, lsof, мониторинг. Разбор каждого инструмента с чтением вывода.
Ответить
Аватара пользователя
Dmitry_SRE
Сообщения: 47
Зарегистрирован: 11 май 2026, 05:31

Swap и подкачка: swapon, swappiness, когда своп - это боль

Сообщение Dmitry_SRE »

Оглавление курса (47)
  1. С чего начать диагностику Linux: методология вместо паники
  2. Первые 60 секунд: экспресс-диагностика нагруженного сервера
  3. Методологии диагностики: USE, RED и здравый смысл
  4. Логи systemd через journalctl: где искать причину
  5. Где лежат логи Linux: /var/log, dmesg и rsyslog
  6. Источники правды: load average, /proc и /sys
  7. Процессы Linux: ps, pstree и состояния процессов
  8. Интерактивный мониторинг: top и htop
  9. Метрики процессов во времени: pidstat
  10. Приоритеты и ограничения: nice, ionice, cgroups
  11. Сигналы и зависшие процессы: kill, и что делать с D-state
  12. Загрузка CPU: user, system, iowait, steal и контекст-свитчи
  13. Диагностика CPU по ядрам: vmstat и mpstat
  14. Профилирование CPU: perf top и поиск пожирателя
  15. Частоты, троттлинг и NUMA: turbostat и numastat
  16. Память Linux: RSS, VSZ, page cache и миф о нехватке памяти
  17. Сколько памяти занято: free, /proc/meminfo и vmstat
  18. Поиск утечек и пожирателей памяти: smem, pmap, smaps
  19. Swap и подкачка: swapon, swappiness, когда своп - это боль (вы здесь)
  20. OOM killer: кто и за что убил процесс
  21. Память ядра и slab: slabtop и куда уходит RAM
  22. Подсистема ввода-вывода: путь запроса от приложения до диска
  23. Диагностика диска: iostat и чтение await, %util
  24. Кто грузит диск: iotop и атрибуция io процессам
  25. Файловые системы: df, du, иноды и куда делось место
  26. Глубокая диагностика блочного слоя: blktrace и biolatency
  27. Кеш страниц и грязные данные: dirty pages, fsync, drop_caches
  28. Сетевой стек Linux: путь пакета и где возникают задержки
  29. Сокеты и соединения: ss и netstat
  30. Захват трафика: tcpdump для диагностики сети
  31. Задержки и потери в сети: ping, mtr, диагностика латентности
  32. Сеть как источник проблем: nftables, conntrack, дропы
  33. Что такое системный вызов и зачем его трассировать
  34. strace: трассировка системных вызовов на практике
  35. strace в бою: почему программа висит, падает или тормозит
  36. ltrace: трассировка вызовов библиотек
  37. Накладные расходы трассировки и безопасные альтернативы
  38. perf: универсальный профайлер Linux
  39. Флеймграфы: визуализация профиля производительности
  40. Трассировка ядра: ftrace и trace-cmd
  41. eBPF: революция в наблюдаемости Linux
  42. Инструменты eBPF на практике: BCC и bpftrace
  43. lsof: открытые файлы, дескрипторы, кто держит файл и порт
  44. Разбор кейса: приложение тормозит - пошаговая диагностика
  45. Непрерывный мониторинг: sar, node_exporter, Grafana, Zabbix
  46. Диагностика в контейнерах: cgroups, лимиты, Docker и Kubernetes
  47. Карта инструментов и сквозной разбор инцидента производительности
Знакомая картина: сервер вроде живой, но "тормозит всем". Команды выполняются с задержкой, ssh лагает, графики CPU невысокие, а диск раскалён докрасна. Очень часто за этим стоит подкачка - swap. В этом уроке разберёмся, что такое swap в Linux, как его посмотреть и настроить, и главное - как по цифрам отличить здоровую работу от катастрофы, когда система ушла в постоянную подкачку и фактически встала. Все ориентиры даны на состояние дел в 2026 году: современное ядро 6.x, cgroup v2 по умолчанию, zram как штатный вариант.

Что такое 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
Читаем по колонкам. NAME - что используется как swap (файл или устройство). TYPE - file или partition. SIZE - общий размер. USED - сколько реально занято прямо сейчас; вот это важная цифра. PRIO - приоритет: чем больше число, тем раньше ядро берёт этот swap (отрицательные значения система раздаёт сама). То же самое в сыром виде лежит в /proc:

Код: Выделить всё

$ cat /proc/swaps
Filename     Type        Size      Used    Priority
/swapfile    file        4194300   524288  -2
Размеры тут в килобайтах. Быстрый итог по всей памяти даёт free -h: колонка Swap покажет total/used/free. Если swapon --show вообще ничего не вывел - значит подкачка не подключена. Это допустимо, своп не обязателен.

Изображение

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
В мире cgroup v2 (это дефолт на современных системах с systemd) есть ещё и per-cgroup настройка: файл memory.swappiness внутри конкретной cgroup переопределяет глобальное значение для процессов в ней. Это позволяет, например, разрешить активный своп фоновым джобам и запретить чувствительной к задержке базе - не трогая систему целиком.

Практический ориентир: на сервере с СУБД снижают до 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 (swap in - читаем из swap в RAM, КБ/с) и so (swap out - пишем в swap, КБ/с) - твой главный индикатор. Первую строку игнорируем: она усреднена с момента загрузки. В спокойной строке si/so по нулям - всё хорошо. Во второй строке si/so в тысячах КБ/с, при этом wa (wait - процент времени ожидания диска) скакнул до 80, а id (idle) упал почти в ноль. Вот это и есть thrashing: процессор простаивает, всё ждёт диск, система буксует в подкачке. Колонка b (процессы в непрерывном сне, обычно ждут I/O) тоже подросла - подтверждает диагноз. Колонка r (run queue) при этом часто остаётся низкой: налицо именно I/O-bound, а не CPU-bound затык.

Запомни правило: разовый всплеск 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=...
Строка some - хоть один процесс ждал память, full - вообще все были заблокированы (никто не работал). avg10 в десятках процентов - явный сигнал нехватки памяти и свопинга прямо сейчас. PSI удобен тем, что это понятная метрика "процент простоя из-за памяти", которую легко завести в Prometheus/node_exporter и повесить алерт - в отличие от si/so, которые приходится интерпретировать на глаз.

Когда увидел беду по 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
Колонка majflt/s (major page faults в секунду) - это обращения, которые потребовали лезть на диск, в том числе подтягивать страницы из swap. Высокий majflt/s у конкретного процесса = вот он, главный потребитель подкачки. minflt/s (minor faults) к диску не ходят, их не пугаемся. VSZ - вся виртуальная память процесса, RSS - сколько реально в RAM; смотри на RSS и majflt/s в паре.

Если на машине есть современный стек 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
Высокий PRIO=100 заставляет ядро свопить сначала в быстрый zram, а на диск - только когда тот переполнится. Алгоритм zstd - актуальный выбор по умолчанию: хороший баланс степени и скорости; lzo-rle быстрее, но жмёт слабее. Свежая фича ядер 6.x - рекомпрессия (CONFIG_ZRAM_MULTI_COMP): zram умеет дожимать холодные страницы вторым, более сильным алгоритмом, экономя ещё больше RAM. Проверяем эффективность сжатия:

Код: Выделить всё

$ zramctl
NAME       ALGORITHM DISKSIZE  DATA  COMPR  TOTAL STREAMS MOUNTPOINT
/dev/zram0 zstd            2G  680M   190M   210M       8 [SWAP]
Читаем: DISKSIZE - заявленный объём устройства. DATA - сколько несжатых данных туда положили (680M). COMPR - во что они ужались (190M). TOTAL - реальный расход RAM с накладными (210M). Сжатие почти втрое - типичный результат для zstd. Подробнее по каждому устройству - в /sys/block/zram0/mm_stat. На Astra Linux и RED OS zram тоже доступен через стандартный модуль ядра и собирается тем же способом.

Типичные грабли и заблуждения
  • "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 вместо дискового свопа) снимает боль почти даром.
👍 ❤️3 🔥1 😄 🤔1
Аватара пользователя
Blackca
Сообщения: 1
Зарегистрирован: 26 май 2026, 13:15

Re: Swap и подкачка: swapon, swappiness, когда своп - это боль

Сообщение Blackca »

Спасибо, наконец дошло, что USED и si/so это вообще про разное. У меня на сервере в swapon --show висит 1.5G, я паниковал, а si/so по нулям - значит можно выдохнуть, это просто старьё лежит?
👍1 ❤️1 🔥1 😄 🤔1
Аватара пользователя
py5abd2mw
Сообщения: 1
Зарегистрирован: 29 май 2026, 00:36

Re: Swap и подкачка: swapon, swappiness, когда своп - это боль

Сообщение py5abd2mw »

Не знал про диапазон 0-200, везде в старых гайдах пишут до 100. На нодах с zram теперь поставлю swappiness под 150 и проверю PSI. /proc/pressure/memory вообще огонь, давно искал нормальную метрику под алерт вместо гадания по si/so.
👍 ❤️1 🔥 😄 🤔1
Ответить
← Предыдущая глава
Поиск утечек и пожирателей памяти: smem, pmap, smaps
Следующая глава →
OOM killer: кто и за что убил процесс

Все главы курса «Диагностика и производительность Linux: логи, strace, perf и eBPF»

Поделиться темой: ✈ Telegram VK

Вернуться в «Диагностика и производительность Linux: логи, strace, perf и eBPF»

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и 1 гость