Выберите продукт

Linux swap usage: почему система свопит при свободной RAM и как это диагностировать (vmstat, swappiness, PSI)

Разбираем, почему Linux может активно использовать swap даже при видимой «свободной» RAM: роль page cache, reclaim, swappiness и лимитов cgroup. Даю практику диагностики через vmstat si/so, PSI, /proc/meminfo и /proc/vmstat и варианты действий — от zram до настройки swap и OOM.
Linux swap usage: почему система свопит при свободной RAM и как это диагностировать (vmstat, swappiness, PSI)

Зачем вообще нужен swap и почему «свободная RAM» — не аргумент

Swap в Linux — это не «память на случай, когда всё плохо», а часть общей политики управления памятью. Ядро постоянно балансирует между анонимной памятью (heap/stack процессов), файловым кэшем (page cache), slab-объектами, буферами и другими потребителями. Поэтому ситуация free ram but swapping часто нормальна: «свободно» в выводе утилит означает «не занято прямо сейчас», но не гарантирует, что память доступна без потерь производительности.

Ключевая мысль: Linux старается держать RAM полезно занятой (например, кэшем файлов). При этом он может заранее вытеснять часть «холодной» анонимной памяти в swap, чтобы сохранить page cache, подготовиться к будущим аллокациям, снизить фрагментацию или уложиться в лимиты cgroup.

Swap-активность сама по себе не является проблемой. Проблема — это задержки из‑за постоянного reclaim/IO или внезапные убийства процессов OOM, когда память заканчивается «по факту», а не «по цифрам».

Быстрый чек-лист: что посмотреть в первую минуту

Когда вы видите рост swap usage или жалобы на «тормоза», начните с проверки: есть ли реальная активность свопинга прямо сейчас (а не просто занятый swap), есть ли давление по памяти (PSI), не ограничивает ли вас cgroup, и не упирается ли swap в медленный диск/хранилище.

  • Swap занят или именно «шевелится»?
  • Есть ли stalls по PSI для memory?
  • Есть ли контейнеры/systemd-слайсы с жёсткими лимитами?
  • Какой носитель у swap (и что с IO)?
  • Используется ли zram и не стало ли CPU узким местом?

Если вы администрируете проекты на VDS, полезно заранее заложить мониторинг PSI и swap-in: при дефиците RAM это быстрее всего выдаёт реальную деградацию, а не «красивые» проценты занятости.

Вывод vmstat с полями si и so для диагностики свопинга

Как читать swap usage правильно: занято — не значит «свопим»

Важно различать две ситуации:

  • Swap занят — в нём лежат страницы, выгруженные раньше. Это может быть «исторический след» пиков нагрузки и вообще не мешать.
  • Идёт свопинг сейчас — страницы активно пишутся/читаются. Это уже нагрузка на диск и потенциальные задержки, особенно при swap-in.

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

vmstat: ключевые поля si/so и как не ошибиться

Для диагностики в реальном времени удобно начать с vmstat (часто ищут именно «vmstat si so»):

vmstat 1

Смотрите на:

  • si — swap in: страницы читаются из swap в RAM. Обычно это самое болезненное (даёт latency).
  • so — swap out: страницы пишутся в swap. Само по себе может быть терпимо, если это не фон и диск быстрый.
  • r, b — очереди на выполнение и блокировки (косвенно указывают на «залипание»).
  • wa — ожидание IO (полезно в связке с si/so).

Практическая интерпретация:

  • Высокий so при низком si: ядро «разгружает» анонимную память (часто после всплеска). Может быть нормальным.
  • Регулярный высокий si: процессы постоянно «достают» страницы из swap. Почти всегда даёт лаги.
  • si и so растут вместе и постоянно: типичный thrashing — памяти объективно не хватает или лимиты cgroup слишком жёсткие.
FastFox VDS
Облачный VDS-сервер в России
Аренда виртуальных серверов с моментальным развертыванием инфраструктуры от 195₽ / мес

swappiness: что делает параметр и почему «поставить 1» — не универсальный совет

