`ru_maxrss`가 예상보다 더 많은 사용량을 반환하는 이유

`ru_maxrss`가 예상보다 더 많은 사용량을 반환하는 이유

프로그램 실행기를 테스트 중입니다. GNU 시간 1.9를 사용하여 아래 코드를 테스트할 때

// nul.c
#include <stdio.h>
#include <sys/resource.h>

int main()
{
  struct rusage r_usage;
  getrusage(RUSAGE_SELF, &r_usage);
  printf("%ld\n", sizeof r_usage);
  printf("%ld\n", r_usage.ru_maxrss);
  return 0;
}

컴파일용

gcc nul.c -o nul

그리고 달리다

/usr/bin/time -v ./nul

, 보고

144
576
    Command being timed: "./nul"
    User time (seconds): 0.00
    System time (seconds): 0.00
    Percent of CPU this job got: 0%
    Elapsed (wall clock) time (h:mm:ss or m:ss): 0:00.00
    Average shared text size (kbytes): 0
    Average unshared data size (kbytes): 0
    Average stack size (kbytes): 0
    Average total size (kbytes): 0
    Maximum resident set size (kbytes): 1424
    Average resident set size (kbytes): 0
    Major (requiring I/O) page faults: 0
    Minor (reclaiming a frame) page faults: 61
    Voluntary context switches: 1
    Involuntary context switches: 4
    Swaps: 0
    File system inputs: 0
    File system outputs: 0
    Socket messages sent: 0
    Socket messages received: 0
    Signals delivered: 0
    Page size (bytes): 4096
    Exit status: 0

최대 상주 세트 크기가 프로그램의 출력을 만족시키지 않습니다. 추가 테스트 후에 maxrssGNU 시간에 보고된 크기는 항상 약 1400kB입니다. 그리고 아래 코드를 테스트해보세요

// nul2.c
int main(){ return 0; }

컴파일용

gcc nul2.c -o nul2

그리고 달리다

/usr/bin/time -v ./nul2

GNU 시간은 ~1000kB maxrss사용량을 보고합니다. 그러나 내 프로그램에서는 메모리 공간이 사용되지 않습니다. 그렇다면 maxrss사용량이 ~0kB가 아닌 이유는 무엇이며 프로그램에서 사용되는 실제 메모리를 측정하는 방법은 무엇입니까?


고쳐 쓰다:

나는 빈 어셈블리 프로그램을 작성했습니다.

.text
.global _start
_start:
    movl $0, %ebx
    movl $1, %eax
    int  $0x80

다음으로 컴파일

as -o nul.o nul.s
ld -s -o nul nul.o

GNU 시간으로 테스트했습니다.

    Command being timed: "./nul"
    User time (seconds): 0.00
    System time (seconds): 0.00
    Percent of CPU this job got: 61%
    Elapsed (wall clock) time (h:mm:ss or m:ss): 0:00.00
    Average shared text size (kbytes): 0
    Average unshared data size (kbytes): 0
    Average stack size (kbytes): 0
    Average total size (kbytes): 0
    Maximum resident set size (kbytes): 128
    Average resident set size (kbytes): 0
    Major (requiring I/O) page faults: 0
    Minor (reclaiming a frame) page faults: 13
    Voluntary context switches: 1
    Involuntary context switches: 0
    Swaps: 0
    File system inputs: 0
    File system outputs: 0
    Socket messages sent: 0
    Socket messages received: 0
    Signals delivered: 0
    Page size (bytes): 4096
    Exit status: 0

또한 최대 RSS 사용량은 128kB입니다. 그것은 어디에서 왔습니까?

답변1

당신의 전화번호는 여기 내 전화번호와 비슷합니다.

귀하의 프로그램이 라이브러리를 사용한다는 것을 잊지 마십시오. (예를 들어, 함수는 printf프로그램의 일부입니다. 함수의 버퍼는 프로그램이 시작될 때나 그 이후에 또는 둘 다에 할당됩니다. 코드가 메모리에 로드되면 코드도 RSS로 계산됩니다.) 수량이 0이고 프로세스가 완료되기 전에 수량이 증가한다는 사실.

