
설명할 수 없는 다음과 같은 동작이 관찰됩니다. 서버에서 보고하는 사용 가능한 물리적 메모리의 양은 증가하는 반면, 메모리를 가장 많이 사용하는 프로세스(웹 서버 프로세스)에서 보고하는 'Res' 메모리는 거의 균일합니다.
내가 주로 이해하고 싶은 것은 프로세스에 의해 보고된 상주 메모리가 일정한 동안 물리적 메모리 사용이 증가하는 것이 어떻게 가능하다는 것입니다. 특히 많은 로드를 생성하지 않고 관찰 가능한 동작을 유발하기 위해 이러한 프로세스 내부에서 무슨 일이 일어날 수 있습니까?
즉, 처음에는 '상주'로 보고되었지만 실제로 물리적 메모리를 점유하지 않은 '메모리'가 여전히 '상주'로 보고되지만 지금은 변경되는 것과 같은 프로세스 내에서 일어날 수 있는 일입니다. 실제로 물리적 메모리도 차지합니까?
예: 메모리가 2GB인 가상 서버가 있습니다. top
/ free
[1] 에서 보고한 바와 같이 어제 12시에는 약 800MB(40%)가 사용되었습니다 . 대부분은 몇 가지 프로세스에서 사용되며, 총 1.2GB의 상주 메모리가 사용된 것으로 보고되었습니다[2].
그런 다음 몇 가지 테스트(이 프로세스에서 제공하는 대량의 HTTP 요청 수행)를 시작하여 실제 메모리 사용량을 1.2GB(60%)로 늘리고 프로세스에서 사용하는 상주 메모리를 3.2GB로 늘렸습니다. 그 후에는 서버를 전혀 건드리지 않았으며 공개적으로 사용할 수 없습니다. 이후 로드는 0.03 미만이었습니다.
그럼에도 불구하고, 프로세스에 의해 보고된 상주 메모리는 3.2GB로 균일했지만, 물리적 메모리 사용량은 서서히 증가하여 어느 시점에서 90%(1.8GB)를 초과하여 플래그가 발생했습니다. 이러한 웹 서버 프로세스 내에서는 그 당시 아무 일도 일어나지 않았으며(부하로 입증됨) 실행 중인 특별한 작업도 없습니다.
위의 시나리오 그래프를 볼 수 있습니다여기. 위쪽 그래프가 보여주는 것은 정확히 top
/ free
사용 가능한 물리적 메모리로 보고되는 것입니다. 아래쪽 그래프에 표시되는 내용은 정확히 top
'Res' 열에 보고된 내용입니다. 표시된 영역은 Ruby
총 6개의 프로세스입니다.
[1] 일반적으로 이러한 서버에서는 모든 메모리가 '사용됨'으로 표시되고 모든 여유 메모리는 캐시에 사용됩니다. 내 말은 마지막 바이트까지라는 뜻입니다. top
및 안의 다른 모든 숫자 free
는 0입니다.
[2] 여러 프로세스에서 보고된 상주 메모리의 합이 사용된 물리적 메모리를 초과할 수 있다는 것을 알고 있지만, 모르는 것 같습니다.모두이런 일이 일어날 수 있는 방법 중.
답변1
RSS가 있기 때문에 이런 일이 발생합니다~ 아니다해당 프로그램에서 사용되는 메모리의 양을 알려주는 신뢰할 수 있는 값입니다. 해당 프로그램이 얼마나 많은 상주 메모리를 매핑하는지에 대한 권위 있는 값입니다. 그리고 차이점이 있습니다.
RSS는 기껏해야 사용 중인 메모리 양에 대한 힌트로만 사용할 수 있습니다.
커널에는 메모리를 절약하기 위한 많은 트릭이 있습니다. 프로세스는 많은 메모리를 공유할 수 있으며, 특히 분기되는 프로세스는 더욱 그렇습니다.
100M의 메모리를 할당하는 부모가 있고 자식을 생성하는 경우 두 프로세스 모두 해당 메모리 영역을 공유합니다. 부모와 자식 모두 RSS 값이 100M 이상이라고 주장합니다. 동일한 메모리 영역. 기술적으로 이것은 정확합니다. 상위 프로세스의 RSS는 프로세스가 매핑한 메모리 양이므로 100M 이상입니다.그리고하위 프로세스에도 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)
이 프로그램은 100M 메모리 영역을 생성하고 이를 'A'로 채웁니다. 그런 다음 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
상단에는 14610520KB의 여유 메모리가 표시됩니다.
프로그램을 실행해 보겠습니다.
$ 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
14292208KB의 여유 공간이 있습니다. 약 300M의 메모리가 사용되었습니다. 그러나 RSS가 나에게 말하는 대로 가면 실제로 10GB의 메모리를 사용한 것입니다!
마지막으로 프로세스 매핑을 살펴보면 가상 메모리 주소가 서로 동일한 것을 확인할 수 있습니다.
$ 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말한다:
따라서 가비지 수집 주기로 인해 모든 개체가 기록됩니다(또는 운영 체제 전문 용어로 개체의 메모리 페이지가 더러워집니다). OS는 해당 메모리를 모두 복사하므로 쓰기 중 복사 효과가 무효화됩니다.
이 기간 동안 공유된 메모리 양은 어떻게 되나요?