Почему дискуссии о «подкачке» ведут себя так, будто информация может быть только в одном месте одновременно?

Я читал о настраиваемой «swappiness» Linux, которая контролирует, насколько агрессивно ядро ​​относится к подкачке памяти приложений на диск, когда они не используются. Если вы введете этот термин в Google, вы получите множество страниц вроде это, на которых обсуждаются плюсы и минусы. Вкратце аргумент звучит так:

If your swappiness is too low, inactive applications will hog all the system memory that other programs might want to use.

If your swappiness is too high, when you wake up those inactive applications, there's going to be a big delay as their state is read back off the disk.

Для меня этот аргумент не имеет смысла. Если у меня есть неактивное приложение, которое использует тонну памяти, почему ядро ​​не выгружает свою память на диск И не оставляет в памяти еще одну копию этих данных? Кажется, это дает лучшее из обоих миров: если другому приложению нужна эта память, оно может немедленно запросить физическую ОЗУ и начать запись в нее, поскольку другая ее копия находится на диске и может быть заменена обратно, когда неактивное приложение просыпается. вверх. И когда исходное приложение просыпается, любые его страницы, которые все еще находятся в ОЗУ, могут использоваться как есть, без необходимости извлекать их с диска.

Или я что-то упускаю?

На этот вопрос нет ответа. Правильным значением vm.swappiness остается voodoo. Я снизил его до 10 на своем рабочем столе, и скорость отклика улучшилась. Я увеличил его до 100, использование файла подкачки близко к нулю, а скорость отклика отличная даже с 1/4 RAM, занятой виртуальной машиной. Кажется, что "неправильное" значение - 60 по умолчанию.

Apalala 31.12.2010 20:21
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
4
1
1 738
4
Перейти к ответу Данный вопрос помечен как решенный

Ответы 4

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

If I have an inactive application that's using a ton of memory, why doesn't the kernel page its memory to disk AND leave another copy of that data in-memory?

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

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

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

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

Так стоит ли это делать? Честно говоря, не знаю. Я просто пытаюсь объяснить, почему оставить страницу в памяти не так очевидно, как кажется.

(*) Все это очень похоже на механизм под названием Copy-On-Write, который используется, когда процесс fork () s. Дочерний процесс, скорее всего, выполнит всего несколько инструкций и вызовет exec (), поэтому было бы глупо копировать все родительские страницы. Вместо этого у ребенка отнимается разрешение на запись, и ребенку просто разрешается работать. Копирование при записи - это выигрыш, потому что ошибка страницы почти никогда не возникает: дочерний элемент почти всегда немедленно вызывает exec ().

Ответ принят как подходящий

Согласно этому 1 это именно то, что делает Linux.

Я все еще пытаюсь понять многое из этого, поэтому любые авторитетные ссылки будут признательны.

Первое, что делает виртуальная машина - очищает страницы и перемещает их в чистый список. При очистке анонимной памяти (вещи, которые не имеют фактического хранилища файловых резервных копий, вы можете видеть сегменты в / proc // maps, которые являются анонимными и не имеют хранилища vnode файловой системы за ними), первое, что собирается сделать виртуальная машина - возьмите «грязные» страницы и «очистите» затем, выписав содержимое страницы для обмена. Теперь, когда виртуальная машина испытывает нехватку полностью свободной памяти и обеспокоена своей способностью предоставлять новые бесплатные страницы для использования, она может просматривать список «чистых» страниц в зависимости от того, как давно они использовались и какой тип памяти. они переместят эти страницы в свободный список.

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

Кроме того, подкачка довольно ужасна для серверных приложений в бизнес-среде / транзакционной / онлайн-среде / среде, чувствительной к задержкам. Когда у меня есть блоки ОЗУ на 16 ГБ, в которых я не использую много браузеров и графических интерфейсов, я обычно хочу, чтобы все мои приложения были почти закреплены в памяти. Основная часть моей оперативной памяти, как правило, составляет 8-10 ГБ java-кучи, которую я, НИКОГДА, всегда хочу выгружать на диск, а доступный мусор - это такие процессы, как mingetty (но даже там страницы glibc в этих приложениях используются другими приложениями и фактически используется, поэтому даже размер RSS этих бесполезных процессов в основном используется совместно используемыми страницами). Обычно я не вижу более нескольких 10 МБ из 16 ГБ, фактически очищенных для замены. Я бы посоветовал очень, очень низкие числа подкачки или нулевую подкачку для серверов - неиспользуемые страницы должны составлять небольшую часть общей ОЗУ, и попытка вернуть этот относительно небольшой объем ОЗУ для буферного кеша рискует подкачивать страницы приложений и получать задержки запущенное приложение.

Другие вопросы по теме