web-dev-qa-db-fra.com

éviter le gel / absence de réponse du système en raison de l'utilisation abusive de la mémoire

Si un processus nécessite beaucoup de mémoire, le système transfère tous les autres processus dans le fichier d'échange. Y compris, semble-t-il, des processus nécessaires comme le serveur X11 ou le terminal.

Ainsi, si un processus continue à allouer sans limite, tout devient insensible, jusqu'à ce que ce processus soit tué par le destructeur de MOO. Mon ordinateur portable semble être particulièrement sensible et réagit extrêmement mal. Je viens de passer une heure entière à attendre la fin du processus pendant lequel même le curseur de la souris ne pouvait pas être déplacé.

Comment cela peut-il être évité?

1) Désactiver le swap => Je lance souvent beaucoup de processus qui deviennent ensuite inactifs. Les inactifs doivent être déplacés vers l’échange.

2) Obtenez un SSD => trop cher

3) définissez un maximum de mémoire ulimit => mais cela échouera dans les cas où un programme a besoin d'une quantité de mémoire importante et résonable. le problème n'est pas qu'il en utilise trop, mais qu'il supprime les autres processus

4) garder en mémoire les programmes importants (X11, bash, kill, top, ...) et ne jamais les échanger => cela peut-il être fait? Comment? peut-être seulement échanger de gros programmes?

5)?

39
BeniBela

TL; DR

Courte temporaire/réponse

  • Le plus simple : utilisez une partition de swap plus petite et évitez que le noyau n'essaye de croire qu'il n'y a pas de limite de mémoire en exécutant des processus à partir d'un stockage lent.
    • Avec un grand échange, le MOO (gestionnaire de mémoire épuisé) n'agit pas assez tôt. En règle générale, cela correspond à la mémoire virtuelle et, dans mon expérience passée, il n'a pas tué de choses tant que l'échange n'était pas entièrement rempli, d'où le système volumineux et rampant ...
  • Besoin d'un grand échange pour une veille prolongée?
    • Tentative/problématique : définissez quelques ulimits (par exemple, cochez ulimit -v et éventuellement une limite stricte ou douce à l'aide de l'option as dans limits.conf). Auparavant, cela fonctionnait assez bien, mais grâce à WebKit introduisant gigacage, de nombreuses applications gnome s'attendent maintenant à des espaces d'adressage illimités et ne parviennent pas à s'exécuter!
    • Tentative/problématique : La politique et le ratio de surengagement excessif sont un autre moyen de gérer et d’atténuer ce problème (par exemple, sysctl vm.overcommit_memory, sysctl vm.overcommit_ratio, mais cette approche n’a pas fonctionné pour moi.
    • Difficile/compliqué : Essayez d’appliquer une priorité de groupe sur les processus les plus importants (par exemple, ssh), mais cela semble actuellement encombrant pour cgroup v1 (la version 2 facilitera les choses plus facilement) ...

J'ai aussi trouvé:

Solution à plus long terme

attendre et espérer que certains correctifs en amont pénètrent dans les noyaux distro stables. Espérons également que les fournisseurs de distribution améliorent les valeurs par défaut du noyau et exploitent mieux les groupes de contrôle systemd pour hiérarchiser la réactivité de l’interface graphique dans les éditions de bureau.

Quelques taches d'intérêt:

Donc, ce n’est pas seulement le mauvais code d’espace utilisateur et la configuration/configuration par défaut de la distribution qui sont en cause - le noyau pourrait mieux gérer cela.

Commentaires sur les options déjà envisagées

1) Désactiver l'échange

Il est recommandé de fournir au moins une petite partition de swap ( . Avons-nous vraiment besoin de swap sur les systèmes modernes? ). Désactiver le swap empêche non seulement le remplacement des pages inutilisées, mais peut également affecter la stratégie de surcommission heuristique par défaut du noyau pour l'allocation de mémoire ( . Que signifie l'heuristique dans Overcommit_memory = 0? ) compter sur les pages d'échange. Sans échange, le sur-engagement peut toujours fonctionner dans les modes heuristique (0) ou toujours (1), mais la combinaison de l’absence de permutation et de la stratégie de non-dépassement jamais (2) est probablement une très mauvaise idée. Dans la plupart des cas, aucun échange ne sera donc préjudiciable aux performances.

