Question Désactiver le tueur de MOO Linux par défaut?


Le tueur de MOO sous Linux fait des ravages avec diverses applications de temps en temps, et il apparaît que rien n’est vraiment fait du côté du développement du noyau pour améliorer cela. Ne serait-il pas préférable, en tant que meilleure pratique lors de la création d'un nouveau serveur, pour inverser la valeur par défaut de la mémoire surchargée, c’est-à-dire la désactiver (vm.overcommit_memory=2) sauf si vous savez que vous le souhaitez pour votre usage particulier? Et quels seraient ces cas d'utilisation pour lesquels vous savez que vous voulez que le dépassement de contrat soit effectif?

En prime, depuis le comportement en cas de vm.overcommit_memory=2 dépend de vm.overcommit_ratio et permuter l’espace, quelle serait la bonne règle pour dimensionner les deux derniers afin que toute cette installation continue de fonctionner raisonnablement?


36
2018-01-12 14:16


origine




Réponses:


Une analogie intéressante (de http://lwn.net/Articles/104179/):

Une compagnie aérienne a découvert que   était moins cher de piloter ses avions avec   moins de carburant à bord. Les avions seraient   être plus léger et utiliser moins de carburant et d'argent   a été sauvé. En de rares occasions cependant   la quantité de carburant était insuffisante,   et l'avion s'écraserait. Ce   problème a été résolu par les ingénieurs de   la société par le développement d'un   mécanisme spécial d'absence de carburant.   En cas d'urgence, un passager était   sélectionné et jeté hors de l'avion.   (Si nécessaire, la procédure a été   répété.) Un large corpus de théorie a été   développé et de nombreuses publications ont été   consacré au problème de bien   en sélectionnant la victime à éjecter.   La victime devrait-elle être choisie au hasard?   Ou faut-il choisir le plus lourd   la personne? Ou le plus vieux? Devrait   les passagers paient pour ne pas être   éjecté, de sorte que la victime soit   les plus pauvres à bord? Et si pour   par exemple la personne la plus lourde était   choisi, devrait-il y avoir un spécial   exception au cas où il s'agissait du pilote?   Les passagers de première classe doivent-ils être   exempté? Maintenant que le mécanisme OOF   existait, il serait activé tous les   de temps en temps, et éjecter les passagers   même quand il n'y avait pas de pénurie de carburant.   Les ingénieurs étudient encore   précisément comment ce dysfonctionnement est   causé.


62
2017-10-25 19:36



J'ai beaucoup apprécié cela, merci de l'avoir découvert. - Nick Bolton


Le tueur OOM ne fait des ravages que si vous avez surchargé votre système. Donnez-lui suffisamment d'échange, et n'exécutez pas d'applications qui décident soudainement de consommer des quantités énormes de RAM, et vous n'aurez pas de problème.

Pour répondre spécifiquement à vos questions:

  • Je ne pense pas que ce soit une bonne idée de désactiver le sur-engagement dans le cas général; très peu d'applications sont écrites pour traiter correctement brk(2) (et les wrappers qui l'utilisent, tels que malloc(3)) retourne une erreur. Lorsque j’ai expérimenté cela dans mon travail précédent, il a été jugé plus fastidieux d’obtenir tout ce qui était capable de gérer les erreurs de mémoire insuffisante que de faire face aux conséquences d’un MOO (qui, dans notre cas, était bien pire que de devoir redémarrer le service occasionnel si un MOO se produisait - nous avons dû redémarrer un cluster entier, car GFS est une pile de matières fécales fumante.
  • Vous souhaitez sur-engager pour tout processus surchargeant en mémoire. Les deux principaux coupables ici sont Apache et la machine virtuelle Java, mais de nombreuses applications le font à un degré plus ou moins grand. Ils pense ils pourrait besoin de beaucoup de mémoire à un moment donné dans l’avenir, alors ils en prennent une grosse part. Sur un système activé par la surcapacité, le noyau dit "meh, peu importe, viens me gêner quand tu veux vraiment écrire sur ces pages" et rien de mal ne se passe. Sur un système de surcommit-off, le noyau dit "non, vous ne pouvez pas avoir autant de mémoire, si vous écrivez tout cela à un moment donné dans le futur, je suis désossé, donc pas de mémoire pour vous!" et l'allocation échoue. Puisque rien "Oh, OK, puis-je avoir cette plus petite quantité de segment de données de processus?", alors le processus (a) se ferme avec une erreur de mémoire insuffisante ou (b) ne vérifie pas le code de retour de malloc, pense pouvoir y aller, et écrit dans un emplacement mémoire invalide, provoquant un segfault. Heureusement, la machine virtuelle Java effectue tout son travail pré-alloué au démarrage (donc votre machine virtuelle démarre ou meurt immédiatement, ce que vous remarquez généralement), mais Apache fait des trucs géniaux à chaque nouvel enfant, ce qui peut avoir des effets excitants en production (non reproductible). "types d'excitation).
  • Je ne voudrais pas que mon surcommit_ratio soit supérieur à la valeur par défaut de 50%. Encore une fois, de mes tests, bien que la mise en place autour de 80 ou 90 pourrait du son comme une bonne idée, le noyau nécessite de gros morceaux de mémoire à des moments inopportuns, et un système entièrement chargé avec un taux de surcapacité élevé risque de ne pas disposer de suffisamment de mémoire de secours lorsque le noyau en a besoin (ce qui engendre la peur, la pestilence et des difficultés). Donc, jouer avec surcommit introduit un nouveau mode d'échec, encore plus amusant - plutôt que de simplement redémarrer le processus obtenu par OOM lorsque vous manquez de mémoire, votre machine tombe en panne, ce qui entraîne une panne totale de la machine. IMPRESSIONNANT!
  • L'échange d'espace dans un système dépourvu de surcapacité dépend de la quantité de mémoire demandée mais non utilisée par vos applications, plus d'une marge de sécurité suffisante. Déterminer ce qui est nécessaire dans un cas spécifique reste un exercice pour le lecteur.

