La mémoire «mise en cache» est-elle de facto gratuite?

11

Lors de l'exécution cat /proc/meminfo, vous obtenez ces 3 valeurs en haut:

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

Pour autant que je sache, la valeur "Cached" est des caches de disque créés par le système Linux qui seront libérés immédiatement si une application a besoin de plus de RAM, donc Linux ne manquera jamais de mémoire jusqu'à ce que MemFree et Cached soient à zéro.

Malheureusement, "MemAvailable" n'est pas signalé par / proc / meminfo, probablement parce qu'il s'exécute sur un serveur virtuel. (La version du noyau est 4.4)

Ainsi, à toutes fins pratiques, la RAM disponible pour les applications est MemFree + Cached.

Cette opinion est-elle correcte?

Roland Seuhs
la source
1
Je ne veux pas marteler cet or, mais cette question est pertinente sinon un double. Je suis surpris que vous n'en ayez pas MemAvailable, il a été ajouté en 3.14.
Stephen Kitt
La réponse acceptée de cette question utilise / proc / zoneinfo, qui n'est pas également disponible sur mon vserver
Roland Seuhs
uname -a: hôte Linux 4.4.0-042stab134.8 # 1 SMP ven 7 déc 17:16:09 MSK 2018 x86_64 x86_64 x86_64 GNU / Linux
Roland Seuhs
Je soupçonne que c'est un système OpenVZ avec un noyau qui est vraiment basé sur 2.6.32, pas 4.4.
Stephen Kitt
1
@sourcejedi et il a été compilé exactement en même temps que le noyau 4.4!
Stephen Kitt

Réponses:

10

Ce point de vue peut être très trompeur dans un certain nombre de cas concrets.

Le noyau fournit maintenant une estimation de la mémoire disponible, sur le MemAvailableterrain. Cette valeur est significativement différente de MemFree + Cached.

/ proc / meminfo: fournir une estimation de la mémoire disponible [description des modifications du noyau, 2014]

De nombreux programmes d'équilibrage de charge et de placement de charge de travail vérifient / proc / meminfo pour estimer la quantité de mémoire disponible. Ils le font généralement en ajoutant "gratuit" et "mis en cache", ce qui était bien il y a dix ans, mais il est pratiquement garanti d'avoir tort aujourd'hui.

C'est faux car Cached inclut de la mémoire qui n'est pas libérable comme cache de page, par exemple des segments de mémoire partagée, tmpfs et ramfs, et il n'inclut pas de mémoire de dalle récupérable, qui peut occuper une grande partie de la mémoire système sur des systèmes pour la plupart inactifs avec beaucoup de fichiers.

Actuellement, la quantité de mémoire disponible pour une nouvelle charge de travail, sans pousser le système en permutation, peut être estimée à partir de MemFree, Active (fichier), Inactive (fichier) et SReclaimable, ainsi que les filigranes «bas» de / proc / zoneinfo. Cependant, cela pourrait changer à l'avenir, et l'espace utilisateur ne devrait vraiment pas être censé connaître les internes du noyau pour arriver à une estimation de la quantité de mémoire libre. Il est plus pratique de fournir une telle estimation dans / proc / meminfo. Si les choses changent à l'avenir, nous n'avons qu'à le changer en un seul endroit.
...

Documentation / filesystems / proc.txt:
...
MemAvailable: Une estimation de la quantité de mémoire disponible pour démarrer de nouvelles applications, sans échange. Calculé à partir de MemFree, SReclaimable, de la taille des listes de fichiers LRU et des filigranes bas dans chaque zone. L'estimation tient compte du fait que le système a besoin d'un cache de pages pour fonctionner correctement et que toutes les dalles récupérables ne seront pas récupérables, en raison des éléments utilisés. L'impact de ces facteurs variera d'un système à l'autre.

1. Détails MemAvailable

Comme il est dit ci-dessus, les tmpfs et autres Shmemmémoires ne peuvent pas être libérés, uniquement déplacés pour être échangés. Cacheden /proc/meminfopeut être très trompeur, en raison de l'inclusion de cette Shmemmémoire échangeable . Si vous avez trop de fichiers dans un tmpfs, cela pourrait occuper une grande partie de votre mémoire :-). Shmempeut également inclure des allocations de mémoire graphique , qui peuvent être très importantes.

