В защиту свопа: распространенные заблуждения

Ссылка на оригинал - https://chrisdown.name/2018/01/02/in-defence-of-swap.html, автор публикации - Chris Down

tl;dr:

  1. Своп является достаточно важной частью хорошо функционирующей системы. Без него разумное управление памятью становится все труднее и труднее.
  2. Обычно своп памяти - это не получение экстренной памяти, а эгалитарное и эффективное восстановление памяти. На самом деле, использование ее в качестве "аварийной памяти", как правило, активно вредит.
  3. Отключение подкачки не мешает дисковому вводу/выводу стать проблемой при работе с памятью, а просто сдвигает дисковую подкачку ввода/вывода с анонимных страниц на файловые. Это не только может быть менее эффективным, так как у нас есть меньший пул страниц, чтобы выбрать из них для восстановления, но это также может способствовать попаданию в это высокое состояние соперничества в первую очередь.
  4. Свпо на ядрах до 4.0 имеет много подводных камней и способствовал негативному восприятию многими людьми свопа из-за его чрезмерного желания выкачивать страницы. На ядрах >4.0 ситуация значительно лучше.
  5. На SSD подкачка анонимных страниц и восстановление файловых страниц по существу эквивалентны с точки зрения производительности/латентности. На старых вращающихся дисках чтение подкачки происходит медленнее из-за случайного чтения, поэтому здесь имеет смысл установить более низкую установку vm.swappiness (подробнее о vm.swappiness читайте дальше).
  6. Отключение подкачки не предотвращает патологического поведения вблизи OOM, хотя это правда, что подкачка может продлить ее. Вне зависимости от того, был ли системный глобальный OOM-убийца вызван с или без подкачки, или был вызван рано или поздно, результат будет один и тот же: вы остаетесь с системой в непредсказуемом состоянии. Отсутствие подкачки не избавит вас от этого.
  7. Вы можете добиться лучшего поведения подкачки под давлением памяти и предотвратить "молочницу" с помощью memory.low и друзей в cgroup v2.

Как часть моей работы по улучшению управления памятью ядра и cgroup v2, я говорил со многими инженерами об отношении к управлению памятью, особенно о поведении приложений под давлением и эвристике операционной системы, используемой под капотом для управления памятью.

В этих дискуссиях неоднократно повторялась тема обмена мнениями. Обмен - это горячо оспариваемая и плохо понимаемая тема, даже теми, кто работает с Linux много лет. Многие считают его бесполезным или активно вредным: пережиток времени, когда память была скудной, а диски были необходимым злом, чтобы обеспечить столь необходимое пространство для пейджинга. Это утверждение, которое я до сих пор вижу, как меня бьют с относительной частотой в последние годы, и я провел много обсуждений с коллегами, друзьями и коллегами по индустрии, чтобы помочь им понять, почему замена дисков все еще является полезной концепцией на современных компьютерах с гораздо большим количеством физической памяти, чем в прошлом.

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

Многие из нас слышали большинство обычных рассуждений о памяти: «Linux использует слишком много памяти», «своп должен быть в два раза больше вашей физической памяти» и тому подобное. Хотя их можно либо развеять тривиально, либо обсуждение вокруг них стало более нюансированным в последние годы, миф об «бесполезном» обмене гораздо больше основан на эвристике и тайнах, нежели чем-то, что можно объяснить простой аналогией, и требует несколько большего понимание управления памятью, чтобы рассуждать о.

Этот пост в основном предназначен для тех, кто администрирует системы Linux и заинтересован в том, чтобы услышать противопоказания для работы с недопустимым / без свопинга или для работы с vm.swappinessустановленным на 0.

Задний план

Трудно говорить о том, почему своп и замена страниц являются хорошими вещами в обычной работе без общего понимания некоторых основных базовых механизмов, которые играют роль в управлении памятью Linux, поэтому давайте убедимся, что мы на одной странице.

Типы памяти

В Linux существует много разных типов памяти, и у каждого типа есть свои свойства. Понимание их нюансов является ключом к пониманию важности обмена.

Например, есть страницы («блоки» памяти, обычно 4 КБ), отвечающие за хранение кода для каждого процесса, выполняемого на вашем компьютере. Существуют также страницы, отвечающие за кэширование данных и метаданных, связанных с файлами, к которым обращаются эти программы, чтобы ускорить доступ в будущем. Это часть кеша страниц, и я буду называть их файловой памятью.