En gros, mon expérience est que désactiver le sur-engagement est une belle expérience qui fonctionne rarement aussi bien dans la pratique que dans la théorie. Cela correspond bien à mon expérience avec d’autres réglages dans le noyau - les développeurs du noyau Linux sont presque toujours plus intelligents que vous, et les valeurs par défaut sont optimales pour les applications plus vastes, vaste majorité des cas. Laissez-les tranquilles et cherchez plutôt le processus qui a la fuite et corrigez-le.


31
2018-01-12 21:31



Je ne veux pas que mon processus de sauvegarde soit tué parce que quelqu'un fait mon service web. Les exceptions sont acceptables, mais la valeur par défaut doit être la sécurité et la cohérence. Les optimisations telles que le MOO doivent être activées manuellement à mon humble avis. C'est comme coder, coder proprement, puis optimiser. Le sur-envoi est une fonctionnalité intéressante, mais ne devrait pas être la valeur par défaut. - Aki
Si vous ne voulez pas que votre processus de sauvegarde soit tué parce que quelqu'un fait du DoS sur votre serveur Web, ne configurez pas votre serveur Web de manière à ce qu'un DoS puisse surcharger les ressources du système. - womble♦
J'ai 8 Go de RAM et juste en cours d'exécution avec Firefox et une machine virtuelle, le tueur de MOO tue parfois la machine virtuelle. Lors de la compilation d'Unreal Engine 4, chaque appel de résonance nécessite 1 à 1,5 Go de mémoire et, encore une fois, le tueur OOM tue de temps en temps. Maintenant, je suis généralement d'accord avec ça. Sans le tueur OOM, ils auraient probablement une erreur de segmentation de toute façon. C'est juste que chaque fois que le tueur OOM veut tuer un processus, mon système se bloque pendant 10 minutes avant que le mauvais processus ne soit réellement tué. Bug peut-être? Probablement. Est-ce que je le veux? Définitivement pas. Et c’est la raison pour laquelle vous voudrez peut-être désactiver le tueur OOM. - Shahbaz
Si vous faites tout cela sur une boîte, vous avez besoin de plus de RAM, et la désactivation de la surconsommation ne fera qu'empirer les choses. - Ben Lutgens


Hmm, je ne suis pas totalement convaincu par les arguments en faveur de la surconsommation et du tueur OOM ... Quand womble écrit,

"Le tueur de MOO ne fait des ravages que si vous avez surchargé votre système. Donnez-lui suffisamment d'échange, et n'exécutez pas d'applications qui décident soudainement de consommer des quantités énormes de RAM, et vous n'aurez aucun problème."