Par exemple, pensez à un processus de longue durée qui utilise initialement la mémoire pour un travail ponctuel, mais ne parvient pas ensuite à libérer cette mémoire et continue à exécuter l'arrière-plan. Le noyau devra utiliser RAM pour cela jusqu'à la fin du processus. Sans aucun échange, le noyau ne peut pas le rechercher pour quelque chose d'autre qui veut réellement utiliser activement la RAM. Pensez également au nombre de développeurs qui sont paresseux et ne libérez pas explicitement la mémoire après utilisation.

3) définir une mémoire ulimit maximale

Cela ne s’applique que par processus, et il est probablement raisonnable de penser qu’un processus ne devrait pas demander plus de mémoire qu’un système physiquement! Il est donc probablement utile d’empêcher un processus isolé et fou de déclencher des raclées tout en restant généreux.

4) garder en mémoire les programmes importants (X11, bash, kill, top, ...) et ne jamais les échanger

Bonne idée, mais alors ces programmes auront une mémoire qu'ils ne sont pas en train d'utiliser. Cela peut être acceptable si le programme ne demande qu'une petite quantité de mémoire.

La version 232 de systemd vient d'ajouter quelques options qui rendent cela possible: je pense que l'on pourrait utiliser le 'MemorySwapMax = 0' pour empêcher une unité (service) telle que ssh d'avoir toute sa mémoire remplacée .

Néanmoins, pouvoir hiérarchiser l’accès à la mémoire serait mieux.

Longue explication

Le noyau linux étant mieux adapté aux charges de travail du serveur, la réactivité de l'interface graphique a malheureusement été une préoccupation secondaire ... Les paramètres de gestion de la mémoire du noyau dans l'édition Desktop d'Ubuntu 16.04 LTS ne semblaient pas différer de ceux des autres éditions de serveur. Il correspond même aux valeurs par défaut de RHEL/CentOS 7.2, généralement utilisé en tant que serveur.

MOO, ulimit et compromis de l'intégrité pour la réactivité

Le swap thrashing (lorsque le jeu de mémoire de travail, c'est-à-dire les pages en cours de lecture et d'écriture dans un laps de temps donné supérieur à la RAM physique) verrouille toujours le stockage en entrée/sortie - aucune magie du noyau ne peut enregistrer un système sans tuer un processus ou deux...

J'espère que les modifications mineures de la MOO Linux apparaissant dans les noyaux plus récents reconnaîtront que cet ensemble de travail dépasse la situation de mémoire physique et met fin à un processus. Quand ce n'est pas le cas, le problème se produit. Le problème est que, avec une grande partition de swap, il peut sembler que le système a encore une marge de sécurité alors que le noyau s’engage joyeusement et continue de servir les demandes de mémoire, mais l’ensemble de travail peut déborder dans le swap, essayant de traiter efficacement c'est RAM.

Sur les serveurs, il accepte la pénalité de performances de la course pour un temps déterminé, lent, ne perdez pas de données, un compromis. Sur les ordinateurs de bureau, le compromis est différent et les utilisateurs préfèrent un peu de perte de données (sacrifice de processus) pour que les choses restent réactives.

C'était une belle analogie comique à propos de MOO: oom_pardon, aka ne tuez pas mon xlock

Par ailleurs, OOMScoreAdjust est une autre option de systemd pour aider à pondérer et éviter les processus de destruction par le MOO considérés comme plus importants.

écriture différée en mémoire tampon

Je pense que " rend l’écriture d’arrière-plan non sucer " aidera à éviter certains problèmes dans lesquels un processus monopolisé RAM provoque une autre permutation (écriture sur disque) et l’écriture en bloc sur le disque ne bloque rien. autrement vouloir IO. Ce n'est pas le problème de la cause, mais il ajoute à la dégradation globale de la réactivité.

ulimits limitation

Un problème avec ulimits est que la limite de comptabilisation et d'application s'applique à l'espace d'adressage de la mémoire virtuelle (ce qui implique la combinaison de l'espace physique et de l'espace de permutation). Selon man limits.conf:

       rss
          maximum resident set size (KB) (Ignored in Linux 2.4.30 and
          higher)

Donc, définir un ulimit à appliquer uniquement à une utilisation physique RAM ne semble plus utilisable. Par conséquent

      as
          address space limit (KB)

