Является ли «кэшированная» память де-факто свободной?

11

При запуске cat /proc/meminfoвы получаете эти 3 значения вверху:

MemTotal:        6291456 kB
MemFree:         4038976 kB
Cached:          1477948 kB

Насколько я знаю, значение "Cached" - это дисковые кэши, создаваемые системой Linux, которые будут немедленно освобождены, если любому приложению потребуется больше оперативной памяти, поэтому Linux никогда не исчерпает память до тех пор, пока MemFree и Cached не будут установлены на ноль.

К сожалению, «procAvailable» не сообщается / proc / meminfo, возможно потому, что он работает на виртуальном сервере. (Версия ядра - 4.4)

Таким образом, для всех практических целей доступной для приложений оперативной памяти является MemFree + Cached.

Это мнение правильно?

Роланд Сеухс
источник
1
Я не хочу, чтобы это закрыли, но этот вопрос актуален, если не дубликат. Я удивлен, что у вас нет MemAvailable, это было добавлено в 3.14.
Стивен Китт
Принятый ответ на этот вопрос использует / proc / zoneinfo, который также недоступен на моем сервере
Roland Seuhs
uname -a: узел Linux 4.4.0-042stab134.8 # 1 SMP пт 7 декабря 17:16:09 MSK 2018 x86_64 x86_64 x86_64 GNU / Linux
Роланд Сеухс,
Я подозреваю, что это система OpenVZ с ядром, которое действительно основано на 2.6.32, а не 4.4.
Стивен Китт
1
@sourcejedi, и он был скомпилирован в то же время, что и ядро ​​4.4!
Стивен Китт

Ответы:

10

Эта точка зрения может вводить в заблуждение в ряде реальных случаев.

Теперь ядро ​​предоставляет оценку доступной памяти в MemAvailableполе. Это значение значительно отличается от MemFree + Cached.

/ proc / meminfo: предоставить приблизительную доступную память [описание изменения ядра, 2014]

Многие программы балансировки нагрузки и размещения рабочей нагрузки проверяют / proc / meminfo, чтобы оценить объем свободной памяти. Как правило, они делают это, добавляя «free» и «cached», что было хорошо десять лет назад, но в значительной степени гарантированно ошибается сегодня.

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

В настоящее время объем памяти, доступной для новой рабочей нагрузки, без принудительной загрузки системы в систему, можно оценить по MemFree, Active (файл), Inactive (файл) и SReclaimable, а также по «низким» водяным знакам из / Proc / ZoneInfo. Тем не менее, это может измениться в будущем, и пользовательское пространство не должно ожидать, что оно знает внутреннее ядро, чтобы оценить объем свободной памяти. Такую оценку удобнее представить в / proc / meminfo. Если что-то изменится в будущем, мы должны изменить это только в одном месте.
...

Documentation / filesystems / proc.txt:
...
MemAvailable: оценка объема доступной памяти для запуска новых приложений без замены. Рассчитывается из MemFree, SReclaimable, размера файлов LRU списков и нижних водяных знаков в каждой зоне. Оценка учитывает, что системе необходим некоторый кэш страниц, чтобы функционировать хорошо, и что не все восстанавливаемые плиты будут пригодны для использования из-за используемых предметов. Влияние этих факторов будет варьироваться от системы к системе.

1. MemAvailable детали

Как сказано выше, tmpfs и другая Shmemпамять не могут быть освобождены, только перемещены для подкачки. CachedЭто /proc/meminfoможет вводить в заблуждение из-за включения этой заменяемой Shmemпамяти. Если у вас слишком много файлов в tmpfs, это может занять много вашей памяти :-). Shmemтакже может включать в себя некоторые выделения графической памяти , которые могут быть очень большими.

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

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

/*
 * Not all the page cache can be freed, otherwise the system will
 * start swapping. Assume at least half of the page cache, or the
 * low watermark worth of cache, needs to stay.
 */
pagecache = pages[LRU_ACTIVE_FILE] + pages[LRU_INACTIVE_FILE];
pagecache -= min(pagecache / 2, wmark_low);
available += pagecache;

Тем не менее, я обнаружил, что это правильно относится Shmemк «использованной» памяти. Я создал несколько файлов 1GB в TMPFS. Каждое увеличение на 1 ГБ Shmemуменьшается MemAvailableна 1 ГБ. Таким образом, размер «списков файлов LRU» не включает общую память или любую другую заменяемую память. (Я заметил, что те же самые числа страниц также используются в коде, который вычисляет «грязный лимит» ).

Этот MemAvailableрасчет также предполагает, что вы хотите сохранить как минимум достаточное количество файлового кэша, чтобы соответствовать «низкому значению ядра» ядра. Или половина текущего кэша - в зависимости от того, что меньше. (Это делает то же самое предположение для исправимых плит также). «Низкий водяной знак» ядра может быть настроен, но обычно он составляет около 2% системной памяти . Так что если вам нужна только приблизительная оценка, вы можете проигнорировать эту часть :-).