Il décrit un scénario d’environnement dans lequel la surcharge et le tueur de MOO ne sont pas appliqués ou n’agissent pas vraiment (si toutes les applications allouaient de la mémoire au besoin et qu’il y avait suffisamment de mémoire virtuelle à allouer, les écritures en mémoire suivraient de près les allocations de mémoire sans erreurs, nous ne pouvons donc pas vraiment parler de système sur-engagé même si une stratégie de sur-engagement était activée). Il s’agit d’une admission implicite que le sur-engagement et le tueur OOM sont plus efficaces lorsque leur intervention n’est pas nécessaire, ce qui est en quelque sorte partagé par la plupart des partisans de cette stratégie, autant que je sache (et j’admets que je ne peux pas en dire beaucoup ...). De plus, me référer à des applications ayant des comportements spécifiques lors de la préallocation de mémoire me fait penser qu’une manipulation spécifique pourrait être réglée au niveau de la distribution, au lieu d’avoir une approche système par défaut basée sur des méthodes heuristiques (personnellement, j’estime qu’une approche heuistique n’est pas une très bonne approche. pour les trucs du noyau)

Pour ce qui concerne la JVM, eh bien, c’est une machine virtuelle, elle a besoin dans une certaine mesure d’allouer toutes les ressources qu’elle Besoins au démarrage, il peut ainsi créer son "faux" environnement pour ses applications et garder ses ressources disponibles séparées de l'environnement hôte, dans la mesure du possible. Ainsi, il serait peut-être préférable qu’elle échoue au démarrage, plutôt qu’après un certain temps, en raison d’une condition "externe" du MOO (causée par un excès de motivation / du tueur MOO / peu importe), ou de toute façon pour une telle condition interférant avec sa propre stratégies de gestion des MOO internes (en général, une machine virtuelle doit obtenir toutes les ressources requises dès le début et le système hôte doit les "ignorer" jusqu'à la fin, de la même manière que toute quantité de mémoire vive physique partagée avec une carte graphique n'est jamais - et ne peut pas être - touché par l'OS).

À propos d'Apache, je doute qu'avoir le serveur entier tué et redémarré de temps en temps soit mieux que de laisser un seul enfant, ainsi qu'une seule connexion, échouer dès le début (= de l'enfant / de la connexion) (comme s'il s'agissait d'une toute nouvelle instance de JVM créée après une autre instance exécutée pendant un certain temps). Je suppose que la meilleure "solution" pourrait dépendre d'un contexte spécifique. Par exemple, si vous envisagez un service de commerce électronique, il peut s'avérer beaucoup préférable d'avoir parfois quelques connexions à la carte d'achat défaillantes au lieu de perdre l'ensemble du service, avec le risque, par exemple, d'interrompre la finalisation d'une commande en cours, ou (Peut-être pire) un processus de paiement, avec toutes les conséquences de l'affaire (peut-être inoffensif, mais peut-être nuisible - et bien sûr, lorsque des problèmes surviennent, ceux-ci sont pires qu'une condition d'erreur non reproductible aux fins du débogage).

De la même manière, sur un poste de travail, le processus qui consomme le plus de ressources et qui constitue donc un premier choix pour le destructeur de MOO peut être une application gourmande en mémoire, telle qu'un transcodeur vidéo ou un logiciel de rendu, probablement la seule application. l'utilisateur veut rester intact. Ces considérations m'indiquent que la stratégie par défaut du tueur OOM est trop agressive. Il utilise une approche de "pire ajustement" qui est en quelque sorte similaire à celle de certains systèmes de fichiers (OOMK essaie de libérer autant de mémoire que possible, tout en réduisant le nombre de sous-processus tués, afin d'éviter toute intervention ultérieure dans un délai aussi court. ainsi, un fs peut allouer plus d’espace disque que ce qui est réellement nécessaire pour un certain fichier, afin d’empêcher toute allocation supplémentaire si le fichier grossissait et empêchant ainsi, dans une certaine mesure, la fragmentation).

Cependant, je pense qu'une politique opposée, telle qu'une approche de "meilleur ajustement", pourrait être préférable, afin de libérer la mémoire exacte nécessaire à un moment donné, et de ne pas s'embarrasser de "gros" processus, ce qui pourrait bien être une perte de temps. mais le noyau ne peut pas le savoir (hmm, je peux imaginer que le fait de garder trace du nombre et de la durée des accès à la page laisse deviner si un processus alloue de la mémoire, il n’en a plus besoin, alors devinez si un processus gaspille de la mémoire ou utilise simplement beaucoup, mais les retards d'accès doivent être pondérés en fonction des cycles de l'unité centrale pour distinguer une perte de mémoire d'une mémoire et utilisation intensive du processeur, mais, même s’il est potentiellement imprécis, une telle heuristique peut entraîner une surcharge excessive).