semble être le seul accordable respecté.

Malheureusement, comme expliqué plus en détail dans l'exemple de WebKit/Gnome, certaines applications ne peuvent pas s'exécuter si l'allocation d'espace d'adressage virtuel est limitée.

les groupes de discussion devraient aider à l'avenir?

Actuellement, cela semble fastidieux, mais il est possible d'activer certains indicateurs de groupe de contrôle du noyau cgroup_enable=memory swapaccount=1 (par exemple, dans la configuration grub), puis d'essayer d'utiliser le contrôleur de mémoire de groupe de contrôle pour limiter l'utilisation de la mémoire.

les groupes de contrôle ont des fonctionnalités de limite de mémoire plus avancées que les options 'ulimit'. CGroup v2 fait allusion aux tentatives d’amélioration du fonctionnement d’ulimits.

La combinaison mémoire + échange et limitation est remplacée par un contrôle réel sur l’espace de swap.

Les options du groupe peuvent être définies via les options du contrôle des ressources systemd . Par exemple.:

  • MémoireHigh
  • MemoryMax

D'autres options utiles pourraient être

  • IOWeight
  • CPUShares

Ceux-ci ont des inconvénients:

  1. Aérien. La documentation actuelle de docker mentionne brièvement 1% d'utilisation de mémoire supplémentaire et 10% de dégradation des performances (probablement en ce qui concerne les opérations d'allocation de mémoire - cela ne spécifie pas vraiment).
  2. Les choses concernant Cgroup/systemd ont été considérablement retravaillées récemment, de sorte que le flux en amont implique que les fournisseurs de distribution Linux attendent peut-être d’être réglés en premier.

Dans CGroup v2 , ils suggèrent que memory.high devrait être une bonne option pour limiter et gérer l'utilisation de la mémoire par un groupe de processus. Cependant, cette citation suggère que la surveillance des situations de pression de la mémoire nécessitait davantage de travail (à partir de 2015).

Une mesure de la pression de la mémoire - à quel point la charge de travail est affectée par un manque de mémoire - est nécessaire pour déterminer si une charge de travail a besoin de plus de mémoire; Malheureusement, le mécanisme de surveillance de la pression de la mémoire n'est pas encore implémenté.

Etant donné que les outils d'espace utilisateur systemd et cgroup sont complexes, je n'ai pas trouvé de moyen simple de définir quelque chose de approprié et de l'exploiter davantage. La documentation de cgroup et systemd pour Ubuntu n’est pas excellente. Les travaux futurs devraient concerner les distributions avec les éditions de bureau afin d’utiliser les groupes et les systèmes afin de permettre à ssh et aux composants X-Server/gestionnaire de fenêtres d’obtenir un accès plus prioritaire à la CPU, à la mémoire physique RAM et au stockage IO, en concurrence avec les processus occupés à permuter. Les fonctions de priorité du processeur et des E/S du noyau existent depuis un moment. Il semble que l'accès à la RAM physique soit prioritaire.

Cependant, même les priorités du processeur et IO ne sont pas correctement définies !? Quand j'ai vérifié les limites de cdd de systemd, les parts de cpu, etc. appliquées, autant que je sache, Ubuntu n'avait cuit aucune hiérarchisation prédéfinie. Par exemple. Iran:

systemctl show dev-mapper-Ubuntu\x2dswap.swap

J'ai comparé cela à la même sortie pour ssh, samba, gdm et nginx. Des éléments importants tels que l'interface graphique et la console d'administration distante doivent se battre de manière égale avec tous les autres processus en cas de blocage.

Exemple de limites de mémoire dont je dispose sur un système RAM de 16 Go

Je voulais activer l'hibernation, j'avais donc besoin d'une grande partition de swap. D'où la tentative d'atténuer avec ulimits, etc.

ulimit

Je mets * hard as 16777216 dans /etc/security/limits.d/mem.conf de sorte qu'aucun processus unique ne soit autorisé à demander plus de mémoire que ce qui est physiquement possible. Je n'empêcherai pas les combats tous ensemble, mais sans cela, un seul processus utilisant une mémoire gourmande, ou une fuite de mémoire, peut provoquer des contournements. Par exemple. J'ai constaté que gnome-contacts utilisait plus de 8 Go de mémoire lors de tâches banales, telles que la mise à jour de la liste d'adresses globale à partir d'un serveur Exchange ...