MemAvailablene comprend pas délibérément de mémoire échangeable. Un échange excessif peut entraîner de longs retards. Vous avez peut-être même choisi de courir sans espace de swap, ou autorisé seulement un montant relativement limité.

J'ai dû revérifier le MemAvailablefonctionnement. À première vue, le code ne semblait pas mentionner cette distinction.

/*
 * 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;

Cependant, je l'ai trouvé correctement traité Shmemcomme mémoire "utilisée". J'ai créé plusieurs fichiers de 1 Go dans un tmpfs. Chaque augmentation de 1 Go est Shmemréduite MemAvailablede 1 Go. La taille des "listes de fichiers LRU" n'inclut donc pas la mémoire partagée ni aucune autre mémoire échangeable. (J'ai remarqué que le même nombre de pages est également utilisé dans le code qui calcule la "limite de blocage" ).

Ce MemAvailablecalcul suppose également que vous souhaitez conserver au moins suffisamment de cache de fichiers pour égaler le "filigrane faible" du noyau. Ou la moitié du cache actuel - la plus petite des deux. (Cela fait la même hypothèse pour les dalles récupérables également). Le «filigrane bas» du noyau peut être réglé, mais il représente généralement environ 2% de la mémoire RAM du système . Donc, si vous ne voulez qu'une estimation approximative, vous pouvez ignorer cette partie :-).

Lorsque vous utilisez firefoxenviron 100 Mo de code de programme mappé dans le cache de pages, vous souhaitez généralement conserver ces 100 Mo en RAM :-). Sinon, au mieux, vous subirez des retards, au pire le système passera tout son temps à fouiller entre différentes applications. Il en MemAvailableva de même pour un petit pourcentage de RAM. Il pourrait ne pas en permettre suffisamment, ou il pourrait être trop généreux. "L'impact de ces facteurs variera d'un système à l'autre".

Pour de nombreuses charges de travail PC, le point sur "beaucoup de fichiers" peut ne pas être pertinent. Malgré cela, j'ai actuellement 500 Mo de mémoire de dalle récupérable sur mon ordinateur portable (sur 8 Go de RAM). Cela est dû à ext4_inode_cache(plus de 300 000 objets). Cela s'est produit parce que j'ai récemment dû analyser l'ensemble du système de fichiers pour trouver ce qui utilisait mon espace disque :-). J'ai utilisé la commande df -x / | sort -n, mais par exemple, Gnome Disk Usage Analyzer ferait la même chose.

2. [modifier] Mémoire dans les groupes de contrôle

Soi-disant « conteneurs Linux » sont construits à partir namespaces, cgroupset d'autres caractéristiques selon le goût :-). Ils peuvent fournir un environnement suffisamment convaincant pour exécuter quelque chose comme un système Linux complet. Les services d'hébergement peuvent créer des conteneurs comme celui-ci et les vendre en tant que "serveurs virtuels" :-).

Les serveurs d'hébergement peuvent également créer des "serveurs virtuels" en utilisant des fonctionnalités qui ne sont pas dans Linux principal. Les conteneurs OpenVZ sont antérieurs à deux ans pour les groupes principaux de la ligne principale et peuvent utiliser des «beancounters» pour limiter la mémoire. Vous ne pouvez donc pas comprendre exactement comment ces limites de mémoire fonctionnent si vous ne lisez que des documents ou posez des questions sur le noyau Linux principal. cat /proc/user_beancountersmontre l'utilisation actuelle et les limites. vzubcle présente dans un format légèrement plus convivial. La page principale sur les beancounters documente les noms des lignes.

Les groupes de contrôle incluent la possibilité de définir des limites de mémoire sur les processus qu'ils contiennent. Si vous exécutez votre application dans un tel groupe de contrôle, alors toute la mémoire système ne sera pas disponible pour l'application :-). Alors, comment pouvons-nous voir la mémoire disponible dans ce cas?

L'interface pour cela diffère de plusieurs façons, selon que vous utilisez cgroup-v1 ou cgroup-v2 .

L'installation de mon ordinateur portable utilise cgroup-v1. Je peux courir cat /sys/fs/cgroup/memory/memory.stat. Le fichier présente divers domaines , y compris total_rss, total_cache, total_shmem. shmem, y compris tmpfs, compte pour les limites de mémoire. Je suppose que vous pouvez regarder total_rsscomme un équivalent inverse de MemFree. Et il y a aussi le fichier memory.kmem.usage_in_bytes, représentant la mémoire du noyau, y compris les dalles. (Je suppose que memory.kmem.comprend également memory.kmem.tcp.et toutes les extensions futures, bien que cela ne soit pas documenté explicitement). Il n'y a pas de compteurs séparés pour afficher la mémoire de dalle récupérable. Le document pour cgroup-v1 indique que l'atteinte des limites de mémoire ne déclenche pas la récupération de la mémoire de dalle. (Le document contient également une clause de non-responsabilité indiquant qu'il est "désespérément dépassé" et que vous devez vérifier le code source actuel).

cgroup-v2 est différent. Je pense que le groupe racine (niveau supérieur) ne prend pas en charge la comptabilité de la mémoire. cgroup-v2 possède toujours un memory.statfichier. Tous les champs sont additionnés sur les groupes de contrôle enfants, vous n'avez donc pas besoin de rechercher de total_...champs. Il y a un filechamp, ce qui signifie la même chose cache. Ennuyeusement, je ne vois pas un champ global comme à l' rssintérieur memory.stat; Je suppose que vous devrez ajouter des champs individuels. Il existe des statistiques distinctes pour la mémoire de dalle récupérable et non récupérable; Je pense qu'un groupe de contrôle v2 est conçu pour récupérer des dalles lorsqu'il commence à manquer de mémoire.

Les cgroups Linux ne virtualisent pas automatiquement /proc/meminfo(ou tout autre fichier /proc), ce qui afficherait les valeurs pour la machine entière. Cela dérouterait les clients VPS. Cependant, il est possible d'utiliser des espaces de noms pour les remplacer /proc/meminfopar un fichier truqué par le logiciel de conteneur spécifique . L'utilité des fausses valeurs dépendra de ce que fait ce logiciel spécifique.

systemdestime que cgroup-v1 ne peut pas être délégué en toute sécurité, par exemple à des conteneurs. J'ai regardé à l'intérieur d'un systemd-nspawnconteneur sur mon système cgroup-v1. Je peux voir le groupe de contrôle dans lequel il a été placé et la mémoire qui en tient compte. D'un autre côté, le contenu systemdne configure pas les groupes de contrôle par service habituels pour la comptabilité des ressources. Si la comptabilité de la mémoire n'était pas activée dans ce groupe de contrôle, je suppose que le conteneur ne pourrait pas l'activer.

Je suppose que si vous êtes dans un conteneur cgroup-v2, il sera différent de la racine d'un vrai système cgroup-v2, et vous pourrez voir la mémoire représenter son groupe de contrôle de niveau supérieur. Ou si le groupe de contrôle que vous pouvez voir n'a pas activé la comptabilité de la mémoire, nous espérons que vous bénéficierez d'une autorisation déléguée afin que vous puissiez activer la comptabilité de la mémoire danssystemd (ou équivalent).

sourcejedi
la source
1
c'est clicky nao. J'utilise des liens GitHub car ils montrent la première version contenant le commit (similaire à git describe --contains). Je l'ai trouvé lié en tant que TL; DR par une question SU, qui s'est avéré ne citer que la section ajoutée à proc.txt. Mais pour cette question, la description du commit est juste parfaite IMO :-).
sourcejedi
MemAvailable ne semble pas être disponible sur la plupart des serveurs virtuels ... que faire alors?
Roland Seuhs
@RolandSeuhs apprend peut-être les "beancounters". Voir les modifications en gras. Si vous avez une question sur les beancounters, j'apprécierais que vous posiez une nouvelle question. Nous pouvons toujours le lier à partir de celui-ci, mais les détails ne sont probablement pas pertinents pour les lecteurs qui utilisent un noyau Linux principal.
sourcejedi