De plus, il n’est peut-être pas vrai que tuer le moins de processus possibles est toujours un bon choix. Par exemple, dans un environnement de bureau (imaginons un nettop ou un netbook avec des ressources limitées, par exemple), un utilisateur peut exécuter un navigateur avec plusieurs onglets (donc consommer beaucoup de mémoire - supposons qu'il s'agisse du premier choix pour OOMK). , ainsi que quelques autres applications (un traitement de texte avec des données non enregistrées, un client de messagerie, un lecteur de pdf, un lecteur multimédia, ...), quelques démons (système), ainsi que quelques instances de gestionnaire de fichiers. Maintenant, une erreur de MOO se produit et le MOQ choisit de tuer le navigateur pendant que l'utilisateur fait quelque chose jugé "important" sur le net ... l'utilisateur serait déçu. D'autre part, la fermeture des quelques instances du gestionnaire de fichiers en mode inactif pourrait libérer la quantité exacte de mémoire nécessaire tout en maintenant le système en état de fonctionner, mais de manière plus fiable.

Quoi qu'il en soit, je pense que l'utilisateur devrait avoir la possibilité de prendre lui-même la décision. Dans un système de bureau (= interactif), cela devrait être relativement facile à faire, à condition que suffisamment de ressources soient réservées pour demander à l'utilisateur de fermer n'importe quelle application (même fermer quelques onglets pourrait suffire) et gérer son choix (une option pourrait consiste à créer un fichier d'échange supplémentaire, s'il y a suffisamment d'espace). Pour les services (et en général), j’envisageais également deux autres améliorations possibles: l’une concerne la consignation des intervalles tueurs de MOO, ainsi que les processus démarrant / forçant les échecs de telle manière que l’échec puisse être facilement débogué (par exemple, une API informer le processus à l'origine de la création ou de la création du nouveau processus - ainsi, un serveur comme Apache, doté du correctif approprié, pourrait fournir une meilleure journalisation pour certaines erreurs); cela pourrait être fait indépendamment du sur-engagement / OOMK en cours d'effort; en second lieu, mais sans importance, un mécanisme pourrait être mis en place pour affiner l'algorithme OOMK - Je sais qu'il est possible, dans une certaine mesure, de définir une politique spécifique processus par processus, mécanisme de configuration «centralisée», basé sur une ou plusieurs listes de noms d'applications (ou id) pour identifier les processus pertinents et leur attribuer un certain degré d'importance (selon les attributs répertoriés); un tel mécanisme devrait (ou du moins pourrait) être également mis en couches, de sorte qu'il puisse y avoir une liste de niveau supérieur définie par l'utilisateur, une liste définie par le système (distribution), et des entrées définies par l'application (au niveau inférieur) Par exemple, un gestionnaire de fichiers DE peut demander à OOMK de tuer n'importe quelle instance en toute sécurité, puisqu'un utilisateur peut le rouvrir en toute sécurité pour accéder à la vue des fichiers perdus. Toute opération importante, telle que déplacer / copier / créer des données, pourrait être déléguée. un processus plus "privilégié").

