GNU/Linux >> Tutoriels Linux >  >> Linux

Pourquoi mon système Linux bégaie-t-il à moins que je ne supprime continuellement les caches ?

Il semble que vous ayez déjà essayé bon nombre des choses que j'aurais suggérées au départ (modifier la configuration d'échange, modifier les planificateurs d'E/S, etc.).

Outre ce que vous avez déjà essayé de changer, je suggérerais d'envisager de modifier les valeurs par défaut quelque peu mortelles pour le comportement d'écriture différée de la machine virtuelle. Ceci est géré par les six valeurs sysctl suivantes :

  • vm.dirty_ratio :contrôle le nombre d'écritures en attente pour la réécriture avant qu'elle ne soit déclenchée. Gère l'écriture différée de premier plan (par processus) et est exprimée sous la forme d'un pourcentage entier de RAM. Par défaut, 10 % de RAM
  • vm.dirty_background_ratio :contrôle le nombre d'écritures en attente pour la réécriture avant qu'elle ne soit déclenchée. Gère la réécriture en arrière-plan (à l'échelle du système) et est exprimée sous la forme d'un pourcentage entier de RAM. Par défaut, 20 % de RAM
  • vm.dirty_bytes :Identique à vm.dirty_ratio , sauf exprimé sous la forme d'un nombre total d'octets. Soit ceci ou vm.dirty_ratio sera utilisé, celui qui a été écrit pour durer.
  • vm.dirty_background_bytes :Identique à vm.dirty_background_ratio , sauf exprimé sous la forme d'un nombre total d'octets. Soit ceci ou vm.dirty_background_ratio sera utilisé, celui qui a été écrit pour durer.
  • vm.dirty_expire_centisecs :Combien de centièmes de seconde doivent s'écouler avant que l'écriture différée en attente ne commence lorsque les quatre valeurs sysctl ci-dessus ne le déclencheraient pas déjà. La valeur par défaut est 100 (une seconde).
  • vm.dirty_writeback_centisecs :Combien de fois (en centièmes de seconde) le noyau évaluera les pages modifiées pour l'écriture différée. La valeur par défaut est 10 (un dixième de seconde).

Ainsi, avec les valeurs par défaut, tous les dixièmes de seconde, le noyau fera ce qui suit :

  • Écrivez toutes les pages modifiées dans le stockage persistant si elles ont été modifiées pour la dernière fois il y a plus d'une seconde.
  • Écrivez toutes les pages modifiées d'un processus si la quantité totale de mémoire modifiée qui n'a pas été écrite dépasse 10 % de la RAM.
  • Écrivez toutes les pages modifiées dans le système si la quantité totale de mémoire modifiée qui n'a pas été écrite dépasse 20 % de la RAM.

Ainsi, il devrait être assez facile de voir pourquoi les valeurs par défaut peuvent vous causer des problèmes, car votre système peut essayer d'écrire jusqu'à 4 gigaoctets de données vers un stockage persistant tous les dixièmes d'une seconde.

Le consensus général ces jours-ci est d'ajuster vm.dirty_ratio à 1 % de la RAM, et vm.dirty_background_ratio à 2 %, ce qui, pour les systèmes disposant de moins de 64 Go de RAM environ, se traduit par un comportement équivalent à ce qui était prévu à l'origine.

Quelques autres choses à examiner :

  • Essayez d'augmenter le vm.vfs_cache_pressure sysctl un peu. Cela contrôle l'agressivité avec laquelle le noyau récupère la mémoire du cache du système de fichiers lorsqu'il a besoin de RAM. La valeur par défaut est 100, ne la réduisez pas en dessous de 50 (vous allez obtenez un très mauvais comportement si vous descendez en dessous de 50, y compris les conditions OOM), et ne l'augmentez pas à beaucoup plus d'environ 200 (beaucoup plus élevé, et le noyau perdra du temps à essayer de récupérer de la mémoire qu'il ne peut vraiment pas). J'ai constaté que le fait de le faire monter jusqu'à 150 améliore visiblement la réactivité si vous disposez d'un stockage raisonnablement rapide.
  • Essayez de changer le mode de surcharge de la mémoire. Cela peut être fait en modifiant la valeur du vm.overcommit_memory sysctl. Par défaut, le noyau utilisera une approche heuristique pour essayer de prédire la quantité de RAM qu'il peut réellement se permettre de valider. Définir ceci sur 1 désactive l'heuristique et indique au noyau d'agir comme s'il avait une mémoire infinie. Le régler sur 2 indique au noyau de ne pas s'engager sur plus de mémoire que la quantité totale d'espace d'échange sur le système plus un pourcentage de RAM réelle (contrôlé par vm.overcommit_ratio ).
  • Essayez de modifier le vm.page-cluster sysctl. Cela contrôle le nombre de pages échangées à la fois (il s'agit d'une valeur logarithmique de base 2, donc la valeur par défaut de 3 se traduit par 8 pages). Si vous échangez réellement, cela peut aider à améliorer les performances d'échange de pages entrantes et sortantes.

