Добавить в корзинуПозвонить
Найти в Дзене

Режимы выделения виртуальной памяти в Linux

Еще один вопрос, который вызывает ряд неверных толкований и ошибок в применении – это режим выделения виртуальной памяти в Linux. А именно политика overcommitment – избыточного выделения памяти процессам, нежели ее есть на самом деле. Постойте, но зачем выделять памяти больше, чем ее есть на самом деле? Может быть надо жить по средствам? Но не все так просто. Многие процессы запрашивают памяти больше, чем используют на самом деле. Объем заметки не позволяет углубиться в суть происходящих процессов, поэтому допустим определенные упрощения. Во-первых, процесс может резервировать память «на всякий случай», во-вторых – в память могут отображаться разреженные структуры, например, файл 1 ГБ, у которого реально занято 250 МБ, остальное нули (виртуальный диск). И, наконец, процессы могут использовать память совместно. Скажем если материнский процесс порождает потомка, то он тоже запрашивает выделение памяти как у материнского процесса, но на самом деле использует общую с ним память до тех п

Режимы выделения виртуальной памяти в Linux

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

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

Объем заметки не позволяет углубиться в суть происходящих процессов, поэтому допустим определенные упрощения. Во-первых, процесс может резервировать память «на всякий случай», во-вторых – в память могут отображаться разреженные структуры, например, файл 1 ГБ, у которого реально занято 250 МБ, остальное нули (виртуальный диск).

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

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

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

Режим работы этого механизма можно задать при помощи опции

vm.overcommit_memory

Которая может принимать одно из трех значений: 0, 1 и 2

🔹vm.overcommit_memory = 0 – значение по умолчанию, лимит выделения памяти рассчитывается ядром эвристически, с учетом реального ее использования. Такая стратегия позволяет наиболее эффективно использовать всю наличную память.

В таком режиме ядро обычно допускает умеренное избыточное выделение памяти, примерно до 50% от общего размера физической памяти (ОЗУ + подкачка).

Из минусов мы имеем некоторую неопределенность. Один и тот же запрос на выделение памяти, может быть, как одобрен ядром, так и отклонен. Также имеется возможность неожиданного срабатывания OOM-killer.

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

🔹 vm.overcommit_memory = 1 – выделение память происходит всегда, все лимиты отключены. Очень специфический режим, который тем не менее может оказаться полезным для процессов активно использующих потомков и общую память (веб-сервера).

Но включая данный режим нужно очень четко представлять, что вы делаете, так как очень высокий риск привести систему в нестабильное состояние из-за реального недостатка памяти, плюс крайне высок риск непредсказуемого срабатывания OOM-killer.

🔹 vm.overcommit_memory = 2 – жесткий лимит на выделение памяти, для этого режима используется еще одна опция:

vm.overcommit_ratio = 100

Которая обозначает какой процент памяти используется для вычисления лимита, который производится по формуле:

CommitLimit = swap_total + (RAM_total × vm.overcommit_ratio / 100)

По умолчанию vm.overcommit_ratio = 50 и поэтому если вы его не зададите явно, то лимит будет меньше имеющейся в наличии оперативной памяти.

Данный режим рекомендуется использовать вместе с приложениями, которые сами управляют выделением памяти, например, СУБД. В документации PostgreSQL такая настройка указана явно.

Причина здесь проста. В случае тяжелого запроса лучше получить явный отказ в выделении памяти и выдать пользователю ошибку «недостаточно памяти», нежели процесс СУБД окажется завершен OOM-killer и потребует аварийного перезапуска.

В ряде систем с высокими требованиями к стабильности рекомендуется уменьшить лимит выделения до 70-80%.