Gnome contacts chewing up RAM

Comme vu avec ulimit -S -v, de nombreuses distributions ont cette limite stricte et douce définie comme "illimitée", étant donné qu'en théorie, un processus pourrait demander beaucoup de mémoire, mais uniquement utiliser activement un sous-ensemble, et s'exécuter avec joie en pensant qu'il a reçu 24 Go de RAM alors que le système n’a que 16 Go. La limite stricte ci-dessus entraînera l'abandon des processus qui auraient pu s'exécuter correctement lorsque le noyau refuse leurs demandes de mémoire spéculative gloutonne.

Cependant, il intercepte également des choses insensées comme les contacts de gnome et au lieu de perdre la réactivité de mon bureau, je reçois l’erreur "pas assez de mémoire libre":

enter image description here

Complications avec ulimit pour l'espace d'adressage (mémoire virtuelle)

Malheureusement, certains développeurs prétendent que la mémoire virtuelle est une ressource infinie et définir ulimit sur de la mémoire virtuelle peut endommager certaines applications. Par exemple. WebKit (dont dépendent certaines applications gnome) a ajouté une fonctionnalité de sécurité gigacage qui tente d’allouer des quantités insensées de mémoire virtuelle et des erreurs FATAL: Could not allocate gigacage memory avec un indice effronté Make sure you have not set a virtual memory limit. La solution de contournement, GIGACAGE_ENABLED=no, renonce aux avantages en matière de sécurité, mais de même, ne pas être autorisé à limiter l’allocation de mémoire virtuelle, c’est aussi renoncer à une fonctionnalité de sécurité (par exemple, un contrôle de ressource qui peut empêcher un déni de service). Ironiquement, entre gigacage et les développeurs gnome, ils semblent oublier que limiter l’allocation de mémoire est en soi un contrôle de sécurité. Et malheureusement, j'ai remarqué que les applications gnome qui reposent sur le gigacage ne demandent pas explicitement une limite supérieure, de sorte que même une limite souple casse les choses dans ce cas.

Pour être honnête, si le noyau réussissait mieux à refuser l'allocation de mémoire en fonction de l'utilisation de la mémoire résidente au lieu de la mémoire virtuelle, prétendre que la mémoire virtuelle est illimitée serait moins dangereux.

surconsommer

Si vous préférez que les applications se voient refuser l'accès à la mémoire et que vous ne vouliez plus en faire, utilisez les commandes ci-dessous pour tester le comportement de votre système lorsqu'il est soumis à une pression de mémoire élevée.

Dans mon cas, le taux de validation par défaut était:

$ sysctl vm.overcommit_ratio
vm.overcommit_ratio = 50

Mais cela ne prend effet que lorsque vous modifiez la stratégie pour désactiver le sur-engagement et appliquer le ratio.

Sudo sysctl -w vm.overcommit_memory=2

Le ratio implicite ne pouvait allouer que 24 Go de mémoire au total (16 Go de RAM * 0,5 + 16 Go SWAP). Par conséquent, je ne verrais probablement jamais jamais apparaître un MOO, et il serait effectivement moins probable que des processus accèdent constamment à la mémoire lors de l'échange. Mais je vais probablement aussi sacrifier l'efficacité globale du système.

Cela provoquera le blocage de nombreuses applications, étant donné qu'il est courant que les développeurs gèrent mal le système d'exploitation refusant une demande d'allocation de mémoire. Il réduit le risque occasionnel de blocage important dû à des coups (de perdre tout votre travail après une réinitialisation matérielle) en un risque plus fréquent de blocage de diverses applications. Lors de mes tests, cela n'a pas beaucoup aidé, car le poste de travail lui-même est tombé en panne lorsque le système était sous pression mémoire et qu'il ne pouvait pas allouer de mémoire. Cependant, au moins les consoles et SSH fonctionnaient toujours.

Comment VM utilise-t-il plus de mémoire a-t-il plus d'informations?.

J'ai choisi de revenir à la valeur par défaut pour cela, Sudo sysctl -w vm.overcommit_memory=0, étant donné que la pile graphique du bureau et les applications qui s'y trouvent tombaient toujours en panne.

41
JPvRiel