swappiness — это не «включатель swap», а коэффициент, влияющий на то, насколько охотно ядро будет вытеснять анонимную память по сравнению с освобождением page cache. Диапазон обычно 0–100; в современных ядрах 0 не означает «swap выключен навсегда».

Посмотреть текущее значение:

sysctl vm.swappiness

Временно изменить (до перезагрузки):

sysctl -w vm.swappiness=10

Ориентиры по практике:

  • 1–10 — чаще для latency-чувствительных сервисов (веб/API), где swap нужен как «подушка», но не как рабочая область.
  • 20–40 — умеренный вариант для смешанных нагрузок.
  • 60+ — иногда уместно, если важнее удержать файловый кэш и есть «холодные» страницы, к которым редко возвращаются.

Почему опасно бездумно занижать swappiness: если вы фактически запрещаете ядру выгружать «холодную» анонимку, оно может агрессивнее чистить page cache. Итог — чтение файлов становится дороже, аллокации нестабильнее, а в контейнерах при жёстких лимитах вы быстрее увидите OOM.

/proc/meminfo: какие строки помогают понять «почему свопит»

/proc/meminfo — базовый источник правды. Снимите состояние одной командой:

grep -E 'MemTotal|MemFree|MemAvailable|Buffers|Cached|SwapTotal|SwapFree|AnonPages|Active\(|Inactive\(|SReclaimable|Shmem|Dirty|Writeback' /proc/meminfo

На что смотреть в первую очередь:

  • MemAvailable — лучшая оценка «сколько можно выделить без боли». Обычно важнее MemFree.
  • Cached и Buffers — файловый кэш (это не «потерянная» память).
  • AnonPages — объём анонимной памяти (то, что потенциально уходит в swap).
  • Shmem — shared memory (tmpfs, /dev/shm); бывает «тихим пожирателем» памяти.
  • SReclaimable — часть slab, которую можно reclaim (полезно при подозрении, что «ядро съедает память»).

Сценарий «free RAM but swapping» часто выглядит так: MemFree вроде неплохой, Cached большой, MemAvailable уже не так велик, а часть анонимной памяти лежит в swap — потому что ядро решило удерживать page cache.

/proc/vmstat: счётчики свопинга и reclaim, которые не видно в top

/proc/vmstat содержит накопительные счётчики с момента загрузки. Полезно смотреть динамику — прирост за 30–60 секунд, а не абсолютные значения.

egrep 'pswpin|pswpout|pgscan|pgsteal|pgfault|pgmajfault|oom_kill|compact' /proc/vmstat

Если растут:

  • pswpin и pswpout — идёт активный свопинг (особенно важен рост pswpin).
  • pgmajfault — много major page faults (часто означает чтение с диска; не только swap, но симптом неприятный).
  • pgscan* при слабом pgsteal* — reclaim «крутится», но мало что может отнять: признак давления памяти или плохого профиля нагрузки.

Memory Pressure PSI: как понять, что система реально страдает

PSI (Pressure Stall Information) отвечает на главный вопрос: простаивают ли процессы из‑за нехватки ресурса. Для памяти PSI показывает долю времени, когда задачи были вынуждены ждать из‑за reclaim/swap-in и других механизмов освобождения памяти.

Смотреть PSI по памяти:

cat /proc/pressure/memory

Обычно вывод содержит строки some и full с метриками avg10, avg60, avg300:

  • some: часть задач периодически простаивает из‑за давления памяти.
  • full: все задачи одновременно испытывают stall — это уже серьёзная деградация.

Важно: PSI может быть высоким даже при умеренном swap usage, если reclaim тяжёлый (медленный диск, много конкурирующего IO, грязные страницы, compaction). И наоборот: swap может быть занят, но PSI низкий — значит, страданий «здесь и сейчас» нет.

Пример метрик PSI по памяти в Linux и интерпретация some/full

Контейнеры и systemd: cgroup swap и «OOM при свободной памяти»

В современных дистрибутивах часто используется cgroup v2: память и swap лимитируются на уровне групп. Отсюда неожиданные ситуации, когда «на хосте ещё есть RAM», но конкретный контейнер/сервис начинает свопить или падает по OOM.

