web-dev-qa-db-fra.com

Linux effectue-t-il "l'échange opportuniste" ou est-ce un mythe?

Supposons qu'un programme demande une certaine mémoire, mais il n'ya pas assez de mémoire libre. Il existe différentes manières de réagir Linux. Une réponse consiste à sélectionner une autre mémoire utilisée, qui n'a pas été accessible récemment et déplacez cette mémoire inactive pour échanger.

Cependant, je vois de nombreux articles et commentaires qui vont au-delà de cela. Ils disent même quand il y a une grande quantité de mémoire libre, Linux décidera parfois d'écrire une mémoire inactive pour échanger. L'écriture pour échanger à l'avance signifie que lorsque nous voulons finalement utiliser cette mémoire, nous n'avons pas à attendre une écriture de disque. Ils disent que ceci est une stratégie délibérée pour optimiser les performances.

Sont-ils bien? Ou est-ce un mythe? Citer votre source (s).

Veuillez comprendre cette question en utilisant les définitions suivantes:

  • Swap
  • libre Mémoire - la mémoire "libre" affichée par la commande libre . Ceci est la valeur MemFree de /proc/meminfo. /proc/meminfo Est un fichier texte virtuel fourni par le noyau. Voir PROC (5) , ou RHEL DOCS .
  • même quand il y a une grande quantité de mémoire libre - Aux fins de l'argument, imaginez qu'il y a plus de 10% de mémoire libre.

Les références

Voici quelques termes de recherche: Linux "échange opportuniste" OR (échange "lorsque le système n'a rien de mieux à faire" OR "quand il n'a rien de mieux à faire "OR" Lorsque le système est inactif "OR" pendant le temps de ralenti ")

Dans le deuxième résultat le plus élevé sur Google, un utilisateur STACKEXCHANGE demande "Pourquoi utiliser Swap lorsqu'il y a plus que suffisamment d'espace libre en RAM?", Et copie les résultats de la commande free indiquant environ 20% de mémoire libre. En réponse à cette question spécifique, je vois que cette réponse est très votée:

Linux commence à échanger avant que le RAM est rempli. Ceci est fait pour améliorer les performances et la réactivité:

  • La performance est augmentée car parfois RAM est mieux utilisée pour le cache de disque que de stocker la mémoire du programme. Il est donc préférable d'échanger un programme qui a été inactif pendant un certain temps et gardez plutôt des fichiers souvent utilisés dans le cache.

  • La réactivité est améliorée en échangeant des pages lorsque le système est inactif, plutôt que lorsque la mémoire est pleine et que certains programmes sont en cours d'exécution et demandant davantage RAM pour terminer une tâche.

L'échange est ralenti le système, bien sûr - mais l'alternative à l'échange n'est pas échangeable, il dispose de plus RAM ou d'utiliser moins de RAM.

Le premier résultat sur Google a été marqué comme un duplicata de la question ci-dessus :-). Dans ce cas, l'astituant a copié des détails montrant 7 Go MemFree, sur 16 Go. La question a une réponse acceptée et évitée sa propre:

Seulement seulement quand il n'y a pas de mémoire libre n'est que le cas si vous définissez swappiness sur 0. Sinon, pendant le temps d'inactivité, le noyau échangera la mémoire. Ce faisant, les données ne sont pas supprimées de la mémoire, mais une copie est faite dans la partition de swap.

Cela signifie que la situation devrait-elle surgir que la mémoire est épuisée, il n'est pas nécessaire d'écrire sur le disque alors et là-bas. Dans ce cas, le noyau peut simplement écraser les pages de mémoire qui ont déjà été échangées, pour lesquelles il sait qu'il a une copie des données.

Le paramètre swappiness contrôle fondamentalement à quel point cela le fait.

L'autre devis ne prétend pas explicitement que les données échangées sont également conservées dans la mémoire. Mais il semble que vous préfériez cette approche, si vous échangez parfois parfois lorsque vous avez 20% de mémoire libre, et la raison pour laquelle vous le faites est d'améliorer les performances.

Autant que je sache, Linux prend en charge la prise en charge d'une copie des mêmes données dans la mémoire principale et dans l'espace d'échange.

J'ai également remarqué l'affirmation commune selon laquelle "l'échange opportuniste" se passe "pendant le temps de ralenti". Je comprends que c'est censé aider à me rassurer que cette fonctionnalité est généralement bonne pour la performance. Je n'inclut pas cela dans ma définition ci-dessus, car je pense que cela a déjà suffisamment de détails pour faire une bonne question claire. Je ne veux pas que cela soit plus compliqué qu'il n'a besoin d'être.