Существуют также страницы, которые отвечают за выделение памяти внутри этого кода, например, когда mallocзаписывается новая выделенная память или когда используется флаг mmap's' MAP_ANONYMOUS. Это «анонимные» страницы - так называемые , потому что они не подкреплены ничем - и я буду ссылаться на них как Anon памяти.

Существуют и другие типы памяти - разделяемая память, память блоков, память стека ядра, буферы и т. П., Но анонимная память и файловая память являются наиболее известными и простыми для понимания, поэтому я буду использовать их в своих примерах, хотя они в равной степени относятся и к этим типам.

Исправимая / невосстановимая память

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

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

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

Для некоторых типов страниц это невозможно. Например, в случае анонимных страниц, упомянутых ранее, они существуют только в памяти и ни в каком другом хранилище, поэтому их нужно хранить там.

Природа своп

Если вы ищете описание цели подкачки в Linux, вы неизбежно обнаружите, что многие говорят об этом, как будто это просто расширение физической оперативной памяти для использования в чрезвычайных ситуациях. Например, вот случайный пост, который я получил в качестве одного из лучших результатов при вводе «что такое своп» в Google:

Своп по сути является аварийной памятью; пространство, выделенное для времен, когда вашей системе временно требуется больше физической памяти, чем у вас есть в ОЗУ. Он считается «плохим» в том смысле, что он медленный и неэффективный, и если вашей системе постоянно нужно использовать своп, то, очевидно, ей не хватает памяти. […] Если у вас достаточно оперативной памяти для удовлетворения всех ваших потребностей, и вы не рассчитываете когда-либо ее максимально использовать, тогда вы должны быть абсолютно безопасны в работе без места подкачки.

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

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

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

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

Итак, в каких ситуациях в рамках этого сценария «равного возврата» мы законно решили бы вернуть анонимные страницы? Вот несколько абстрактных сценариев:

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

Изучение того, что происходит с / без свопа

Давайте посмотрим на типичные ситуации, и как они работают с и без обмена. Я говорю о показателях, связанных с «конфликтом памяти», в моем выступлении на cgroup v2 .

При отсутствии / недостатке памяти

  • С помощью swap: мы можем выбрать замену редко используемой анонимной памяти, которая может использоваться только в течение небольшой части жизненного цикла процесса, что позволяет нам использовать эту память для повышения частоты обращений в кэш или для других оптимизаций.
  • Без подкачки: мы не можем выгрузить редко используемую анонимную память, так как она заблокирована в памяти. Хотя это может не сразу представлять проблему, в некоторых рабочих нагрузках это может привести к нетривиальному падению производительности из-за устаревших анонимных страниц, которые убирают пространство для более важного использования.

При умеренном / высоком конфликте памяти

  • Со свопом: все типы памяти имеют равную возможность восстановления. Это означает, что у нас больше шансов быть в состоянии восстановить страницы успешно, то есть мы можем вернуть страницы, которые быстро не возвращаются (перебивание).
  • Без свопа: анонимные страницы блокируются в памяти, поскольку им некуда идти. Вероятность успешного долгосрочного восстановления страницы ниже, поскольку у нас есть только некоторые типы памяти, которые могут быть восстановлены вообще. Риск повреждения страницы выше. Случайный читатель может подумать, что это все равно будет лучше, так как он может избежать необходимости выполнять дисковый ввод-вывод, но это не так - мы просто переводим дисковый ввод-вывод для замены на удаление кэшей горячих страниц и отбрасывание сегментов кода нужно в ближайшее время.

При временных скачках в использовании памяти

  • С помощью swap: мы более устойчивы к временным скачкам, но в случаях сильного голодания памяти период от начала перегрузки памяти до убийцы OOM может быть продлен. Мы лучше видим зачинщиков давления памяти, можем действовать более разумно и можем осуществлять контролируемое вмешательство.
  • Без свопа: убийца OOM срабатывает быстрее, поскольку анонимные страницы заблокированы в памяти и не могут быть восстановлены. У нас больше шансов заполучить память, но время между перегрузкой и OOMing сокращается. В зависимости от вашего приложения, это может быть лучше или хуже. Например, приложение на основе очереди может пожелать этого быстрого перехода от уничтожения к убийству. Тем не менее, это слишком поздно, чтобы быть действительно полезным - убийца OOM вызывается только в моменты сильного голода, и полагаться на этот метод для такого поведения было бы лучше заменить более гибким убийством процессов, так как конфликт памяти достигается в первое место.

