С чего начать Первые шаги трек · 15 ступеней
Linux Labs

Память и swap: free, available и кэш страниц

10 мин Ubuntu 24.04 · Linux 6.8 · procps 4.0

Как читать free: занятая и свободная память, кэш страниц и available; swap, swap-файл и vm.swappiness.

Шпаргалка

7 команд Версия для печати
  • free -h память и swap; запас — available
  • grep -E '^(Mem|Cached)' /proc/meminfo то же из ядра, КиБ
  • ps -eo pid,rss,comm --sort=-rss | head -5 кто держит больше
  • swapon --show активный swap; пусто — swap нет
  • vmstat 1 5 si и so — чтение и запись swap
  • sysctl vm.swappiness охота ядра до swap, 60 по умолчанию
  • sync; echo 3 | sudo tee /proc/sys/vm/drop_caches сбросить кэш

Обзор

Память машины делят программы, ядро и кэш файлов. free -h показывает, сколько чего. На машине тренажёра с 512 МиБ:

total used free shared buff/cache available
Mem 458Mi 153Mi 5.4Mi 964Ki 320Mi 304Mi
Swap 0B 0B 0B

Столбцы free

Столбец Что значит
total память, которой распоряжается ядро
used занято программами и ядром
free не занято ничем
shared общая память процессов и tmpfs
buff/cache кэш страниц и буферы — копии данных с диска в памяти
available сколько можно отдать новым программам без swap

total меньше 512 МиБ: часть памяти ядро забрало при загрузке под свой код и служебные таблицы (sudo dmesg | grep Memory:).

Кэш страниц и available

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

available — свободная память плюс та часть кэша, которую ядро может освободить. Это и есть запас. Опыт на машине тренажёра: прочитали много файлов, затем сбросили кэш.