Motivation originale

ATOP affiche `ébullition` (échange) lorsque j'ai des gigaoctets de mémoire libre. Pourquoi?

Il y a quelques rapports comme celui-ci, de l'écriture de Linux à échanger lorsqu'il y a beaucoup de mémoire libre. "L'échange opportuniste" pourrait expliquer ces rapports. Dans le même temps, au moins une cause alternative a été suggérée. En tant que première étape dans la recherche de causes possibles: Linux a-t-il déjà effectué un "échange opportuniste" tel que défini ci-dessus?

Dans l'exemple que j'ai signalé, la question a été répondue à ce jour. La cause n'était pas un échange opportuniste.

12
sourcejedi

Linux ne fait pas "échange opportuniste" tel que défini dans cette question.


Les références principales suivantes ne mentionnent pas le concept du tout:

  1. Comprendre le gestionnaire de mémoire virtuel Linux . Un livre en ligne de Mel Gorman. Écrit en 2003, juste avant la sortie de Linux 2.6.0.
  2. Documentation/Admin-Guide/SYSCTL/VM.RST . Il s'agit de la principale documentation des paramètres corrigés de la gestion de la mémoire virtuelle Linux.

Plus précisement:

10.6 Daemon de page (kswapd)

Historiquement kswapd _ Utilisé pour se réveiller toutes les 10 secondes mais maintenant, il est seulement réveillé par l'allocateur de la page physique lorsque le nombre de pages libres dans une zone est atteint. [...] sous pression de mémoire extrême, les processus feront le travail de kswapd synchrone. [...] kswapd continue de libérer des pages jusqu'à ce que le filigrane pages_high soit atteint.

Sur la base de ce qui précède, nous ne nous attendions à aucun échange lorsque le nombre de pages libres est plus élevé que le "hauteur de filigrane".

Deuxièmement, cela nous dit que le but de kswapd est de faire plus de pages gratuites.

Lorsque kswapd écrit une page de mémoire pour échanger, il libère immédiatement la page de la mémoire. kswapd ne conserve pas une copie de la page échangée en mémoire.

Linux 2.6 utilise le " RMAP " Pour libérer la page. À Linux 2.4, l'histoire était plus complexe. Lorsqu'une page a été partagée par plusieurs processus, KSWAPD n'a pas été en mesure de le libérer immédiatement. C'est une histoire ancienne. Tous les messages liés concernent Linux 2.6 ou plus.

SUPPORTÉ

Ce contrôle est utilisé pour définir la manière dont le noyau sera agressif échanger des pages de mémoire. Des valeurs plus élevées augmenteront l'agressivité, les valeurs plus basses diminuent la quantité de swap. Une valeur de 0 indique au noyau de ne pas lancer d'échange avant que la quantité de pages libres et des pages appuyées par fichier soit inférieure à la hauteur de l'eau dans une zone.

Cette citation décrit un cas spécial: si vous configurez la valeur swappiness à être 0. Dans ce cas, nous devrions en outre ne pas attendre d'échange que le nombre de cache Les pages sont tombées au bon filigrane. En d'autres termes, le noyau essaiera de jeter presque tout le cache de fichier avant qu'il ne commence à échanger. (Cela pourrait causer des ralentissements énormes. Vous devez avoir un cache de fichier! Le cache de fichier est utilisé pour contenir le code de tous vos programmes d'exécution :-)

Quelles sont les filigranes?

Les citations ci-dessus soulèvent la question suivante: Quelle est la taille des réservations de mémoire "filigrane" sur mon système ? Réponse: sur un "petit" système, les filigranes de la zone par défaut peuvent être aussi élevés que 3% de Mémoire. Cela est dû au calcul du filigrane "min". Sur des systèmes plus importants, les filigranes seront une proportion plus faible, approchant de 0,3% de la mémoire.

Donc, si la question concerne un système avec plus de 10% de mémoire libre, les détails exacts de cette logique de filigrane ne sont pas significatifs.

Les filigranes pour chaque "zone" individuelle sont indiqués dans /proc/zoneinfo, Comme documenté dans Proc (5) . Un extrait de ma zoneInfo:

Node 0, zone    DMA32
  pages free     304988
        min      7250
        low      9062
        high     10874
        spanned  1044480
        present  888973
        managed  872457
        protection: (0, 0, 4424, 4424, 4424)