Le problème a été trouvé !

Il s'avère qu'il s'agit d'un problème de performances dans le récupérateur de mémoire de Linux lorsqu'il existe un grand nombre de conteneurs/groupes de contrôle de mémoire. (Avis de non-responsabilité :mon explication est peut-être erronée, je ne suis pas un développeur du noyau.) Le problème a été résolu dans la version 4.19-rc1+ dans cet ensemble de correctifs :

Ce patchset résout le problème de la lenteur de la fonction shrink_slab() sur les machines ayant de nombreux rétrécisseurs et groupes de contrôle de mémoire (c'est-à-dire avec de nombreux conteneurs). Le problème est que la complexité de shrink_slab() est O(n^2) et qu'elle croît trop vite avec la croissance du nombre de conteneurs.

Prenons 200 conteneurs, et chaque conteneur contient 10 montures et 10 groupes. Toutes les tâches de conteneur sont isolées et ne touchent pas les montages de conteneurs étrangers.

En cas de récupération globale, une tâche doit itérer sur tous les memcgs et appeler tous les rétrécissements compatibles avec les memcgs pour chacun d'eux. Cela signifie que la tâche doit visiter 200 * 10 =2 000 rétrécissements pour chaque memcg, et puisqu'il y a 2 000 memcgs, le nombre total d'appels de do_shrink_slab() est de 2 000 * 2 000 =4 000 000.

Mon système a été particulièrement touché, car j'exécute un bon nombre de conteneurs, ce qui est probablement à l'origine du problème.

Mes étapes de dépannage, au cas où elles seraient utiles à toute personne confrontée à des problèmes similaires :

  1. Avis kswapd0 utiliser une tonne de CPU quand mon ordinateur bégaie
  2. Essayez d'arrêter les conteneurs Docker et de remplir à nouveau la mémoire → l'ordinateur ne bégaie pas !
  3. Exécutez ftrace (suite au magnifique blog d'explications de Julia Evan) pour avoir une trace, voyez ce kswapd0 a tendance à rester bloqué en shrink_slab , super_cache_count , et list_lru_count_one .
  4. Google shrink_slab lru slow , trouvez le patchset !
  5. Passez à Linux 4.19-rc3 et vérifiez que le problème est résolu.

Linux
  1. Qu'est-ce que POSIX ? Pourquoi est-ce important pour les utilisateurs Linux/UNIX ?

  2. Linux - Comment Gnome redémarre-t-il sans privilèges root ?

  3. Linux - Pourquoi n'y a-t-il pas de système de fichiers Rootfs présent sur le système ?

  4. Linux – Pourquoi faut-il autant de temps pour détecter une clé USB ?

  5. 12 raisons pour lesquelles chaque administrateur système Linux devrait être paresseux

Le problème Thundering Herd existe-t-il encore sous Linux ?

Pourquoi le préprocesseur C interprète-t-il le mot linux comme la constante 1 ?

Pourquoi cette regex ne fonctionne-t-elle pas sous Linux ?

Pourquoi mon système n'affiche-t-il que 3,2 Go de RAM alors que j'ai définitivement 4,0 Go

Pourquoi Linux ressemble-t-il à Unix si son noyau est monolithique ?

Comment Linux utilise-t-il une horloge en temps réel ?