Момент free buff/cache available
после cat /usr/bin/* > /dev/null 5.4Mi 320Mi 304Mi
после сброса кэша 266Mi 59Mi 304Mi

free вырос в 50 раз, а available не изменился: кэш и до сброса был доступен программам. Те же числа в КиБ — в /proc/meminfo:

text
student@ubuntu:~$ grep -E '^(Mem|Cached)' /proc/meminfo
MemTotal:         469236 kB
MemFree:            5540 kB
MemAvailable:     311944 kB
Cached:           301900 kB

Память процесса: RSS

RSS — сколько памяти процесса сейчас лежит в RAM, в КиБ. VSZ — сколько адресов он себе зарезервировал; большая часть может быть не занята. Память процессов смотрят по RSS: столбец RSS в ps, RES в top, VmRSS в /proc/<pid>/status.

text
student@ubuntu:~$ ps -o pid,rss,vsz,pmem,comm -C systemd-journald,sshd
    PID   RSS    VSZ %MEM COMMAND
    275 16792  42256  3.5 systemd-journal
    773  8244  12028  1.7 sshd

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

Swap

Swap — место на диске, куда ядро вытесняет редко нужные страницы программ, чтобы освободить память. Диск во много раз медленнее памяти: пока swap выручает, программы работают, но медленнее. Без swap при нехватке памяти ядро сразу зовёт oom-killer.

На машине тренажёра swap нет: swapon --show ничего не печатает, в free строка Swap: 0B 0B 0B. Swap бывает разделом диска или файлом; файл проще добавить и убрать.

Работу swap видно в vmstat 1: si — сколько КиБ в секунду читается из swap обратно в память, so — сколько пишется в swap. Процесс на 380 МиБ под нехваткой памяти дал такие строки (часть столбцов опущена):

r b swpd free si so wa
0 1 131688 5920 152012 150756 56
0 1 130904 5096 135084 130312 53

si и so — около 150 МиБ в секунду, wa за 50: машина больше ждёт диск, чем работает. Кто сколько держит в swap — VmSwap в /proc/<pid>/status.

vm.swappiness

Параметр ядра vm.swappiness (от 0 до 200, в Ubuntu — 60) задаёт, насколько охотно ядро при нехватке памяти вытесняет в swap страницы программ по сравнению со страницами кэша. Меньше значение — дольше программы остаются в памяти целиком. На серверах часто ставят 10.

bash
sysctl vm.swappiness                     # текущее значение
sudo sysctl vm.swappiness=10             # до перезагрузки
echo 'vm.swappiness = 10' \
  | sudo tee /etc/sysctl.d/90-swappiness.conf
sudo sysctl --system                     # применить файлы sysctl.d

Значение из файла в /etc/sysctl.d/ переживает перезагрузку. Подробно о параметрах ядра — sysctl.

Рецепты

3

Добавить swap-файл

bash
sudo fallocate -l 512M /swapfile    # файл нужного размера
sudo chmod 600 /swapfile            # читать может только root
sudo mkswap /swapfile               # разметить под swap
sudo swapon /swapfile               # включить
swapon --show
text
student@ubuntu:~$ swapon --show
NAME      TYPE SIZE USED PRIO
/swapfile file 512M   0B   -2

Чтобы swap включался при загрузке, нужна строка в /etc/fstab:

bash
echo '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstab
sudo swapoff /swapfile; sudo swapon -a; swapon --show   # проверить

swapon -a включает всё, что описано в fstab: если файл снова в списке, строка записана без опечаток. Вместо fallocate подойдёт sudo dd if=/dev/zero of=/swapfile bs=1M count=512 — дольше, но работает на любой ФС.

Три детали, на которых ошибаются:

  • Размер. 512M — это 512 МиБ (536870912 байт), 512MB — 512 000 000 байт. Перевести одно в другое — инструмент «Конвертер единиц объёма».
  • Права. chmod 600 — до swapon: иначе содержимое памяти программ сможет прочитать любой пользователь.
  • Путь в fstab. Swap-файл в fstab пишут путём /swapfile. Строка UUID=… none swap sw 0 0 для файла проходит проверку swapon -a, но при загрузке systemd ждёт устройство /dev/disk/by-uuid/…, а такие ссылки бывают только у дисков и разделов. Через 90 секунд в журнале — Timed out waiting for device, swap не включён.

Выключить swap

bash
sudo swapoff /swapfile   # страницы из swap вернутся в память

Затем убери строку из /etc/fstab и удали файл.

Сбросить кэш перед замером

bash
sync; echo 3 | sudo tee /proc/sys/vm/drop_caches

Нужно только для опыта: замерить чтение с диска, а не из кэша. Работе это не помогает, кэш наполнится снова. Запись sudo echo 3 > /proc/sys/vm/drop_caches не сработает: перенаправление делает твоя оболочка без прав root, и она отвечает Permission denied.

Неполадки

8

free почти ноль

Норма: свободную память занял кэш страниц. Смотри available. Тревога — когда мал available и растут si/so в vmstat.

Сервер тормозит, растут si и so

Памяти не хватает, ядро гоняет страницы между памятью и swap. Найди, кто держит больше всех (ps -eo pid,rss,comm --sort=-rss | head), и останови или ограничь его (MemoryMax службы, см. oom-killer). Добавить swap — отсрочка, памяти он не прибавит.

Процесс завершился, в журнале Killed process

Память кончилась, и ядро завершило процесс — разбор в oom-killer.

mkswap или swapon: insecure permissions 0644

mkswap пишет insecure permissions 0644, fix with: chmod 0600 /swapfile, swapon — insecure permissions 0644, 0600 suggested. Swap включится и так, но содержимое памяти программ сможет прочитать любой пользователь. sudo chmod 600 /swapfile.

swapon failed: Device or resource busy

Файл уже включён. Проверь swapon --show.

После перезагрузки swap пропал

swapon действует до перезагрузки. Нужна строка в /etc/fstab (рецепт выше). Строка есть, а в журнале загрузки Timed out waiting for device /dev/disk/by-uuid/… и Dependency failed for …swap — файл записан через UUID=; замени на путь.

swap.img.swap в списке failed

text
student@ubuntu:~$ systemctl --failed --no-legend
● swap.img.swap loaded failed failed /swap.img
student@ubuntu:~$ sudo swapon -a
swapon: cannot open /swap.img: No such file or directory

Для каждой строки swap в fstab systemd делает юнит <путь>.swap. Файл удалили, а строку оставили — юнит падает при каждой загрузке. Убери строку из /etc/fstab, затем sudo systemctl daemon-reload и sudo systemctl reset-failed.

vm.swappiness вернулся к 60

Значение поставили sysctl vm.swappiness=… — оно живёт до перезагрузки. Положи строку в файл /etc/sysctl.d/*.conf. Больше 200 ядро не принимает: sysctl: setting key "vm.swappiness": Invalid argument.

Опасно

1

swapoff при нехватке памяти

swapoff возвращает все страницы из swap в память. Если места в памяти нет, команда долго гоняет диск, а потом приходит oom-killer. Перед swapoff сравни used в строке Swap с available.

Термины

3
кэш страниц (page cache)
Копии прочитанных и записанных файлов в памяти: повторное чтение идёт без диска. В free — buff/cache; когда программам нужна память, ядро освобождает кэш, поэтому запас — available. Ещё встречается в: OOM killer: кто и почему завершил процесс, Мониторинг системы: с чего начать, когда сервер тормозит, iostat и pidstat
swap (подкачка)
Раздел или файл на диске, куда ядро вытесняет редко нужные страницы программ, чтобы освободить память. Выручает при нехватке, но диск медленнее памяти: активный swap — тормоза. Ещё встречается в: Мониторинг системы: с чего начать, когда сервер тормозит, OOM killer: кто и почему завершил процесс, /proc: процессы и ядро в виде файлов, top и ещё 6
RSS (резидентная память) RSS (resident set size)
Сколько памяти процесса сейчас лежит в RAM, в КиБ: столбец RSS в ps, RES в top, VmRSS в /proc/<pid>/status. Общие библиотеки входят в RSS каждого процесса. Ещё встречается в: OOM killer: кто и почему завершил процесс, /proc: процессы и ядро в виде файлов, iostat и pidstat, ps и ещё 1

См. также

  • oom-killer — что происходит, когда память кончилась.
  • system-monitoring — vmstat: si, so, free, cache.
  • sysctl — параметры ядра и /etc/sysctl.d.
  • top — RES и %MEM по процессам.
  • processes — состояния процессов и сигналы.
  • cgroups-namespaces — лимит памяти группы.
Загрузка…