(명령어나 디버거를 읽어서) 프로세스 실행을 중지하는 경우 /proc/<pid>/...느린 프로그램 등을 사용하여 lsof해당 메모리를 검사 할 수 있습니다.

특히, 프로그램은 /usr/lib/x86_64-linux-gnu/libc.so.6하드 드라이브에서 2.2MB(또는 이와 유사한)를 사용하고 있습니다(모든 항목을 로드할 필요는 없음).


어쩌면 그게 다야

/usr/bin/time -v ./nul2 "$(seq -w 1 16000)"

명령줄도 프로세스 메모리의 일부가 되므로 보고된 숫자는 약간 더 높습니다.



고쳐 쓰다:

이제 당신은 더 낮은 수준으로 이동했습니다. 축하해요. C 컴파일러 사용 가능성과 표준 라이브러리를 포함하지 않는 옵션을 건너뛰었습니다. (무작위의협회아마도 방향이 잘못된 것 같습니다. )

나는 당신이 이미 몇 가지 답변을 알고 있다고 생각합니다 Why(그것이 당신이 질문한 방식입니다)(따라서 이 질문은 이미 답변되었으며 어쩌면 더 좋을 수도 있고 더 나쁠 수도 있습니다). 그리고 아마도 xxx보다 "더 적은 프로그램을 컴파일하는 방법"과 같은 새로운 질문을 하고 싶을 수도 있습니다. 이/또는/저것 메모리". 동기를 설명해야 할 것 같습니다. 최소한의 설치 공간으로 프로세스를 실행하고 싶습니까? 이유는 무엇입니까? 최소한의 하드웨어를 사용할 계획입니까? 아니면 백만 ​​개의 프로세스를 실행하려고 합니까?

gdb귀하의 어셈블러의 경우 ( break _start및 사용) 에서 실행하여 r볼 수 있습니다.

cat  /proc/222226/maps     # the number is PID of the process
00400000-00401000 r--p 00000000 103:04 1049144                           /home/h/tmpdir/asm.tmp.1
00401000-00402000 r-xp 00001000 103:04 1049144                           /home/h/tmpdir/asm.tmp.1
7ffff7ff9000-7ffff7ffd000 r--p 00000000 00:00 0                          [vvar]
7ffff7ffd000-7ffff7fff000 r-xp 00000000 00:00 0                          [vdso]
7ffffffde000-7ffffffff000 rw-p 00000000 00:00 0                          [stack]
ffffffffff600000-ffffffffff601000 --xp 00000000 00:00 0                  [vsyscall]

그리고

cat  /proc/222226/maps | tr a-z A-Z | awk 'BEGIN {print "ibase=16";}; {print $1}; ' | bc -l
-4096
-4096
-16384
-8192
-135168
-4096

하지만 그것이 RSS나 기타 등등에 얼마나 기여하는지는 모르겠습니다. 주위를 둘러보니 /proc/222226/smapsRSS가 별로 보이지 않았습니다.

참고: 명령줄의 내용이 메모리를 차지한다고 이미 언급했습니다. 환경도 마찬가지다.

실제로 보고된 내용은 무엇입니까 /usr/bin/time?프로그램은 어떻게 시작하나요? (명시적으로 또는 라이브러리 조합에서 숨겨진)을 통해 시작 되면 fork자체 메모리 사용량이 사용된 메모리에 영향을 미칩니다. 다음 내용이 흥미로워 보입니다.

$  /usr/bin/time -v nonexisting
/usr/bin/time: cannot run nonexisting: No such file or directory
Command exited with non-zero status 127
    Command being timed: "nonexisting"
...
    Maximum resident set size (kbytes): 768
    Minor (reclaiming a frame) page faults: 40

따라서 오류(또는 기타)로부터 복구하기 time위해 거의 많은 새 메모리를 사용하고 메시지를 인쇄하며 해당 작업에서 40페이지 오류가 발생합니다. (아마도 그 엄청난 돈의 대부분은 예상치 못한 정리와 포크된 프로세스를 종료하는 힘든 작업에 소비되었지만 어쨌든 그렇습니다.)execcannot run...

How요약: 대신 새로운 질문을 시작하는 것이 좋습니다 Why.

관련 정보