Итак, я хочу системный своп, но как я могу настроить его для отдельных приложений?

Вы не думали, что пройдете весь этот пост без моего подключения к cgroup v2, не так ли? ;-)

Очевидно, что универсальному эвристическому алгоритму трудно быть правильным все время, поэтому важно, чтобы вы могли давать рекомендации ядру. Исторически единственная настройка, которую вы могли сделать, была на системном уровне, используя vm.swappiness. У этого есть две проблемы: vm.swappinessневероятно трудно рассуждать, потому что он только входит как небольшая часть большей эвристической системы, и он также является общесистемным, а не гранулированным для меньшего набора процессов.

Вы также можете использовать mlockдля блокировки страниц в памяти, но для этого нужно либо изменить программный код, поиграть с ним LD_PRELOAD, либо делать ужасные вещи с помощью отладчика во время выполнения. В языках на основе виртуальных машин это также не очень хорошо работает, так как вы обычно не контролируете распределение и вынуждены это делать mlockall, что не имеет никакой точности по отношению к страницам, которые вам действительно нужны.

cgroup v2 имеет настраиваемую для каждой cgroup форму memory.low, которая позволяет ядру отдавать предпочтение другим приложениям для восстановления ниже определенного порога используемой памяти. Это позволяет нам не препятствовать ядру выгружать части нашего приложения, но предпочитает восстанавливать его из других приложений из-за нехватки памяти. В нормальных условиях логика подкачки в ядре, как правило, довольно хороша, и возможность произвольно поменять ее страницами обычно повышает производительность системы. Thrash Swap Thrash при сильном конфликте памяти не идеален, но это скорее свойство полного исчерпания памяти, чем проблема с подкачкой. В этих ситуациях вы обычно хотите быстро потерпеть неудачу из-за самоуничтожения некритических процессов, когда начинает увеличиваться нагрузка на память.

Вы не можете просто положиться на убийцу OOM для этого. Убийца OOM вызывается только в ситуациях страшного сбоя, когда мы уже вошли в состояние, когда система серьезно неработоспособна и вполне могла быть таковой некоторое время. Тебе нужно смириться с ситуацией, прежде чем думать об убийце ООМ.

Однако определить давление памяти довольно сложно, если использовать традиционные счетчики памяти в Linux. У нас есть некоторые вещи, которые кажутся в некоторой степени связанными, но являются просто тангенциальными - использование памяти, сканирование страниц и т. Д. - и только по этим метрикам очень сложно отличить эффективную конфигурацию памяти от той, которая имеет тенденцию к конфликту памяти. В Facebook есть группа из нас, возглавляемая Йоханнесом, которая работает над разработкой новых метрик, которые легче выявляют нехватку памяти, что должно помочь в этом в будущем. Если вам интересно узнать больше об этом, я подробно расскажу об одной метрике, которая рассматривается в моем выступлении на cgroup v2.

Настройка

Сколько свопа мне нужно?

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

Если у вас достаточно места на диске и свежее ядро ​​(4.0+), то больше подкачки почти всегда лучше, чем меньше. В старых ядрах kswapd, один из процессов ядра, отвечающих за управление подкачкой, исторически был очень склонен к агрессивной выгрузке памяти, чем больше у вас было подкачки. В последнее время поведение подкачки при наличии большого количества пространства подкачки значительно улучшилось. Если вы работаете с ядром 4.0+, наличие большого свопа на современном ядре не должно приводить к чрезмерной перестановке. Таким образом, если у вас есть место, размер подкачки в несколько Гбайт сохраняет ваши возможности открытыми в современных ядрах.

