Поменять местами или нет?

Подходит ли подкачка для современного мира облачного кода и служебной инфраструктуры? Известные проекты, включая Kubernetes, рекомендуют запускать с отключенным свопом. Я объясню, во что я верю и почему.

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

Поскольку некоторые термины не всегда понятны, я сначала определю несколько терминов:

«Виртуальная память» - это, по правде говоря, единственный вид адресации в основных операционных системах: потоки пользовательской среды видят виртуальное адресное пространство, в то время как ОС заботится о сопоставлении его с адресным пространством реальной оперативной памяти.

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

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

Подкачка - это место, куда операционная система может помещать грязные страницы, для которых нет лучшего места. В Linux это означает память процесса, анонимные общие страницы и данные tmpfs. Некоторые виды страниц не нужно менять местами. Если процесс использует mmap () для доступа к файлу, ядро ​​сбрасывает эти данные в файловую систему. Чистые страницы не нужно никуда писать, потому что они не менялись.

Хорошо, это те термины, о которых я говорю. Что такого особенного в включении свопа?

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

В современных системах получение чего-либо из подкачки происходит довольно быстро - может быть, 1 мс для облачного хранилища, а тем более для локального SSD. Однако так было не всегда. Всего несколько лет назад для подкачки было обычным делом использовать вращающиеся жесткие диски, и они намного медленнее, может быть, 20 мс. Это в миллион раз медленнее, чем несколько нано секунд, которые требуются для доступа к ОЗУ.

(Если вы хотите увидеть, как эти цифры менялись с течением времени, посмотрите изящную визуализацию Колина Скотта).

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

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

Возможно, вы сами видели такое поведение и пробовали разные способы его исправить. Мне нужно было самому справиться с такими симптомами, и я расскажу о некоторых из известных мне способов.

  1. Масштабируйте по горизонтали (добавьте больше экземпляров / серверов / модулей и запустите приложение на них параллельно). Это отлично работает, если это вариант. С другой стороны, вы можете добавить один сервер и перейти от отключения, затрагивающего конечных пользователей, до отключения, затрагивающего из них. Аппаратное обеспечение - это не всегда ответ.
  2. Масштабируйте по вертикали (выделите больше памяти / запустите для более крупных экземпляров). Чем больше у вас ОЗУ, тем больше вероятность того, что неиспользуемые страницы останутся резидентными.
  3. Настройте среду выполнения приложения. Вы можете установить swappiness (да, это вещь) для каждой контрольной группы, чтобы память приложения выгружалась последней. Привилегированные приложения могут использовать mlock () или mlockall () для хранения важных страниц в памяти; Я также использовал memlockd на серверах с ограниченными ресурсами для того же эффекта.
  4. Добавить еще своп. Ядро выгружает память, включая код приложения, когда она лучше использует физическую страницу RAM. При отсутствии устройства подкачки или его нехватке ядро ​​всегда должно хранить данные приложения в физической памяти, поскольку им больше некуда идти. Если ядро ​​может использовать пространство подкачки, у него есть больше возможностей для удаления.
  5. Обновить приложение. Когда поток с низким приоритетом может удерживать блокировку, которая блокирует более важные потоки, фактически предотвращая их, это бесполезно. Можно ли переписать систему, чтобы пропустить эту блокировку или изолировать фоновую задачу от других потоков? Возможно, вместо этого вы можете разделить фоновую задачу на запланированную функцию, задание cron или подобное.

Вы, наверное, заметили, что все сводятся к разным вариантам: исправления приложения или предоставления дополнительной памяти. Отключать своп не пробовал.

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

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

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

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

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

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