Когда вы используете firefoxоколо 100 МБ программного кода, отображенного в кеше страницы, вы обычно хотите сохранить эти 100 МБ в ОЗУ :-). В противном случае, в лучшем случае вы будете страдать задержками, в худшем случае система будет тратить все свое время обмолота между различными приложениями. Так MemAvailableчто позволяет небольшой процент оперативной памяти для этого. Это может не позволить достаточно, или это может быть слишком щедрым. «Влияние этих факторов будет варьироваться от системы к системе».

Для многих рабочих нагрузок ПК вопрос о «большом количестве файлов» может быть неактуальным. Несмотря на это, в настоящее время у меня на ноутбуке 500 МБ памяти для восстановления (из 8 ГБ ОЗУ). Это связано с ext4_inode_cache(более 300К объектов). Это произошло потому, что мне недавно пришлось сканировать всю файловую систему, чтобы найти то, что использовало мое дисковое пространство :-). Я использовал команду df -x / | sort -n, но, например, Gnome Disk Usage Analyzer сделал бы то же самое.

2. [править] Память в контрольных группах

Так называемые «Linux контейнеры» построены из namespaces, cgroupsи различных других функций по вкусу :-). Они могут предоставить достаточно убедительную среду для запуска чего-то, почти такого же, как полноценная система Linux. Хостинговые сервисы могут создавать такие контейнеры и продавать их как «виртуальные серверы» :-).

Хостинговые серверы также могут создавать «виртуальные серверы», используя функции, которых нет в основной Linux. Контейнеры OpenVZ предварительно датируют основные групповые группы на два года и могут использовать «beancounters» для ограничения памяти. Таким образом, вы не можете точно понять, как работают эти ограничения памяти, если вы только читаете документы или задаете вопросы о ядре Linux. cat /proc/user_beancountersпоказывает текущее использование и ограничения. vzubcпредставляет его в чуть более дружественном формате. Главная страница на beancounters документов имен строк.

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

Интерфейс для этого отличается по-разному, в зависимости от того, используете ли вы cgroup-v1 или cgroup-v2 .

Мой ноутбук устанавливает cgroup-v1. Я могу бежать cat /sys/fs/cgroup/memory/memory.stat. Файл показывает различные поля , включая total_rss, total_cache, total_shmem. shmem, включая tmpfs, учитывает ограничения памяти. Я думаю, вы можете рассматривать total_rssкак обратный эквивалент MemFree. И есть также файл memory.kmem.usage_in_bytes, представляющий память ядра, включая плиты. (Я предполагаю, memory.kmem.также включает memory.kmem.tcp.и любые будущие расширения, хотя это явно не задокументировано). Не существует отдельных счетчиков для просмотра памяти исправимых плит. В документе для cgroup-v1 говорится, что превышение пределов памяти не приводит к восстановлению какой-либо памяти slab. (В документе также есть заявление об отказе от ответственности за то, что оно «безнадежно устарело» и что вам следует проверить текущий исходный код).

cgroup-v2 отличается. Я думаю, что корневая группа верхнего уровня не поддерживает учет памяти. У cgroup-v2 все еще есть memory.statфайл. Все поля суммируются по дочерним cgroups, поэтому вам не нужно искать total_...поля. Есть fileполе, что означает то же самое, что и cacheсделал. Досадно, я не вижу общее поле, как rssвнутри memory.stat; Я полагаю, вам придется сложить отдельные поля. Есть отдельная статистика для исправляемой и невосстановимой памяти плиты; Я думаю, что v2 cgroup предназначена для восстановления плит, когда она начинает исчерпывать память.

Linux cgroups автоматически не виртуализируется /proc/meminfo(или любой другой файл в нем /proc), поэтому будут отображаться значения для всей машины. Это может запутать клиентов VPS. Однако можно использовать пространства имен для замены /proc/meminfoфайлом, подделанным конкретным программным обеспечением контейнера . Насколько полезны поддельные значения, будет зависеть от того, что делает это конкретное программное обеспечение.

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

Я предполагаю, что если вы находитесь внутри контейнера cgroup-v2, он будет отличаться от корня реальной системы cgroup-v2, и вы сможете увидеть память, учитывающую ее cgroup верхнего уровня. Или, если вы видите, что в cgroup не включен учет памяти, возможно, вам будет делегировано разрешение, чтобы вы могли включить учет памяти вsystemd (или эквивалентном).

sourcejedi
источник
1
Официальный документ elixir.bootlin.com/linux/v5.0-rc5/source/Documentation/...
разительный
1
это щелчок нао. Я использую ссылки GitHub, потому что они показывают первый релиз, содержащий коммит (аналогично git describe --contains). Нашел, что он связан как TL; DR с помощью вопроса SU, который оказался просто цитированием раздела, добавленного в proc.txt. Но для этого вопроса описание коммита просто идеальное ИМО :-).
sourcejedi
Похоже, что MemAvailable недоступна на большинстве виртуальных серверов ... что делать дальше?
Роланд Сеухс
@RolandSeuhs возможно изучают "beancounters". См. Правки жирным шрифтом. Если у вас есть вопрос о beancounters, я буду признателен, если вы зададите новый вопрос. Мы всегда можем ссылаться на него из этого, но подробности, вероятно, не имеют отношения к читателям, которые используют основное ядро ​​Linux.
sourcejedi