Если вы более ограничены дисковым пространством, то ответ на самом деле зависит от компромиссов, которые вы должны сделать, и природы среды. В идеале у вас должно быть достаточно подкачки, чтобы ваша система работала оптимально при нормальной и пиковой нагрузке (памяти). Я бы порекомендовал настроить несколько систем тестирования с 2-3 ГБ подкачки или более и отслеживать, что происходит в течение недели или около того при различных условиях (памяти). Пока вы не столкнулись с сильным истощением памяти в течение этой недели - в этом случае тест не будет очень полезным - вы, вероятно, в конечном итоге будете занимать некоторое количество МБ подкачки. Таким образом, вероятно, стоит иметь хотя бы такой большой объем подкачки, в дополнение к небольшому буферу для изменения рабочих нагрузок.atopв режиме регистрации также может показывать, какие приложения выгружают свои страницы в SWAPSZстолбце, поэтому, если вы еще не используете его на своих серверах для регистрации исторического состояния сервера, вы, вероятно, захотите настроить его на этих тестовых компьютерах в режиме регистрации. как часть этого эксперимента. Это также сообщает вам, когда ваше приложение начало обмениваться страницами, которые вы можете привязать к журналу событий или другим ключевым данным.

Еще одна вещь, которую стоит рассмотреть, это природа среды подкачки. Чтение свопа, как правило, очень случайное, так как мы не можем надежно предсказать, какие страницы будут возвращены и когда. На твердотельных накопителях это не имеет большого значения, но на вращающихся дисках случайный ввод-вывод чрезвычайно дорог, поскольку для его достижения требуется физическое движение. С другой стороны, возврат файлов на страницы, вероятно, менее случайный, поскольку файлы, связанные с работой одного приложения во время выполнения, как правило, менее фрагментированы. Это может означать, что на вращающемся диске вы можете больше склоняться к восстановлению файловых страниц вместо замены анонимных страниц, но, опять же, вам нужно проверить и оценить, как это уравновешивает вашу рабочую нагрузку.

Для пользователей ноутбуков / настольных компьютеров, которые хотят переключиться в режим гибернации, это также необходимо учитывать - в этом случае размер файла подкачки должен быть не меньше физического объема ОЗУ.

Какими должны быть мои настройки подкачки?

Во-первых, важно понять, что vm.swappinessделает. vm.swappiness это sysctl, который смещает восстановление памяти либо на восстановление анонимных страниц, либо на файловые страницы. Это делается с использованием двух разных атрибутов: file_prio(наша готовность вернуть страницы файлов) и anon_prio(наша готовность вернуть анонимные страницы). vm.swappinessиграет в это, так как он становится значением по умолчанию для anon_prio, и он также вычитается из значения по умолчанию 200 для file_prio, что означает для значения vm.swappiness = 50, результат anon_prioравен 50 и file_prio150 (точные числа не имеют значения столько, сколько их относительный вес по сравнению с другими).

Это означает, что, как правило, vm.swappiness представляет собой просто соотношение затрат и затрат на восстановление и возврат анонимной памяти по сравнению с файловой памятью для вашего оборудования и рабочей нагрузки . Чем ниже значение, тем больше вы сообщаете ядру, что нечасто обращающиеся к анонимным страницам дорого обмениваются на ваше оборудование. Чем выше значение, тем больше вы сообщаете ядру, что стоимость замены анонимных страниц и файловых страниц на вашем оборудовании одинакова. Подсистема управления памятью по-прежнему будет пытаться в основном решить, будет ли она менять файл или анонимные страницы, исходя из того, насколько горяча память, но перестановка приводит расчет затрат либо в сторону замены, либо в большей степени на удаление кэшей файловой системы, когда она может пойти в любом случае. На SSD они в основном такие же дорогие, что и настройкиvm.swappiness = 100(полное равенство) может хорошо работать. На вращающихся дисках подкачка может быть значительно дороже, поскольку подкачка обычно требует случайного чтения, поэтому вы можете захотеть сместить больше к более низкому значению.

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

Говоря о том vm.swappiness, чрезвычайно важным изменением, которое следует учитывать с недавних времен, является это изменение в vmscan от Satoru Moriya в 2012 году , которое vm.swappiness = 0довольно существенно меняет способ обработки.

По сути, патч делает это таким образом, что мы крайне склонны против сканирования (и, следовательно, возврата) любых анонимных страниц вообще vm.swappiness = 0, если только мы уже не сталкиваемся с серьезным конфликтом памяти. Как упоминалось ранее в этом посте, это, как правило, не то, что вам нужно, так как это предотвращает равенство восстановления перед возникновением экстремального давления памяти, которое может фактически привести к этому экстремальному давлению памяти. vm.swappiness = 1это самый низкий уровень, который вы можете использовать, не вызывая специальный корпус для анонимного сканирования страниц, реализованный в этом патче.