Базовые файлы в cgroup v2, которые стоит знать:

  • memory.current — текущее потребление памяти;
  • memory.max — лимит памяти;
  • memory.swap.current — текущее потребление swap;
  • memory.swap.max — лимит swap;
  • memory.events — события давления и OOM;
  • memory.pressure — PSI на уровне cgroup.

Пример для systemd-сервиса: узнать cgroup и посмотреть лимиты/события.

systemctl status your-service-name
systemctl show -p ControlGroup your-service-name

Далее подставьте путь из ControlGroup:

cat /sys/fs/cgroup/<CGROUP_PATH>/memory.max
cat /sys/fs/cgroup/<CGROUP_PATH>/memory.swap.max
cat /sys/fs/cgroup/<CGROUP_PATH>/memory.events
cat /sys/fs/cgroup/<CGROUP_PATH>/memory.pressure

Типовые кейсы:

  • memory.max маленький, swap разрешён: группа начинает свопить даже при свободной RAM на хосте — потому что «RAM кончилась» внутри лимита.
  • swap запрещён (memory.swap.max=0): при всплеске анонимной памяти получите OOM внутри cgroup, даже если на хосте swap есть.

Если вы часто упираетесь в лимиты systemd/cgroup в веб-стеке, пригодится разбор практики: как выставлять лимиты MemoryMax/CPUQuota в systemd без сюрпризов и статья про кейсы с PHP-FPM: systemd-слайсы и память для PHP-FPM.

Виртуальный хостинг FastFox
Виртуальный хостинг для сайтов
Универсальное решение для создания и размещения сайтов любой сложности в Интернете от 95₽ / мес

OOM killer: почему он срабатывает и как понять, кого и за что убили

Когда ядро не может удовлетворить запросы памяти и не может эффективно reclaim или свопить, запускается механизм OOM. В контейнерах он часто срабатывает «локально» (cgroup OOM), поэтому выглядит как загадка: «на сервере же ещё есть память».

Минимальная практика расследования:

journalctl -k -b | egrep -i 'oom|out of memory|killed process'

И проверьте memory.events нужной cgroup: там обычно видно рост счётчиков oom или oom_kill.

zram: быстрый «компрессированный swap» и когда он помогает

zram создаёт блочное устройство в RAM и хранит в нём данные в сжатом виде. Это «swap в памяти», который часто выигрывает за счёт компрессии: вместо 1 ГБ несжатых страниц иногда удаётся удержать 1.5–2 ГБ логического объёма (зависит от данных и алгоритма). Но zram не бесплатен: он тратит CPU на сжатие и распаковку.

Когда zram полезен:

  • на небольших серверах, где дисковый swap медленный или IO постоянно занят;
  • для кратковременных всплесков памяти, когда лучше потратить CPU, чем уйти в дисковый swap и получить большие задержки;
  • чтобы снизить риск OOM и «смягчить» пики.

Когда zram может навредить:

  • CPU уже на пределе и компрессия ухудшает latency;
  • нагрузка по памяти постоянная и высокая — zram будет всё время «молотить», но дефицит RAM это не исправит.

Проверить, есть ли активный zram:

lsblk | grep -i zram
swapon --show

Если хотите отдельный чек-лист именно для небольших серверов (swap, zram, пороги PSI, типовые настройки), посмотрите: память на VDS: swap и zram без мифов.

Практические сценарии и действия

1) Swap занят, но vmstat si почти 0: ничего не трогаем

Если si нулевой или почти нулевой, PSI по памяти низкий и сервисы не тормозят — не надо «срочно чистить swap». Чаще всего это след прошлого пика: страницы выгружены и лежат в swap, потому что к ним не обращаются.

2) Постоянный swap-in: ищем источник давления

