본문 바로가기

Programming/Linux_Kernel

ps u에 나오는 RSS 사이즈는 VSZ 사이즈까지 증가한다. (할 수 있다)|

원문 : http://elenoa.tistory.com/181

좋은 내용이군요.
이론으로는 알고 있는 내용이지만 이렇게 실재로 눈으로 보는것은 참 의미있다고 생각합니다.
헌데 여기서 나오는 rss 는 smaps 에 나오는 rss, pss 와 같은 의미일까요?




결과를 다 써놓고 정리하자니 벌쭘하지만.

VSZ와 RSS는 뭘까? man 페이지의 ps 항목에서 설명하는 두 파라미터의 설명은 다음과 같다.

VSZ
virtual memory size of the process in KiB (1024-byte units). Device mappings are currently excluded; this is subject to change. (alias vsize).

RSS
resident set size, the non-swapped physical memory that a task has used (in kiloBytes). (alias rssize, rsz).

아 뭐야. 몰라. 어려워.
간단히 말하자면 VSZ는 가상 메모리의 크기이고, 현재 디바이스 매핑에서는 제외되어 있다는 의미인 것 같다. RSS는 실제 메모리가 세팅된 크기이고, 스와핑이 되지 않은 물리적 메모리가 해당 task에 쓰이고 있는 양을 의미하는 것 같다.
그러니까 VSZ 크기만큼을 reserve 해놓고 실제로 물리적 메모리가 사용하고 있는 것은 RSS 크기만큼이라는 것인데.

Shared Memory에서 테스트, 닫기

간단한 테스트 프로그램을 만들어보자.

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h> /* for strerror */
#include <errno.h> /* for errno */
#include <sys/ipc.h> /* for shmat, shmget, shmdt, shmctl */
#include <sys/shm.h> /* for shmat, shmget, shmdt, shmctl */


#define SHMSIZE     (1024 * 1024 * 1024) /* 1G byte */
#define SHMKEY      0x10102020


int main(void)
{
    char *buf;
    int ret, i;

    ret = shmget(0x10102020, SHMSIZE, 0666|IPC_CREAT|IPC_EXCL);
    if (ret < 0) {
        fprintf(stderr, "shmget(%lx): %s\n", SHMKEY, strerror(errno));
        exit(-1);
    }
    buf = shmat(ret, NULL, 0);
    if (buf == (char *)-1) {
        fprintf(stderr, "shmat(%lx): %s\n", SHMKEY, strerror(errno));
        exit(-1);
    }

    /* memory I/O를 일으키는 for loop. 나중에 뺄거다. */
    for (i = 0; i < SHMSIZE; i++) {
        *(buf + i) = (i % 256);
    }

    system("ps u");
    shmdt(buf);
    shmctl(ret, IPC_RMID, NULL);

    return 0;
}



1메가의 공유메모리를 설정하고 각 byte마다 I/O를 일으킨 후에 ps 결과를 보고 자동으로 공유메모리를 정리한 후에 종료한다.
이 실행 결과는 다음과 같다.

# ./a.out
USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
root     31751 96.0 12.8 1052200 1048884 pts/18 S+  09:51   0:06 ./a.out
#

a.out의 VSZ 크기는 1052200b, RSS 크기는 1048884b. 거의 근접했다.
공유메모리를 할당하는 부분만 놓고 I/O를 일으키는 부분을 제외해보면,

#./a.out
USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
root     31908  0.0  0.0 1052196  304 pts/18   S+   10:08   0:00 ./a.out
#

애게. RSS는 304b 밖에 되지 않는다.
Shared Memory를 attach 해놓는다고 해서 다 물리 메모리에 올라가는 구조는 아닌듯 하다. 어딘가 reserve 해놓았다가 필요한 경우 RSS에 올려서 사용할 수 있도록 한다. 실제 물리 메모리에 매핑된 크기는 RSS에 기록된 크기와 같다.

Shared Memory에서 테스트, 닫기



그런데, 이것이 Shared Memory가 아니라 Local Memory라면?

Local Memory에서 테스트, 닫기

역시 또 간단한 테스트 프로그램을 만들어본다.

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h> /* for strerror */
#include <errno.h> /* for errno */


#define MEMSIZE     (1024 * 1024 * 1024) /* 1G byte */


int main(void)
{
    char *buf;
    int ret, i;

    buf = malloc(MEMSIZE);

    /* memory I/O를 일으키는 for loop. 나중에 뺄거다. */
    for (i = 0; i < MEMSIZE; i++) {
        *(buf + i) = (i % 256);
    }

    system("ps u");
    free(buf);

    return 0;
}



소스의 크기는 좀 더 작네. (당연하지. 공유메모리 관리 부분이 다 빠졌으니까.)

이 결과는?

# ./a.out
USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
root     32034 91.4 12.8 1052200 1048928 pts/18 S+  10:15   0:06 ./a.out
#

기대했던 대로 Shared Memory를 썼던 때와 별반 다를게 없다. 그런데, 여기서 I/O를 일으키는 부분을 제외한다면?

# ./a.out
USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
root     32018  0.0  0.0 1052204  356 pts/18   S+   10:13   0:00 ./a.out
#

기대와는 조금 다르네. 하지만 Shared Memory쪽과 거의 같은 결과다.

Local Memory에서 테스트, 닫기


malloc 혹은 Shared Memory를 attach 해서 확보해 놓은 메모리라고 해도, 실제 I/O를 일으키지 않으면 VSZ 영역에 예약만 되어 있을 뿐이다. 하지만 실제 I/O를 일으키게 되면 RSS 영역에 확보되게 되고, 이것은 실제로 물리적 메모리에 할당된다. (이 동작은 Local Memory와 Shared Memory가 완벽하게 동일하다.)

결론적으로 ps u 옵션에서 볼 수 있는 RSS는 실제 프로세스가 물리 메모리에서 점유하고 있는 메모리이며, VSZ까지 증가할 수 있다. 하지만 Shared Memory 등의 방식으로 각 프로세스는 메모리를 공유할 수 있기 때문에 RSS의 총 크기 합은 서버의 물리 메모리보다 클 수 있다. 프로세스가 동작하는 도중 별도의 메모리 할당 없이 RSS는 VSZ까지 증가할 수 있다. 이것은 정상적인 상황이다.

이 소스는 Linux Kernel 2.6.18 x86_64, Red Hat Enterprise Linux AS release 3에서 테스트 되었다.

이상.