Linux и swap

Аватара пользователя

Автор темы
rogoznik
Сообщения: 10042
Зарегистрирован: 27 июн 2017, 13:36
Решено: 129
Откуда: Нижний Тагил
Благодарил (а): 776 раз
Поблагодарили: 1956 раз
Контактная информация:

Linux и swap

#1

04 фев 2021, 12:26

Попалась мне вчера вечером статья на хабре. А т.к. постоянно возникают споры про swap решил запостить эту статью тут. Думаю, многим будет полезно знать

Почему линукс использует swap-файл
Жажда тюнинга может завести в неведомые дебри. И, пожалуй, едва ли не самая частая неправильная оптимизация — отключение swap-файла. Если прикинуть частоту, с которой эта ошибка встречается, то, наверное, она входит в негласный top-10 (а может и top-5) самых распространенных, самых бесполезных и самых вредных оптимизаций - потому что swap-файл это одна из самых интересных, сложно понимаемых и недооцененных сущностей в подсистеме управления виртуальной памятью.
Эта статья является обзорной и предназначена для того, чтобы дать представление об общих процессах, происходящих в системе, и объяснить, откуда берутся некоторые мифы, следование которым может доставить неприятные моменты

В начале был … вопрос

Когда возникает необходимость в swap-файле? Самый частый ответ — «когда не хватает памяти». И, естественно, это ответ неправильный почти полностью. Правильный ответ - необходимость в использовании swap-файла возникает тогда, когда система не может удержать в памяти необходимый кэш и грязные страницы. А чтобы понять, что это значит, нам надо сделать маленький экскурс внутрь ядра операционной системы.

Вся память, которой оперирует система, разбита на страницы. Каждый процесс в системе имеет свое «плоское» адресное пространство. Для каждого процесса система поддерживает карту страниц — какая страница адресного пространства процесса (страница виртуальной памяти) отображена в какую страницу физической памяти - если вообще отображена, разумеется.

И когда процесс пытается получить доступ к какой-то странице своей памяти, MMU (memory management unit) процессора фактически производит обращение к той странице физической оперативной памяти, куда страница отображена.

А если страница не отображена ни в какую физическую страницу, то возникает page fault — исключительная ситуация «страница не найдена». При обработке этой ситуации система (ядро) проверяет, имеет ли процесс право получить доступ к своей логической странице: если не имеет (например эта страница заразервирована ядром или находится «за хвостом кучи» процесса) - то процессу придет сигнал SEGFAULT — и процесс умрет.

А если имеет — то ядро выполнит все нужные действия, чтобы восстановить правильное содержимое страницы, и предъявит её процессу - после чего операция успешно выполнится.

Какие группы страниц памяти живут в системе?

Страницы физической памяти
  • Свободная — страница физической памяти, которая не используется для хранения данных и может быть свободно использована в любой момент времени
  • Используемая — страница, хранящая данные, не принадлежащие кэшу
  • Страница анонимного кэша (anonymous page cache) — страница числится как принадлежащая кэшу, но не закрепленная ни за каким файлом. Очень похожа на используемую страницу (и в определенных ситуациях может превращаться в неё)
  • Чистая страница кэша (clean cache page)- страница, в которой хранятся закэшированные данные файла, которые не менялись.
  • Грязная страница кэща (dirty cache page) — страница, в которой хранятся данные файла, которые были изменены (данные в кэше поменяли но на диск изменения не сохранили)
Страница процесса, в свою очередь, также может иметь несколько состояний
  • Недоступная — процесс не имеет права на доступ к этой странице. Если процесс к ней обращается "неподобающим образом" то получает SEGFAULT
  • Доступная, сопоставленная физической странице, не принадлежащей кэшу. Процесс может работать с этой страницей
  • Доступная, сопоставленная физической странице кэша, в которую загружены данные файла. Процесс может работать с этой страницей.
  • Доступная, не сопоставленная физической странице, но сопоставленная региону какого-либо файла. Прежде чем процесс сможет работать с этой страницей, система должна выделить физическую страницу, отдать ее в кэш, загрузить в нее данные из файла — и после этого процесс сможет с ней работать (потому, что она превратится в предыдущую разновидность)