Если растёт si и одновременно растут задержки, действуйте по шагам:

  1. Проверьте PSI: cat /proc/pressure/memory и подтвердите stalls.
  2. Проверьте cgroup-лимиты (в контейнерах и systemd): возможно, проблема локальная, а не системная.
  3. Сверьте /proc/meminfo: MemAvailable, AnonPages, не раздувается ли Shmem.
  4. Посмотрите /proc/vmstat: растут ли pswpin, pgmajfault, pgscan*.
  5. Дальше выбирайте действия: оптимизация приложения (утечки/кэши), увеличение RAM, пересмотр лимитов, zram, настройка swap.

3) «Свопит при свободной памяти»: норма или конфигурационная проблема

Обычно причина одна из трёх:

  • нормальная политика: большой page cache, а «холодная» анонимка выталкивается (особенно при умеренном swappiness);
  • cgroup-эффект: группа упёрлась в memory.max и начала свопить, хотя хост свободен;
  • реальный дефицит доступной памяти: MemFree есть, но MemAvailable мал, и давление уже началось.

Нужно ли отключать swap?

Полное отключение swap редко лучший выход. Без swap любой пик анонимной памяти быстрее приводит к OOM, ядру сложнее переживать кратковременные всплески, а ошибки лимитов в контейнерах проявляются жёстче.

Чаще разумнее: держать небольшой swap как страховку, настроить адекватный swappiness, следить за PSI и не допускать постоянного swap-in.

Мини-набор команд для регулярной диагностики (копипаста)

Собрать картину «в моменте» одной пачкой:

date
uname -a
free -h
swapon --show
vmstat 1 10
cat /proc/pressure/memory
grep -E 'MemTotal|MemFree|MemAvailable|Buffers|Cached|SwapTotal|SwapFree|AnonPages|Shmem|SReclaimable' /proc/meminfo
egrep 'pswpin|pswpout|pgscan|pgsteal|pgmajfault|oom_kill' /proc/vmstat

Если под подозрением systemd-сервис:

systemctl show -p ControlGroup -p MemoryMax -p MemorySwapMax your-service-name

Итоги: как мыслить про swap, чтобы не лечить «симптомы»

Swap usage — это след решений ядра о том, какие страницы и когда выгрузить. Сам по себе процент занятости swap не отвечает на вопрос «плохо или нет». Для админа важнее:

  • есть ли активный swap-in (смотрим vmstat и /proc/vmstat);
  • есть ли stalls по PSI (смотрим /proc/pressure/memory);
  • не ограничивает ли вас cgroup (смотрим memory.max, memory.swap.max и memory.events);
  • какой профиль нагрузки (анонимка vs файловый кэш) по /proc/meminfo;
  • что выгоднее: добавить RAM, поправить лимиты, включить/настроить zram или оптимизировать приложение.

Если нужно быстро «закрыть вопрос» на проекте, обычно проще всего начать с правильных лимитов и достаточного объёма памяти на сервере. В этом плане удобнее работать на предсказуемой конфигурации VDS, где вы контролируете swap, zram и политику systemd/cgroup под конкретную нагрузку.

Поделиться статьей

Вам будет интересно

Debian/Ubuntu: mount: wrong fs type, bad option, bad superblock — как быстро найти и исправить причину OpenAI Статья написана AI (GPT 5)

Debian/Ubuntu: mount: wrong fs type, bad option, bad superblock — как быстро найти и исправить причину

Ошибка mount: wrong fs type, bad option, bad superblock в Debian/Ubuntu может означать и простую опечатку в имени раздела, и пробл ...
Debian/Ubuntu: XFS metadata corruption и emergency read-only — пошаговое восстановление OpenAI Статья написана AI (GPT 5)

Debian/Ubuntu: XFS metadata corruption и emergency read-only — пошаговое восстановление

Если XFS-раздел внезапно стал доступен только для чтения, а сервер ушёл в emergency mode, главное — не спешить. Разберём безопасны ...
Debian/Ubuntu: как исправить Failed to fetch при apt update OpenAI Статья написана AI (GPT 5)

Debian/Ubuntu: как исправить Failed to fetch при apt update

Ошибка Failed to fetch при apt update в Debian и Ubuntu обычно связана не с самим APT, а с DNS, сетью, зеркалом, прокси, временем ...