Как может уменьшаться свободная физическая память, если объем памяти Res, используемый процессами, остается постоянным?

Как может уменьшаться свободная физическая память, если объем памяти Res, используемый процессами, остается постоянным?

Я наблюдаю следующее поведение, которое не могу объяснить: объем свободной физической памяти, сообщаемый сервером, увеличивается, в то время как объем памяти «Res», сообщаемый наиболее требовательными к памяти процессами (процессами веб-сервера), практически равен нулю.

Что я в основном хочу понять: как возможно, чтобы использование физической памяти увеличивалось, в то время как резидентная память, сообщаемая процессами, остается постоянной. Что может происходить внутри этих процессов, чтобы вызвать это наблюдаемое поведение, особенно без создания большой нагрузки?

Другими словами: что может произойти внутри процесса, так что «память», которая сначала была указана как «резидентная», но на самом деле не занимала никакой физической памяти, изменится таким образом, что она по-прежнему указывается как «резидентная», но теперь также фактически занимает физическую память?

Пример: У меня есть виртуальный сервер с 2 ГБ памяти. Вчера в 12:00 было использовано около 800 МБ (40%), как сообщает top/ free[1]. Большая часть используется несколькими процессами, которые вместе сообщили об использовании около 1,2 ГБ резидентной памяти[2].

Затем я запустил несколько тестов (выполняя большие объемы HTTP-запросов, обслуживаемых этими процессами), что увеличило использование физической памяти до 1,2 ГБ (60%) и увеличило резидентную память, используемую процессами, до 3,2 ГБ. После этого я вообще не трогал сервер, и он не является общедоступным: после этого нагрузка была < 0,03.

Тем не менее, в то время как резидентная память, сообщаемая процессами, была на уровне 3,2 ГБ, использование физической памяти медленно увеличивалось и в какой-то момент превысило 90% (1,8 ГБ), что привело к поднятию флагов. В этих процессах веб-сервера в это время ничего не происходило (о чем свидетельствует нагрузка), и не выполнялось никаких специальных заданий.

График сценария выше можно увидетьздесь. Верхний график показывает именно то, что top/ freeсообщает как свободную физическую память. Нижний график показывает именно то, что topсообщает в столбце «Res». Обратите внимание, что отмеченная область Rubyпредставляет собой сумму 6 процессов.

[1] Обычно на этих серверах вся память помечена как «Используется», а вся свободная память используется для кэшей. Под всем я подразумеваю: до последнего байта. Все остальные числа в topи freeравны 0.

[2] Я понимаю, что сумма резидентной памяти, сообщаемая несколькими процессами, может превышать используемую физическую память, но я не думаю, что я знаю наверняка.всео том, какими способами это может произойти.

решение1

Это происходит потому, что RSSнетавторитетное значение, которое сообщает вам, сколько памяти используется этой программой. Это авторитетное значение того, сколько резидентной памяти отображается этой программой. И есть разница.

RSS в лучшем случае можно использовать только как подсказку о том, сколько памяти вы используете.

У ядра есть много трюков в рукаве для экономии памяти. Процессы могут совместно использовать много памяти, особенно процессы, которые разветвляются.

Если у вас есть родительский процесс, который выделяет 100 Мб памяти, а затем порождает дочерний процесс, оба этих процесса будут совместно использовать эту область памяти, и родительский, и дочерний процессы будут утверждать, что имеют значение RSS >= 100 Мб, потому что они оба отображаются в одну и ту же область памяти. Технически это правильно, RSS для родительского процесса >= 100 Мб, поскольку это объем памяти, отображенный процессом,идочерний процесс также имеет RSS >= 100M, потому что этот процесстакжетак много отображено, просто так получилось, что оба процесса используют (в основном) одни и те же отображения.

Вы можете продемонстрировать это с помощью простого кода на Python.

#!/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)

Эта программа создает область памяти размером 100 МБ и заполняет ее символами «А». Затем она порождает 100 дочерних процессов (всего 101 процесс), а затем ждет нажатия клавиш ctrl-c.

Это предыдущий сценарий.

$ 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

Сверху показано 14610520 КБ свободной памяти.

Запустим нашу программу:

$ 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

У меня свободно 14292208 Кб. Около 300 Мб памяти было использовано. Но, если верить RSS, я на самом деле использовал 10 ГБ памяти!

Наконец, если вы посмотрите на сопоставления процессов, то увидите, что адреса виртуальной памяти совпадают друг с другом.

$ pmap -x 3561
...
00007f05da5e8000  102404  102404  102404 rw---   [ anon ]
...

$ pmap -x 3565
...
00007f05da5e8000  102404  102404  102404 rw---   [ anon ]
...

Ленивое копирование

Эта программа на языке C демонстрирует ленивое копирование, в этом сценарии все процессы отображаются в одну и ту же область памяти, но потомки перезаписали содержимое. В фоновом режиме ядро ​​переназначило эти страницы в разные места в реальной памяти, но показало одно и то же виртуальное адресное пространство.

Теперь каждый экземпляр фактически занимает память, но значение RSS остается постоянным.

#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();
}

Скомпилируйте с помощью gcc -o trick_rss trick_rss.c. И запустите с помощью free -m; ./trick_rss & sleep 5; free -m.

Вы получаете следующий результат;

$ 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

решение2

Объем используемой физической памяти может расти по мере уменьшения объема памяти, разделяемой между процессами ruby ​​(или другими). ​​В вашем случае, однако, система простаивает, поэтому вы не ожидаете никаких изменений. Возможно, сборщик мусора ruby ​​вызывает уменьшение совместного использования, как эта цитата изhttp://www.rubyenterpriseedition.com/faq.htmlговорит:

Таким образом, цикл сборки мусора приведет к тому, что все объекты будут записаны (или, на жаргоне операционных систем: страницы памяти объектов будут засорены). ОС скопирует всю эту память, тем самым сведя на нет эффект копирования при записи.

Каков объем совместно используемой памяти за этот период времени?

Связанный контент