Lorsque mon système Linux se rapproche de la pagination (c'est-à-dire, dans mon cas, 16 Go de RAM presque plein, 16 Go de swap complètement vide) si un nouveau processus X essaie d'allouer de la mémoire, le système se verrouille complètement. Autrement dit, jusqu'à ce qu'un nombre disproportionné de pages (par rapport à la taille totale et au taux des demandes d'allocation de mémoire de X) aient été échangées. Notez que non seulement l'interface graphique ne répond plus complètement, mais même les services de base comme sshd sont complètement bloqués.
Ce sont deux morceaux de code (certes grossiers) que j'utilise pour déclencher ce comportement de manière plus "scientifique". Le premier obtient deux nombres x, y à partir de la ligne de commande et continue d'allouer et d'initialiser plusieurs morceaux de y octets jusqu'à ce que plus de x octets totaux aient été alloués. Et puis il dort juste indéfiniment. Cela sera utilisé pour amener le système au bord de la pagination.
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
int main(int argc, char** argv) {
long int max = -1;
int mb = 0;
long int size = 0;
long int total = 0;
char* buffer;
if(argc > 1)
{
max = atol(argv[1]);
size = atol(argv[2]);
}
printf("Max: %lu bytes\n", max);
while((buffer=malloc(size)) != NULL && total < max) {
memset(buffer, 0, size);
mb++;
total=mb*size;
printf("Allocated %lu bytes\n", total);
}
sleep(3000000);
return 0;
}
Le deuxième morceau de code fait exactement ce que le premier fait, sauf qu'il a un sleep(1);
droit après le printf
(je ne vais pas répéter tout le code). Celui-ci sera utilisé lorsque le système est sur le point de paginer pour le faire échanger des pages d'une manière "douce", c'est-à-dire en demandant lentement l'allocation de nouveaux morceaux de mémoire (de sorte que le système devrait certainement être en mesure d'échanger des pages et suivre les nouvelles demandes).
Donc, avec les deux morceaux de code compilés, appelons les exes respectifs fasteater et sloweater, faisons ceci:
1) Commencez votre interface graphique préférée (pas strictement nécessaire bien sûr)
2) démarrer un compteur mem / swap (par exemple watch -n 1 free
)
3) démarrer plusieurs instances fasteater x y
où x est de l'ordre des gigaoctets et y est de l'ordre des mégaoctets. Faites-le jusqu'à ce que vous remplissiez presque le bélier.
4) démarrer une instance de sloweater x y
, où x est de l'ordre des gigaoctets et y est de l'ordre des mégaoctets.
Après l'étape 4), ce qui devrait arriver (et cela arrive toujours pour mon système), c'est que juste après avoir épuisé le vérin, le système se verrouille complètement. gui est verrouillé sshd est verrouillé etc. MAIS, pas pour toujours! Une fois que le ralentisseur a terminé ses demandes d'allocation, le système reprendra vie (après des minutes de verrouillage, pas des secondes ...) avec cette situation:
a) le bélier est à peu près plein
b) le swap est aussi à peu près plein (rappelez-vous, il était vide au début)
c) aucune intervention de tueur.
Et notez que la partition de swap se trouve sur un SSD. Ainsi, le système semble incapable de déplacer progressivement les pages du bélier vers le swap (vraisemblablement des fasteaters qui ne font que dormir) pour faire de la place aux demandes lentes (et de quelques mégaoctets seulement) du sloweater.
Maintenant, quelqu'un me corrige si je me trompe, mais cela ne semble pas la façon dont un système moderne devrait se comporter dans ce contexte. Il semble se comporter comme les anciens systèmes (waaaaay back) quand il n'y avait pas de support pour la pagination et le système de mémoire virtuelle a juste échangé tout l'espace mémoire d'un processus au lieu de quelques pages.
Quelqu'un peut-il tester cela aussi? Et peut-être quelqu'un qui a également un système BSD.
MISE À JOUR 1
J'ai suivi les conseils de Mark Plotnick ci-dessous dans les commentaires et j'ai commencé vmstat 1 >out
avant de procéder au test de radiomessagerie. Vous pouvez voir le résultat ci-dessous (j'ai coupé toute la partie initiale où le bélier est rempli sans implication de swap):
procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
r b swpd free buff cache si so bi bo in cs us sy id wa st
0 0 6144 160792 8 272868 0 0 0 0 281 1839 1 0 99 0 0
0 0 6144 177844 8 246096 0 0 0 0 425 2300 1 1 99 0 0
0 0 6144 168528 8 246112 0 0 16 0 293 1939 1 0 99 0 0
0 0 6144 158320 8 246116 0 0 0 0 261 1245 0 0 100 0 0
2 0 10752 161624 8 229024 0 4820 17148 4820 845 3656 1 2 97 0 0
2 0 10752 157300 8 228096 0 0 88348 0 2114 8902 0 5 94 1 0
0 0 10752 176108 8 200052 0 0 108312 0 2466 9772 1 5 91 3 0
0 0 10752 170040 8 196780 0 0 17380 0 507 1895 0 1 99 0 0
0 10 10752 160436 8 191244 0 0 346872 20 4184 17274 1 9 64 26 0
0 29 12033856 152888 8 116696 5992 15916880 1074132 15925816 819374 2473643 0 94 0 6 0
3 21 12031552 295644 8 136536 1188 0 11348 0 1362 3913 0 1 10 89 0
0 11 12030528 394072 8 151000 2016 0 17304 0 907 2867 0 1 13 86 0
0 11 12030016 485252 8 158528 708 0 7472 0 566 1680 0 1 23 77 0
0 11 12029248 605820 8 159608 900 0 2024 0 371 1289 0 0 31 69 0
0 11 12028992 725344 8 160472 1076 0 1204 0 387 1381 0 1 33 66 0
0 12 12028480 842276 8 162056 724 0 3112 0 357 1142 0 1 38 61 0
0 13 12027968 937828 8 162652 776 0 1312 0 363 1191 0 1 31 68 0
0 9 12027456 1085672 8 163260 656 0 1520 0 439 1497 0 0 30 69 0
0 10 12027200 1207624 8 163684 728 0 992 0 411 1268 0 0 42 58 0
0 9 12026688 1331492 8 164740 600 0 1732 0 392 1203 0 0 36 64 0
0 9 12026432 1458312 8 166020 628 0 1644 0 366 1176 0 0 33 66 0
Comme vous pouvez le voir, dès que le swap est impliqué, il y a un swapout massif de 15916880 Kbytes à la fois qui, je suppose, dure pendant toute la durée du gel du système. Et tout cela est apparemment causé par un processus (le sloweater) qui ne demande que 10 Mo par seconde.
MISE À JOUR 2: J'ai fait une installation rapide de FreeBSD et j'ai répété le même schéma d'allocation utilisé avec Linux ... et c'était aussi fluide qu'il devrait l'être. FreeBSD a échangé les pages progressivement tandis que le sloweater a alloué tous ses morceaux de mémoire de 10 Mo. Pas un accroc du tout ... WTF se passe ici?!
MISE À JOUR 3: J'ai déposé un bug avec le bugtracker du noyau. Il semble attirer l'attention, alors ... croise les doigts ...
la source
vmstat 1>somefile
directement à partir du système et voir ce qu'il signale une fois que le système est revenu à la vie. Je vais essayer ça.swappiness
est le 60 par défaut (pas que le changer donne un meilleur résultat). Le noyau utilisé avec lavmstat
course est 4.14.35 mais j'ai essayé 4.15, 4.16 et je suis même revenu à la série 4.0 (!): Toujours le même comportement. Et ce n'est pas que j'utilise une distribution bizarre, c'est juste Debian. Je n'utilise pas les images du noyau de Debian (pas que les miennes aient des configurations inhabituelles) mais j'ai essayé l'une de ces ... même comportement.Réponses:
C'est exactement pour cela que la protection anti-thrash existe.
Il surveille constamment l'état de permutation et, lorsque quelque chose commence accidentellement à occuper beaucoup de RAM, gèle temporairement les processus gourmands en RAM, de sorte que le noyau a le temps de permuter de la mémoire sans que le système entier ne réponde pas.
la source
Vous allouez uniquement de la mémoire - vous n'y mettez rien. Un programme "normal" allouerait un morceau puis commencerait à l'utiliser. L'allocation n'est pas la même chose que l'utilisation de la mémoire.
la source