Ядро по умолчанию здесь vm.swappiness = 60. Это значение, как правило, не так уж плохо для большинства рабочих нагрузок, но трудно установить общее значение по умолчанию, подходящее для всех рабочих нагрузок. Таким образом, ценным дополнением к настройке, упомянутой в разделе «сколько нужно подкачки», было бы тестирование этих систем с различными значениями для vm.swappiness и мониторинг ваших приложений и системных показателей под большой нагрузкой (память). Когда- нибудь в ближайшем будущем, когда у нас будет достойная реализация обнаружения ошибок в ядре, вы также сможете определить это в некоторой степени независимо от рабочей нагрузки, взглянув на показатели возврата страниц cgroup v2.

Обновление от 2019-07: показатели давления памяти в ядре 4.20+

Метрики исправлений, упомянутые ранее, находятся в ядре начиная с версии 4.20 и могут быть включены с помощью CONFIG_PSI=y. Смотрите мой доклад на SREcon около 25:05:

В заключение

  • Swap - это полезный инструмент, позволяющий обеспечить равное восстановление страниц памяти, но его цель часто неправильно понимается, что приводит к его негативному восприятию в отрасли. Однако, если вы используете своп в духе намерения - в качестве метода увеличения равенства рекламаций - вы обнаружите, что это полезный инструмент, а не помеха.
  • Отключение подкачки не предотвращает проблемы с дисковым вводом-выводом в условиях нехватки памяти, а просто перебивает дисковый ввод-вывод с анонимных страниц на страницы файлов. Мало того, что это может быть менее эффективно, так как у нас есть меньший пул страниц для выбора, но это также может способствовать в первую очередь переходу в это состояние высокой конкуренции.
  • Свопинг может замедлить работу системы до уничтожения OOM, поскольку он предоставляет другой, более медленный источник памяти для включения в ситуациях нехватки памяти - убийца OOM используется ядром только в качестве крайней меры, после того, как все уже стало монументально облажано. Решения здесь зависят от вашей системы:
    • Вы можете произвольно изменить рабочую нагрузку системы в зависимости от локальной или глобальной нагрузки на cgroup. Это в первую очередь предотвращает попадание в такие ситуации, но в истории Unix отсутствуют четкие показатели давления памяти. Надеюсь, скоро это будет лучше с добавлением обнаружения ошибок.
    • Вы можете смещать освобождение (и, таким образом, подкачку) от определенных процессов для каждой группы, используя его memory.low, позволяя защищать критически важные демоны без полного отключения свопинга.

Большое спасибо RahulTejun и Johannes за их обширные предложения и отзывы об этом посте.

Добавить комментарий

Plain text

  • No HTML tags allowed.
  • Web page addresses and e-mail addresses turn into links automatically.
  • Lines and paragraphs break automatically.

Не нашли ответ на свой вопрос? Возможно, вы найдете решение проблемы на нашем канале в Youtube! Здесь мы собрали небольшие, но эффективные инструкции. Смотрите и подписывайтесь на наш youtube-канал!

Смотреть на Youtube

Руководства и обзоры

1 Что нужно восстановить?

Видео

MP4, AVI и HD видео хранятся на телефоне и / или по ошибке удаляются вместе с фотографиями и другими медиафайлами.

Контакты

Номера телефонов друзей и знакомых из приложения «Контакты Android», журналы вызовов; Восстановление SIM-карты.

Фото

Удалены файлы JPG / PNG из Галереи Android; фото, загруженные на мобильный, файлы повреждены после восстановления.

Смс и сообщения

Чаты WhatsApp и Facebook, текстовые сообщения в соцсетях, информация на сим-карте

2 Где пропали файлы?

На sd-карте

Фотографии и документы хранятся на SD-картах. Часто на них случайно удаляются файлы

На телефоне

Программы для восстановления не распознают внутреннее хранилище телефона как диск, но есть другие решения.

На USB флешке

Эти небольшие устройства хранения данных часто выходят из строя или на них появляются ошибки чтения.

На HDD или SSD

Несмотря на то, что настольные платформы становятся все менее популярными, проблема потери файлов всегда оставалась.