
Ich beobachte das folgende Verhalten, das ich nicht erklären kann: Die Menge des von einem Server gemeldeten freien physischen Speichers nimmt zu, während der von den speicherhungrigsten Prozessen (Webserverprozessen) gemeldete „Res“-Speicher nahezu unverändert bleibt.
Was ich hauptsächlich verstehen möchte, ist: Wie ist es möglich, dass die physische Speichernutzung zunimmt, während der von den Prozessen gemeldete residente Speicher konstant ist? Was könnte innerhalb dieser Prozesse passieren, um dieses beobachtbare Verhalten zu verursachen, insbesondere ohne viel Last zu erzeugen?
Mit anderen Worten: Was kann innerhalb eines Prozesses passieren, sodass sich „Speicher“, der zuerst als „resident“ gemeldet wurde, aber tatsächlich keinen physischen Speicher belegte, so ändert, dass er zwar noch immer als „resident“ gemeldet wird, nun aber tatsächlich physischen Speicher belegt?
Beispiel: Ich habe einen virtuellen Server mit 2 GB Arbeitsspeicher. Gestern um 12:00 Uhr waren davon rund 800 MB (40%) belegt, wie top
/ free
[1] meldete. Der Großteil wird von wenigen Prozessen genutzt, die zusammen rund 1,2 GB belegten residenten Arbeitsspeicher meldeten[2].
Ich habe dann ein paar Tests gestartet (indem ich eine große Anzahl von HTTP-Anfragen ausgeführt habe, die von diesen Prozessen bedient wurden), was den physischen Speicherverbrauch auf 1,2 GB (60 %) und den von den Prozessen genutzten residenten Speicher auf 3,2 GB ansteigen ließ. Danach habe ich den Server überhaupt nicht mehr berührt und er ist nicht öffentlich verfügbar: Die Auslastung war danach < 0,03.
Obwohl der von den Prozessen gemeldete residente Speicher mit 3,2 GB unverändert blieb, stieg die physische Speichernutzung langsam an und überschritt irgendwann 90 % (1,8 GB), was zu Warnmeldungen führte. Innerhalb dieser Webserverprozesse passierte zu diesem Zeitpunkt nichts (wie die Auslastung zeigt) und es wurden keine speziellen Jobs ausgeführt.
Eine Grafik des obigen Szenarios finden SieHier. Das obere Diagramm zeigt genau das, was top
/ free
als freien physischen Speicher angibt. Das untere Diagramm zeigt genau das, was top
in der Spalte „Res“ angegeben ist. Beachten Sie, dass der markierte Bereich Ruby
insgesamt 6 Prozesse darstellt.
[1] Normalerweise ist auf diesen Servern der gesamte Speicher als „Benutzt“ markiert und der gesamte freie Speicher wird für Caches verwendet. Mit „benutzt“ meine ich: bis zum letzten Byte. Alle anderen Zahlen in top
und free
sind 0.
[2] Ich verstehe, dass die Summe des von mehreren Prozessen gemeldeten residenten Speichers den verwendeten physischen Speicher überschreiten kann, aber ich glaube nicht, dass ich weißalleüber die Möglichkeiten, wie dies geschehen kann.
Antwort1
Dies liegt daran, dass RSSnichtein maßgeblicher Wert, der Ihnen sagt, wie viel von diesem Speicher von diesem Programm verwendet wird. Es ist ein maßgeblicher Wert, der angibt, wie viel residenter Speicher von diesem Programm zugeordnet wird. Und es gibt einen Unterschied.
RSS kann bestenfalls als Hinweis darauf verwendet werden, wie viel Speicher Sie nutzen.
Der Kernel hat viele Tricks auf Lager, um Speicher zu sparen. Prozesse können viel Speicher gemeinsam nutzen, insbesondere Prozesse, die sich verzweigen.
Wenn Sie einen übergeordneten Prozess haben, der 100 MB Speicher zuweist und dann einen untergeordneten Prozess erzeugt, teilen sich beide Prozesse diesen Speicherbereich. Sowohl der übergeordnete als auch der untergeordnete Prozess geben an, einen RSS-Wert von >= 100 MB zu haben, da sie beide auf denselben Speicherbereich abgebildet werden. Technisch ist das richtig, der RSS-Wert für den übergeordneten Prozess ist >= 100 MB, da dies die Speichermenge ist, die der Prozess abgebildet hat.UndDer untergeordnete Prozess hat auch RSS >= 100M, weil dieser ProzessAuchhat so viel zugeordnet, es ist nur so, dass beide Prozesse (größtenteils) dieselben Zuordnungen teilen.
Sie können dies mit etwas einfachem Python demonstrieren.
#!/usr/bin/python
import os,sys,signal
HOG = 'A' * 104857600 ## 100 MB
try:
for i in range(100):
pid = os.fork()
if pid:
continue
else:
break
signal.pause()
except KeyboardInterrupt:
sys.exit(0)
Dieses Programm erstellt einen 100 MB großen Speicherbereich und füllt ihn mit 'A's. Anschließend erzeugt es 100 untergeordnete Prozesse (insgesamt 101 Prozesse) und wartet auf Strg+C.
Dies ist das vorherige Szenario.
$ top -bn1 -u matthew
top - 21:03:04 up 11 min, 1 user, load average: 0.04, 0.08, 0.09
Tasks: 212 total, 1 running, 211 sleeping, 0 stopped, 0 zombie
%Cpu(s): 0.7 us, 0.3 sy, 0.0 ni, 98.7 id, 0.2 wa, 0.0 hi, 0.0 si, 0.0 st
KiB Mem: 16124248 total, 1513728 used, 14610520 free, 78268 buffers
KiB Swap: 8069116 total, 0 used, 8069116 free, 578148 cached
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
1837 matthew 20 0 767916 5072 3400 S 0.0 0.0 0:00.06 gnome-keyr+
1880 matthew 20 0 13920 608 468 S 0.0 0.0 0:00.00 dbus-launch
1949 matthew 20 0 307180 2804 2312 S 0.0 0.0 0:00.01 gvfsd
2051 matthew 20 0 337684 2908 2436 S 0.0 0.0 0:00.00 at-spi-bus+
2059 matthew 20 0 127260 2920 2360 S 0.0 0.0 0:00.05 at-spi2-re+
2082 matthew 9 -11 486316 7044 4376 S 0.0 0.0 0:00.09 pulseaudio
2121 matthew 20 0 317660 2952 2324 S 0.0 0.0 0:00.00 gvfs-gphot+
2132 matthew 20 0 1440732 105732 30156 S 0.0 0.7 0:09.64 gnome-shell
2145 matthew 20 0 513076 3996 3064 S 0.0 0.0 0:00.00 gsd-printer
2160 matthew 20 0 313300 3488 2940 S 0.0 0.0 0:00.00 ibus-dconf
2172 matthew 20 0 775428 14000 10348 S 0.0 0.1 0:00.05 gnome-shel+
2182 matthew 20 0 319120 7120 5444 S 0.0 0.0 0:00.07 mission-co+
2196 matthew 20 0 232848 2708 2164 S 0.0 0.0 0:00.00 gvfsd-meta+
2206 matthew 20 0 408000 11828 8084 S 0.0 0.1 0:00.06 abrt-applet
2209 matthew 20 0 761072 15120 10680 S 0.0 0.1 0:00.13 nm-applet
2216 matthew 20 0 873088 14956 10600 S 0.0 0.1 0:00.09 evolution-+
2224 matthew 20 0 1357640 29248 14052 S 0.0 0.2 0:00.26 evolution-+
2403 matthew 20 0 295036 6680 3876 S 0.0 0.0 0:00.01 telepathy-+
2475 matthew 20 0 380916 2756 2264 S 0.0 0.0 0:00.00 gvfsd-burn
2486 matthew 20 0 8460 736 608 S 0.0 0.0 0:00.00 gnome-pty-+
2617 matthew 20 0 116412 3068 1596 S 0.0 0.0 0:00.04 bash
2888 matthew 20 0 457196 9868 5164 S 0.0 0.1 0:00.05 telepathy-+
3347 matthew 20 0 123648 1400 1020 R 0.0 0.0 0:00.00 top
Oben werden 14610520 KB freier Speicher angezeigt.
Lassen Sie uns unser Programm ausführen:
$ python trick_rss.py & top -bn1 -u matthew
[2] 3465
top - 21:04:54 up 13 min, 1 user, load average: 0.05, 0.07, 0.08
Tasks: 415 total, 1 running, 414 sleeping, 0 stopped, 0 zombie
%Cpu(s): 0.7 us, 0.3 sy, 0.0 ni, 98.8 id, 0.2 wa, 0.0 hi, 0.0 si, 0.0 st
KiB Mem: 16124248 total, 1832040 used, 14292208 free, 78320 buffers
KiB Swap: 8069116 total, 0 used, 8069116 free, 578144 cached
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
3465 matthew 20 0 227652 106676 1792 S 31.7 0.7 0:00.05 python
2483 matthew 20 0 641568 18736 11656 S 6.3 0.1 0:01.26 gnome-term+
1837 matthew 20 0 767916 5072 3400 S 0.0 0.0 0:00.06 gnome-keyr+
1880 matthew 20 0 13920 608 468 S 0.0 0.0 0:00.00 dbus-launch
1949 matthew 20 0 307180 2804 2312 S 0.0 0.0 0:00.01 gvfsd
2051 matthew 20 0 337684 2908 2436 S 0.0 0.0 0:00.00 at-spi-bus+
2059 matthew 20 0 127260 2920 2360 S 0.0 0.0 0:00.05 at-spi2-re+
2082 matthew 9 -11 486316 7044 4376 S 0.0 0.0 0:00.09 pulseaudio
2121 matthew 20 0 317660 2952 2324 S 0.0 0.0 0:00.00 gvfs-gphot+
2136 matthew 20 0 178692 2588 1788 S 0.0 0.0 0:00.00 dconf-serv+
2145 matthew 20 0 513076 3996 3064 S 0.0 0.0 0:00.00 gsd-printer
2160 matthew 20 0 313300 3488 2940 S 0.0 0.0 0:00.00 ibus-dconf
2172 matthew 20 0 775428 14000 10348 S 0.0 0.1 0:00.05 gnome-shel+
2182 matthew 20 0 319120 7120 5444 S 0.0 0.0 0:00.07 mission-co+
2196 matthew 20 0 232848 2708 2164 S 0.0 0.0 0:00.00 gvfsd-meta+
2206 matthew 20 0 408000 11828 8084 S 0.0 0.1 0:00.06 abrt-applet
2209 matthew 20 0 761072 15120 10680 S 0.0 0.1 0:00.14 nm-applet
2216 matthew 20 0 873088 14956 10600 S 0.0 0.1 0:00.10 evolution-+
2224 matthew 20 0 1357640 29248 14052 S 0.0 0.2 0:00.26 evolution-+
2403 matthew 20 0 295036 6680 3876 S 0.0 0.0 0:00.01 telepathy-+
2475 matthew 20 0 380916 2756 2264 S 0.0 0.0 0:00.00 gvfsd-burn
2487 matthew 20 0 116544 3316 1716 S 0.0 0.0 0:00.09 bash
2804 matthew 20 0 1239196 275576 41432 S 0.0 1.7 0:25.54 firefox
2890 matthew 20 0 436688 15932 7288 S 0.0 0.1 0:00.05 telepathy-+
3360 matthew 20 0 227652 106680 1792 S 0.0 0.7 0:00.05 python
3366 matthew 20 0 227652 105096 208 S 0.0 0.7 0:00.00 python
3368 matthew 20 0 227652 105096 208 S 0.0 0.7 0:00.00 python
3370 matthew 20 0 227652 105096 208 S 0.0 0.7 0:00.00 python
3372 matthew 20 0 227652 105096 208 S 0.0 0.7 0:00.00 python
3374 matthew 20 0 227652 105096 208 S 0.0 0.7 0:00.00 python
3376 matthew 20 0 227652 105096 208 S 0.0 0.7 0:00.00 python
3378 matthew 20 0 227652 105096 208 S 0.0 0.7 0:00.00 python
3380 matthew 20 0 227652 105096 208 S 0.0 0.7 0:00.00 python
3382 matthew 20 0 227652 105096 208 S 0.0 0.7 0:00.00 python
3384 matthew 20 0 227652 105096 208 S 0.0 0.7 0:00.00 python
3386 matthew 20 0 227652 105096 208 S 0.0 0.7 0:00.00 python
3388 matthew 20 0 227652 105096 208 S 0.0 0.7 0:00.00 python
3390 matthew 20 0 227652 105096 208 S 0.0 0.7 0:00.00 python
3392 matthew 20 0 227652 105096 208 S 0.0 0.7 0:00.00 python
3394 matthew 20 0 227652 105096 208 S 0.0 0.7 0:00.00 python
3396 matthew 20 0 227652 105096 208 S 0.0 0.7 0:00.00 python
3398 matthew 20 0 227652 105096 208 S 0.0 0.7 0:00.00 python
3400 matthew 20 0 227652 105096 208 S 0.0 0.7 0:00.00 python
3402 matthew 20 0 227652 105096 208 S 0.0 0.7 0:00.00 python
3404 matthew 20 0 227652 105096 208 S 0.0 0.7 0:00.00 python
3406 matthew 20 0 227652 105096 208 S 0.0 0.7 0:00.00 python
3408 matthew 20 0 227652 105096 208 S 0.0 0.7 0:00.00 python
3410 matthew 20 0 227652 105096 208 S 0.0 0.7 0:00.00 python
3412 matthew 20 0 227652 105096 208 S 0.0 0.7 0:00.00 python
3414 matthew 20 0 227652 105096 208 S 0.0 0.7 0:00.00 python
3416 matthew 20 0 227652 105096 208 S 0.0 0.7 0:00.00 python
3418 matthew 20 0 227652 105096 208 S 0.0 0.7 0:00.00 python
3420 matthew 20 0 227652 105096 208 S 0.0 0.7 0:00.00 python
3422 matthew 20 0 227652 105096 208 S 0.0 0.7 0:00.00 python
3424 matthew 20 0 227652 105096 208 S 0.0 0.7 0:00.00 python
3426 matthew 20 0 227652 105096 208 S 0.0 0.7 0:00.00 python
3428 matthew 20 0 227652 105096 208 S 0.0 0.7 0:00.00 python
3430 matthew 20 0 227652 105096 208 S 0.0 0.7 0:00.00 python
3432 matthew 20 0 227652 105096 208 S 0.0 0.7 0:00.00 python
3434 matthew 20 0 227652 105096 208 S 0.0 0.7 0:00.00 python
3436 matthew 20 0 227652 105096 208 S 0.0 0.7 0:00.00 python
3438 matthew 20 0 227652 105096 208 S 0.0 0.7 0:00.00 python
3440 matthew 20 0 227652 105096 208 S 0.0 0.7 0:00.00 python
3442 matthew 20 0 227652 105096 208 S 0.0 0.7 0:00.00 python
3444 matthew 20 0 227652 105096 208 S 0.0 0.7 0:00.00 python
3446 matthew 20 0 227652 105096 208 S 0.0 0.7 0:00.00 python
3448 matthew 20 0 227652 105096 208 S 0.0 0.7 0:00.00 python
3450 matthew 20 0 227652 105096 208 S 0.0 0.7 0:00.00 python
3452 matthew 20 0 227652 105096 208 S 0.0 0.7 0:00.00 python
3454 matthew 20 0 227652 105096 208 S 0.0 0.7 0:00.00 python
3456 matthew 20 0 227652 105096 208 S 0.0 0.7 0:00.00 python
3458 matthew 20 0 227652 105096 208 S 0.0 0.7 0:00.00 python
3460 matthew 20 0 227652 105096 208 S 0.0 0.7 0:00.00 python
3462 matthew 20 0 227652 105096 208 S 0.0 0.7 0:00.00 python
3464 matthew 20 0 227652 105096 208 S 0.0 0.7 0:00.00 python
3467 matthew 20 0 227652 105092 208 S 0.0 0.7 0:00.00 python
3469 matthew 20 0 227652 105092 208 S 0.0 0.7 0:00.00 python
3471 matthew 20 0 227652 105092 208 S 0.0 0.7 0:00.00 python
3473 matthew 20 0 227652 105092 208 S 0.0 0.7 0:00.00 python
3475 matthew 20 0 227652 105092 208 S 0.0 0.7 0:00.00 python
3477 matthew 20 0 227652 105092 208 S 0.0 0.7 0:00.00 python
3479 matthew 20 0 227652 105092 208 S 0.0 0.7 0:00.00 python
3481 matthew 20 0 227652 105092 208 S 0.0 0.7 0:00.00 python
3483 matthew 20 0 227652 105092 208 S 0.0 0.7 0:00.00 python
3485 matthew 20 0 227652 105092 208 S 0.0 0.7 0:00.00 python
3487 matthew 20 0 227652 105092 208 S 0.0 0.7 0:00.00 python
3489 matthew 20 0 227652 105092 208 S 0.0 0.7 0:00.00 python
3491 matthew 20 0 227652 105092 208 S 0.0 0.7 0:00.00 python
3493 matthew 20 0 227652 105092 208 S 0.0 0.7 0:00.00 python
3495 matthew 20 0 227652 105092 208 S 0.0 0.7 0:00.00 python
3497 matthew 20 0 227652 105092 208 S 0.0 0.7 0:00.00 python
3499 matthew 20 0 227652 105092 208 S 0.0 0.7 0:00.00 python
3501 matthew 20 0 227652 105092 208 S 0.0 0.7 0:00.00 python
3503 matthew 20 0 227652 105092 208 S 0.0 0.7 0:00.00 python
3505 matthew 20 0 227652 105092 208 S 0.0 0.7 0:00.00 python
3507 matthew 20 0 227652 105092 208 S 0.0 0.7 0:00.00 python
3509 matthew 20 0 227652 105092 208 S 0.0 0.7 0:00.00 python
3511 matthew 20 0 227652 105092 208 S 0.0 0.7 0:00.00 python
3513 matthew 20 0 227652 105092 208 S 0.0 0.7 0:00.00 python
3515 matthew 20 0 227652 105092 208 S 0.0 0.7 0:00.00 python
3517 matthew 20 0 227652 105092 208 S 0.0 0.7 0:00.00 python
3519 matthew 20 0 227652 105092 208 S 0.0 0.7 0:00.00 python
3521 matthew 20 0 227652 105092 208 S 0.0 0.7 0:00.00 python
3523 matthew 20 0 227652 105092 208 S 0.0 0.7 0:00.00 python
3525 matthew 20 0 227652 105092 208 S 0.0 0.7 0:00.00 python
3527 matthew 20 0 227652 105092 208 S 0.0 0.7 0:00.00 python
3529 matthew 20 0 227652 105092 208 S 0.0 0.7 0:00.00 python
3531 matthew 20 0 227652 105092 208 S 0.0 0.7 0:00.00 python
3533 matthew 20 0 227652 105092 208 S 0.0 0.7 0:00.00 python
3535 matthew 20 0 227652 105092 208 S 0.0 0.7 0:00.00 python
3537 matthew 20 0 227652 105092 208 S 0.0 0.7 0:00.00 python
3539 matthew 20 0 227652 105092 208 S 0.0 0.7 0:00.00 python
3541 matthew 20 0 227652 105092 208 S 0.0 0.7 0:00.00 python
3543 matthew 20 0 227652 105092 208 S 0.0 0.7 0:00.00 python
3545 matthew 20 0 227652 105092 208 S 0.0 0.7 0:00.00 python
3547 matthew 20 0 227652 105092 208 S 0.0 0.7 0:00.00 python
3549 matthew 20 0 227652 105092 208 S 0.0 0.7 0:00.00 python
3551 matthew 20 0 227652 105092 208 S 0.0 0.7 0:00.00 python
3553 matthew 20 0 227652 105092 208 S 0.0 0.7 0:00.00 python
3555 matthew 20 0 227652 105092 208 S 0.0 0.7 0:00.00 python
3557 matthew 20 0 227652 105092 208 S 0.0 0.7 0:00.00 python
3559 matthew 20 0 227652 105092 208 S 0.0 0.7 0:00.00 python
3561 matthew 20 0 227652 105092 208 S 0.0 0.7 0:00.00 python
3563 matthew 20 0 227652 105092 208 S 0.0 0.7 0:00.00 python
3565 matthew 20 0 227652 105092 208 S 0.0 0.7 0:00.00 python
Ich habe 14292208 KB frei. Etwa 300 MB Speicher sind verbraucht. Aber wenn ich mich nach den RSS-Feeds richte, habe ich tatsächlich 10 GB Speicher verbraucht!
Wenn Sie sich schließlich die Prozesszuordnungen ansehen, können Sie erkennen, dass die Adressen des virtuellen Speichers untereinander identisch sind.
$ pmap -x 3561
...
00007f05da5e8000 102404 102404 102404 rw--- [ anon ]
...
$ pmap -x 3565
...
00007f05da5e8000 102404 102404 102404 rw--- [ anon ]
...
Faules Kopieren
Dieses C-Programm demonstriert Lazy Copying. In diesem Szenario werden alle Prozesse auf denselben Speicherbereich abgebildet, aber die untergeordneten Prozesse haben den Inhalt überschrieben. Im Hintergrund hat der Kernel diese Seiten an verschiedene Stellen im realen Speicher neu abgebildet, zeigen aber denselben virtuellen Adressraum.
Nun beansprucht jede Instanz tatsächlich Speicher, der RSS-Wert bleibt jedoch konstant.
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <string.h>
int main() {
int i;
char c=65;
pid_t pid;
signal(SIGCHLD, SIG_IGN);
/* Allocate some memory */
char *hog = malloc(104857600);
memset(hog, c, 104857600);
for (i=1; i < 4; i++) {
if (fork())
continue;
memset(hog, c+i, 104857600);
break;
}
sleep(3);
printf("Pid %d shows HOG[1048576] saying %c\n", getpid(), hog[1048576]);
pause();
}
Kompilieren mit gcc -o trick_rss trick_rss.c
. Und ausführen mit free -m; ./trick_rss & sleep 5; free -m
.
Sie erhalten das folgende Ergebnis;
$ free -m; ./trick_rss & sleep 5; free -m
total used free shared buffers cached
Mem: 15746 2477 13268 0 79 589
-/+ buffers/cache: 1808 13938
Swap: 7879 0 7879
[3] 4422
Pid 4422 shows HOG[1048576] saying A
Pid 4424 shows HOG[1048576] saying B
Pid 4425 shows HOG[1048576] saying C
Pid 4426 shows HOG[1048576] saying D
total used free shared buffers cached
Mem: 15746 2878 12867 0 79 589
-/+ buffers/cache: 2209 13536
Swap: 7879 0 7879
Antwort2
Die Menge des verwendeten physischen Speichers könnte zunehmen, wenn die Menge des von den Ruby-Prozessen (oder anderen) gemeinsam genutzten Speichers abnimmt. In Ihrem Fall ist das System jedoch im Leerlauf, sodass Sie keine Änderungen erwarten würden. Möglicherweise führt der Ruby-Garbage Collector dazu, dass die gemeinsame Nutzung abnimmt, wie dieses Zitat aushttp://www.rubyenterpriseedition.com/faq.htmlsagt:
Ein Garbage-Collection-Zyklus führt daher dazu, dass alle Objekte beschrieben werden (oder im Betriebssystemjargon: die Speicherseiten der Objekte werden verschmutzt). Das Betriebssystem kopiert den gesamten Speicher und hebt so den Effekt von Copy-on-Write auf.
Wie sieht die Menge des gemeinsam genutzten Speichers in diesem Zeitraum aus?