И сейчас, когда мы более-менее определились с видами страниц, мы переходим к самой интересной части

Работа процесса

Чтобы понять как все эти механизмы связаны и работают, давайте рассмотрим запуск нового процесса. Мы запускаем новый процесс, и система загружает исполняемый файл. Как это происходит?

Система открывает бинарный файл с программой и … Нет, она не читает его. Она отображает файл в адресное пространство процесса — то есть создает записи (например)
  • Страница 0 ... 15 -> /usr/bin/filename сегмент 0 ... 65535
  • Страница 16 ... 31 -> /usr/bin/filename сегмент 65536 ... 131071
Ну да, там всё сложнее — но нам сейчас главное понять идею.

С точки зрения системы, эти логические страницы принадлежат процессу, отображены на какой-то файл файловой системы и не сопоставлены никакой физической странице. И теперь, управление отдается процессу — например вызывается инструкция с какой-то страницы или читаются или записываются данные в страницу.

MMU обнаруживает ошибку — странице процесса не сопоставлена никакая физическая страница - ошибка, page fault! Ядро получает эту ошибку, смотрит на статус страницы:
  • процессу разрешен доступ
  • физической странице не сопоставлена (и это логично, иначе бы page fault не возник)
  • но сопоставлена сегменту файла
  • указанный фрагмент файла в кэше не обнаружен
В указанной ситуации, ядро берет свободную страницу, объявляет её страницей кэша и загружает в неё данные из файла с диска. Теперь это чистая страница кэша - clean page. Затем ядро добавляет ссылку «этой странице процесса сопоставлена эта физическая страница, принадлежащая кэшу и взятая из указанного места файла». Управление возвращается процессу, а проблемная операция завершается успешно. Ну а если это была операция модификации данных (и модификация допустима), то после записи данных страница помечается как измененная — и становится грязной страницей кэша - dirty page с точки зрения ядра.

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

Точно такие же процессы происходят для разделяемых библиотек (бинарник программы, на самом деле, тоже фактически разделяемая библиотека, которая просто содержит специальную точку входа).

Примечание "на полях": на самом деле, когда файл разделяемой библиотеки загружается, он частично прочитывается (как минимум его заголовок и секция символов: описание расположения объектов (функций и переменных) содержащихся в файле разделяемой библиотеки) — но в большинстве случаев, целиком файл не читается, и подгружается в процессе работы программы по мере обращения к функциям и переменным, описанным в загруженных разделяемых библиотеках. Поэтому, после перезагрузки система может немного «подтупливать» - в том числе всё то время, пока кэш заполняется разделяемыми библиотеками.

Второе "примечание": механизмы работы с отображаемыми в память файлами намного сложнее и если за них браться, эта статья превратилась бы в многостраничный трактат. Но нам сейчас надо понять основные линии поведения системы в стрессовых условиях нехватки RAM


Откуда (и когда) начинается использование swap-файла?

Представим, что мы загрузили большой бинарник с большим количеством библиотек (привет, браузер!) в котором открыли сколько-то вкладок с документами, и исчерпали доступную физическую память. При этом, у нас образуется две больших группы страниц — чистые страницы кэша, сопоставленные разделяемым библиотекам — причем в этих страницах содержится использующийся код (мы ведь помним про то, что библиотеки загружаются «по мере необходимости») и приватные страницы процесса или страницы anonymous page cache (этот механизм часто используется для предварительной аллокации памяти). Но, в обоих случаях, мы можем рассматривать их как данные процесса.

Свободных страниц у нас нет — всё ушло на кэш и данные.