...
Node 0, zone   Normal
  pages free     11977
        min      9611
        low      12013
        high     14415
        spanned  1173504
        present  1173504
        managed  1134236
        protection: (0, 0, 0, 0, 0)

Les "filigranes" actuelles sont min, low et high. Si un programme demande déjà une mémoire suffisante pour réduire free ci-dessous min, le programme entre "Récupération directe". Le programme est fait pour attendre pendant que le noyau libère la mémoire.

Nous voulons éviter la récupération directe si possible. Donc, si free va plonger sous le filigrane low watermark, le noyau se réveille kswapd. kswapd libère la mémoire en échangeant et en laissant tomber des caches, jusqu'à ce que free est supérieur à high à nouveau.


Qualification supplémentaire: kswapd _ fonctionnera également pour protéger le montant complet de LowMem_Reserve, pour le noyau LowMem et DMA _ Usage. La valeur par défaut lowmem_reserve est d'environ 1/256 du premier 4GIB de RAM (zone DMA32), il est donc généralement d'environ 16 MiB.

Le code Linux s'engage

mm: Échelle des filigranes Kswapd proportionnellement à la mémoire

[...]

watermark_scale_factor:

Ce facteur contrôle l'agressivité de KSWAPD. Il définit la quantité de mémoire laissée dans un nœud/système avant que kswapd ne soit réveillée et quelle quantité de mémoire doit être libre avant que Kswapd ne se rend au sommeil.

L'unité est en fractions de 10 000. La valeur par défaut de 10 signifie que les distances entre les filigranes sont de 0,1% de la mémoire disponible dans le nœud/système. La valeur maximale est de 1000, ou 10% de la mémoire.

Un taux élevé de threads entrant de la récupération directe (Allocstall) ou Kswapd allez dormir prématurément (kswapd_low_wmark_hit_quicly) peut indiquer que le nombre de pages libres KSWAPD maintient pour des raisons de latence est trop faible pour les rafales de répartition survenant dans le système. Ce bouton peut ensuite être utilisé pour régler l'agressivité kswapd en conséquence.

Proc: Meminfo: Estimez la mémoire disponible plus de manière conservatrice

L'élément MemAvailable in /proc/meminfo Est de donner aux utilisateurs une soupçon de la quantité de mémoire allouée sans causer d'échange, de sorte qu'il exclut les basses filigranes des zones indisponibles pour les utilisateurs.

Toutefois, pour une allocation d'utilisateurs, kswapd _ récupérera réellement que les pages libres touchent une combinaison de filigrane élevée et la protection LowMem de la page conserve une certaine quantité de mémoire DMA et DMA32 de utilisateurpace aussi.

Soustrayez le montant total que nous savons être indisponible pour les utilisateursPace du nombre de pages gratuites lors du calcul de la mémoire MEMPABLABLE.

Code linux

Il est parfois prétendu que la modification swappiness sur 0 Désactivera efficacement "l'échange opportuniste". Cela fournit une avenue intéressante d'enquête. S'il y a quelque chose appelé "échange opportuniste", et il peut être réglé par l'échange, nous pourrions ensuite la chasser en trouvant toutes les chaînes d'appels qui ont lu vm_swappiness. Notez que nous pouvons réduire notre espace de recherche en supposant que CONFIG_MEMCG N'est pas défini (c'est-à-dire "" Les cgroups de mémoire "sont désactivés). La chaîne d'appels va:

shrink_node_memcg Est commenté "Il s'agit d'une page de base Per-noode plus libre. Utilisé par Kswapd et Réclamation directe". C'est à dire. Cette fonction augmente le nombre de libre pages. Il n'essaie pas de faire dupliquer les pages à échanger afin qu'ils puissent être libérés beaucoup plus tard. Mais même si nous remonons que:

La chaîne ci-dessus est appelée à partir de trois fonctions différentes, indiquées ci-dessous. Comme prévu, nous pouvons diviser les sites d'appels en RECLAIM V.S.. kswapd. Il ne serait pas logique de réaliser un "échange opportuniste" en récupération directe.

  1. [.____]/* 
     * Ceci est le chemin de récupération directe, pour allouer des pages. Nous seulement [.____] * Essayez de récupérer les pages de zones qui satisferont l'allocation de l'appelant 
     * Demande.] * [.____] * Si une zone est réputée être épinglée Pages alors donnez-lui simplement une lumière 
     * Scannez puis abandonnez-le. [.____] */
     Void statique  rétrécit_zones  [.____]
  2. [.____] * Kswapd rétrécit un noeud de pages qui sont à ou inférieures à la plus haute utilisable 
     * Zone actuellement déséquilibrée. [.____] * [.____] * Retourne Vrai si kswapd scanné moins le nombre demandé de pages à [.____] * Récupérez ou si le manque de progrès était dû à des pages sous réveillon. [.____] * Ceci est utilisé pour déterminer si la priorité de numérisation doit être soulevée. 
     */
     statique bool  kswapd_shrink_node
  3. [.____] * Pour kswapd, Balance_PGDAT () récupérera les pages sur un nœud à partir de zones [.____] * qui sont éligibles à utiliser par l'appelant jusqu'à ce que au moins une zone soit 
     * [.____] * Retourne la commande KSWAPD fini de récupérer à l'adresse. [.____] * [.____] * Kswapd scanne les zones dans la direction HighMem-> normale-> DMA. Il ignore 
     * Zones qui ont free_pages> High_wmark_Pages (zone), mais une fois qu'une zone est [.____] * a été trouvée pour avoir free_pages <= high_wmark_pages (zone), toute page de cette zone [.____] * ou inférieur est admissible à la récupération jusqu'à ce que au moins une zone utilisable soit [.____] * * * équilibré. [.____] */[.____] statique int  balance_pgdat

Donc, probablement la revendication est que Kswapd est réveillé d'une manière ou d'une autre, même lorsque toutes les allocations de mémoire sont satisfaites immédiatement de la mémoire libre. J'ai examiné à travers les utilisations de wake_up_interruptible(&pgdat->kswapd_wait), et je ne vois aucune réveil comme celle-ci.

14
sourcejedi

Non, il n'y a pas d'échange opportuniste sous Linux. J'ai passé du temps à regarder le problème et à toutes les sources (manuels scolaires, courriels sur les listes de messagerie des développeurs de noyau, code source Linux et commentaires de commettre, ainsi que des échanges Twitter avec Mel Gorman) me disent la même chose: Linux seulement Récuce mémoire en réponse à une forme de pression de mémoire (avec l'exception évidente de l'hibernation).

Toutes les idées fausses populaires sur le sujet proviennent probablement du fait que Linux ne peut pas se permettre d'attendre le dernier octet de la mémoire libre avant de commencer à échanger. Il a besoin d'une sorte de coussin pour le protéger des formes extrêmes d'épuisement de la mémoire, et certains tunables peuvent affecter la taille de ce coussin (par ex. vm.min_free_kbytes). Mais ce n'est pas la même chose que "échanger parce qu'il n'y a rien de mieux à faire".

Malheureusement, l'algorithme de récupération de la page de page a augmenté beaucoup plus complexe par rapport à 2,6 (lorsqu'il a été décrit en détail dans le livre de Mel Gorman), mais l'idée de base est plus ou moins la même: la récupération de page est déclenchée par des allocations ayant échoué, que ce soit ensuite Réveillez-vous kswapd ou essayez de libérer des pages de manière synchrone (en fonction de la pression de la mémoire, des drapeaux d'affectation et d'autres facteurs).

La raison la plus évidente pour laquelle les allocations de page peuvent commencer à défaillir avec suffisamment de mémoire libre restante sont qu'ils peuvent demander une mémoire contiguë en réalité que la mémoire peut trop fragmentée pour satisfaire la demande. Historiquement, les développeurs de noyaux Linux ont fait de grandes longueurs pour éviter la nécessité d'allocations contiguës. Néanmoins, certains pilotes de périphériques nécessitent encore que - soit parce qu'ils ne peuvent pas faire mémoire multipage I/O (scatter-recueillir DMA), ou il pourrait simplement être bâclée par les développeurs de codage du pilote. L'avènement des énormes pages transparentes (THP) a fourni une autre raison d'attribuer la mémoire dans des morceaux physiquement contigus.

Le compactage de zone, qui a été introduit autour du même châssis, est censé aider au problème de la fragmentation de la mémoire, mais il ne produit pas toujours l'effet attendu.

Il existe diverses vmscan _ TracePoints qui peuvent aider à comprendre ce qui se passe exactement dans votre cas spécifique - il est toujours plus facile de trouver le contenu dont vous avez besoin dans le code de noyau Linux lorsque vous disposez de piles d'appels spécifiques, plutôt que de numériser tout pertinent à distance.

3
Nikolai