De plus, une API pourrait être fournie afin de permettre aux applications d’augmenter ou de réduire leur niveau «d’importance» au moment de l’exécution (en ce qui concerne les objectifs de gestion de la mémoire et quelle que soit la priorité d’exécution), de sorte qu'un processeur Word puisse par exemple démarrer avec une «importance» faible, mais augmentez-la au fur et à mesure que certaines données sont conservées avant le vidage dans un fichier, ou une opération d'écriture est en cours d'exécution, et diminuez l'importance à nouveau une fois que cette opération se termine (de manière analogue, un gestionnaire de fichiers pourrait changer de niveau lorsqu'il passait juste Lit des fichiers pour traiter des données et vice-versa, au lieu d'utiliser des processus distincts, et Apache pourrait attribuer différents niveaux d'importance à différents enfants, ou modifier un état enfant conformément à une politique décidée par les administrateurs système et exposée via le serveur Apache - ou tout autre type de serveur. - réglages). Bien sûr, une telle API pourrait être et serait utilisée de manière abusive, mais je pense qu’il s’agit d’une préoccupation mineure par rapport au noyau qui tue arbitrairement des processus pour libérer de la mémoire, sans aucune information pertinente sur ce qui se passe sur le système (et sur la consommation de mémoire / le moment de la création). les mêmes ne sont pas assez pertinents ou "valident" pour moi) - seuls les utilisateurs, les administrateurs et les rédacteurs de programme peuvent vraiment déterminer si un processus est "encore nécessaire" pour une raison quelconque, quelle en soit la raison et / ou si l'application est en cours un état conduisant à la perte de données ou à d'autres dommages / troubles s'il est tué; cependant, certaines hypothèses pourraient encore être faites, par exemple rechercher des ressources d'un certain type (descripteurs de fichier, sockets réseau, etc.) acquises par un processus et avec des opérations en attente, indiquer si un processus doit être dans un "état" supérieur celui-ci, ou si celui-ci est «auto-établi», est plus élevé que nécessaire et peut être réduit (approche agressive, à moins que l'utilisateur ne le remplace, par exemple en forçant un certain état ou en demandant - par le biais des listes susmentionnées - de respecter choix de l'application).

Ou bien, évitez simplement de surcharger et laissez le noyau faire ce qu’il doit faire, allouer des ressources (sans les sauver arbitrairement comme le fait le tueur de MOO), planifier des processus, empêcher les famines et les blocages (ou les sauver), assurer la préemption et séparation des espaces mémoire, etc.

Je passerais également quelques mots sur les approches de sur-engagement. D’autres discussions, j’ai avancé l’idée que l’une des principales préoccupations concernant le sur-engagement (à la fois comme raison de le vouloir et comme source de problèmes possibles) consiste en une manipulation des fourchettes: honnêtement, je ne sais pas exactement comment la stratégie en écriture est mise en œuvre, mais je pense que toute stratégie agressive (ou optimiste) pourrait être atténuée par une stratégie de localité à la swap-like. En d’autres termes, au lieu de simplement cloner (et ajuster) un code de processus et des structures de planification divisés, quelques autres pages de données pourraient être copiées avant une écriture réelle, en choisissant parmi les pages auxquelles le processus parent a accédé plus fréquemment (c’est-à-dire, utiliser un compteur pour les opérations d'écriture).

Tout, bien sûr, à mon humble avis.


5
2018-03-22 21:22



"De plus, une API pourrait être fournie afin de permettre aux applications d'augmenter ou de réduire leur niveau" d'importance "au moment de l'exécution" L'importance est: /proc/$PID/oom_adj. - Vi.
En ce qui concerne la machine virtuelle Java, il existe un piège qui vous oblige parfois à demander un excès de mémoire: si vous souhaitez créer une autre machine virtuelle à partir de votre machine virtuelle d'origine, elle appelle fork (). Un appel fork va allouer autant de mémoire que le processus original (en premier), jusqu'à ce qu'il commence réellement le processus. Supposons donc que vous avez une machine virtuelle Java de 4 Go et que vous souhaitez créer une nouvelle machine virtuelle Java de 512 Ko, à moins que vous n'ayez trop de travail, vous aurez besoin de 8 Go de mémoire pour le faire ... - alci
@Vi. Semble maintenant est /proc/$PID/oom_score_adj - erm3nda


Si les processus épuisent votre mémoire de manière excessive, ce qui peut menacer la stabilité du système, le destructeur de MOO entre en scène. Le tueur de MOO a pour tâche de tuer les processus jusqu'à ce que suffisamment de mémoire soit libérée pour le bon déroulement du processus.   Le tueur OOM doit sélectionner le "meilleur" processus à tuer. Le terme «meilleur» fait référence à ce processus qui libère une mémoire maximale lors de la mise à mort et qui est également moins important pour le système. L'objectif principal est de supprimer le plus petit nombre de processus possible afin de minimiser les dommages causés tout en maximisant la quantité de mémoire libérée.   Pour faciliter cela, le noyau maintient oom_score pour chacun des processus. Vous pouvez voir le oom_score de chacun des processus dans le système de fichiers / proc sous le répertoire pid

# cat /proc/10292/oom_score

Plus la valeur de oom_score d'un processus est élevée, plus sa probabilité d'être tué par le tueur MOM est grande, plus le nombre de morts est élevé.

Crédit:- Le noyau Linux lance le tueur de MOO


0
2018-03-08 11:04