Теперь мы открываем еще одну вкладку, что при этом случается? Чтобы найти память, система вынуждена освободить часть чистых страниц кэша и отдать их под данные приложения — ведь данные которые там лежали, можно снова загрузить с диска (это ведь "чистые" страницы!).

Но в этих страницах был ИСПОЛЬЗУЕМЫЙ код — иначе бы они не подтянулись в кэш.

А это значит, что как только (и скорей всего через не самый долгий промежуток времени) программа пойдет в код, который был выгружен из памяти, она получит page fault — и система снова прочтет код из файла библиотеки с диска. В новую пустую страницу. Но чтобы её получить, надо сбросить другую чистую страницу кэша! И система входит в трэшинг - она постоянно вынуждена освобождать и снова погружать код, раз за разом, из одного файла за другим.

То есть фактически, в системе уже есть swap-файл, из которого постоянно ведется чтение — и это разделяемые библиотеки. Но система не может использовать его эффективно, поскольку он ограничен и фактически неуправляем - и скатывается в трэшинг

А если бы у нас был настоящий swap-файл?

На основе учета частоты обращения к различным страницам, система скорей всего не освободила бы страницу с кодом, а поместила в swap данные наиболее давно не использовавшихся вкладок. И вместо постоянного чтения с диска, у нас случились бы одна запись и одно чтение — причем именно в момент обращения к выгруженной в swap вкладке.

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

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

А если swap-файл маленький, то начинается «веселье» с постоянным записью-чтением в swap-файл.

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

Какие выводы можно сделать из всего вышеописанного?

Кэш (page cache) — это не только кэш данных! Кэш - это очень существенный компонент в схеме организации виртуальной памяти - и теперь мы понимаем неправильность вопроса «почему система ушла в свал а не освободила кэш». Ведь ответ очень прост - этот кэш на самом деле не просто кэш, а код. И если код используется чаще, чем данные - то в данном случае более важно сохранить в памяти код (сохранить кэш) чем удерживать в памяти данные!

Поэтому не надо бояться наличия swap-файла — если статистика не покажет необходимости - система не полезет в свап.

Swap-файл может считаться используемым даже если все данные из него уже подняты обратно в память.

Малый размер swap-файла вреден — он не позволяет системе работать эффективно, поскольку увеличивает объем непродуктивного I/O

Резюме?

Это прекрасно, когда объем оперативной памяти достаточно велик, чтобы вместить и весь необходимый кэш, и данные. Но если у вас бюджетная система с 8 … 16ГБ оперативной памяти (не говоря уж об ультрабюджетных ноутбуках с распаянными и нерасширяемыми 4GB), то swap достаточного объема (не менее 1 x ) это "то, что доктор прописал".

И достаточный размер swap-файла на быстром накопителе (кто сказал NVMe?) на бюджетном ноутбуке может очень хорошо увеличить производительность системы, особенно если вы любитель держать много открытых вкладок, документов, рисунков в графическом редакторе и т.д.

Не мешайте системе работать. Нет нужды бояться swap-файла. Если он не нужен — он не будет использован. И то, что вы видите, что он якобы использован - на самом деле совсем не значит, что он использован. Просто нам показали картинку «без подробностей».

Источник: habr.com
ИзображениеИзображение

Аватара пользователя

sheridan
Сообщения: 1283
Зарегистрирован: 24 фев 2020, 19:13
Решено: 14
Откуда: Алчевск
Благодарил (а): 892 раза
Поблагодарили: 467 раз
Контактная информация:

Linux и swap

#2

04 фев 2021, 14:45

Полезная статья,
у себя я заметил что при компиляции больших пакетов (gcc, llvm, rust, chromium) даже при объёме памяти 32gb система использует swap,
при том что пик используемой памяти был на отметке 16,8gb

Аватара пользователя

Chocobo
Сообщения: 10015
Зарегистрирован: 27 авг 2016, 22:57
Решено: 215
Откуда: НН
Благодарил (а): 815 раз
Поблагодарили: 3010 раз
Контактная информация:

Linux и swap

#3

04 фев 2021, 19:17

rogoznik писал(а):
04 фев 2021, 12:26
Это прекрасно, когда объем оперативной памяти достаточно велик ... Но если у вас бюджетная система ... то swap это "то, что доктор прописал".
Свелось все к непреложной истине, сложно спорить :smile: нет рамы - ешь своп.
Тезис на самом деле остается прежним - проявление своппинга это не очень хорошо)

Аватара пользователя

Автор темы
rogoznik
Сообщения: 10042
Зарегистрирован: 27 июн 2017, 13:36
Решено: 129
Откуда: Нижний Тагил
Благодарил (а): 776 раз
Поблагодарили: 1956 раз
Контактная информация:

Linux и swap

#4

04 фев 2021, 19:29

Chocobo писал(а):
04 фев 2021, 19:17
Тезис на самом деле остается прежним - проявление своппинга это не очень хорошо)
Думаю тут нужно уточнение - агрессивный свопинг.
К примеру у меня 16ГБ рамы, за сегодняшний 12 часовой аптайм показывает 10МБ в свапе. Думаю туда складывается долго неиспользуемое, чтоб не занимало память. Собственно о чем и написано в статье.
ИзображениеИзображение

Аватара пользователя

Chocobo
Сообщения: 10015
Зарегистрирован: 27 авг 2016, 22:57
Решено: 215
Откуда: НН
Благодарил (а): 815 раз
Поблагодарили: 3010 раз
Контактная информация:

Linux и swap

#5

04 фев 2021, 19:46

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

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

Аватара пользователя

demonlibra
Сообщения: 844
Зарегистрирован: 12 авг 2017, 09:09
Решено: 13
Откуда: Ростов-на-Дону
Благодарил (а): 29 раз
Поблагодарили: 204 раза
Контактная информация:

Linux и swap

#6

04 фев 2021, 21:36

Добавлю, что проверить подключен ли файл подкачки можно командами в терминале:
cat /proc/swaps
или
swapon --show

Есть ли какая-нибудь служба, посмотрев лог которой можно понять, что файла подкачки не хватало?
Basic (ZXSpectrum)→Ms-Dos→W95→W98→Me→XP→W7→Ubuntu 15.10→Xubuntu 16.04→Linux Mint 18.2-21.1
Контекстное меню Nemo
Сценарий вывода данных оценки ресурса диска SSD

Аватара пользователя

WWolf
Сообщения: 3895
Зарегистрирован: 14 фев 2018, 00:51
Решено: 31
Откуда: Краснодар
Благодарил (а): 1687 раз
Поблагодарили: 1212 раз
Контактная информация:

Linux и swap

#7

04 фев 2021, 22:17

demonlibra писал(а):
04 фев 2021, 21:36
Есть ли какая-нибудь служба, посмотрев лог которой можно понять, что файла подкачки не хватало?
если и свапа не хватает, то система начинает мочить жирные процессы или виснуть если всё выжрали ядро или драйвер...

Аватара пользователя

Dja
Сообщения: 6875
Зарегистрирован: 27 авг 2016, 20:03
Решено: 30
Откуда: Voskresensk
Благодарил (а): 1312 раз
Поблагодарили: 724 раза
Контактная информация:

Linux и swap

#8

18 мар 2021, 22:58

rogoznik писал(а):
04 фев 2021, 12:26
находится "за хвостом кучи" процесса
это как?

Аватара пользователя

Автор темы
rogoznik
Сообщения: 10042
Зарегистрирован: 27 июн 2017, 13:36
Решено: 129
Откуда: Нижний Тагил
Благодарил (а): 776 раз
Поблагодарили: 1956 раз
Контактная информация:

Linux и swap

#9

19 мар 2021, 06:50

Dja писал(а):
18 мар 2021, 22:58
это как?
Не забивай себе голову :-D
ИзображениеИзображение

Закрыто

Вернуться в «Руководства»

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

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