Help us understand the problem. What is going on with this article?

Linux プログラムのメモリ消費量を測る

More than 3 years have passed since last update.

結論: Linux プログラムのメモリ消費量を見積もるには /proc/pid/status の VmHWM が良いと思います。(コメントで教えていただいたが、$ /usr/bin/time -f "%M" プログラム のようにすると簡単に測れます)

とある Linux プログラムのメモリ消費量を測りたいのだが、色々な測り方があって微妙に結果が違うので調べてみた。

  • ps コマンド
  • proc ファイルシステム /proc/pid/status の結果
  • Valgrind というツールを使う

の3つの方法を比較して見る。以下の単純なプログラムを使った。

#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>

#define HEAP_SIZE  800000000
#define USED_SIZE  400000000
#define STACK_SIZE   2000000

int main(void)
{
    char * heap;
    char stack[STACK_SIZE];
    char dummy[2];

    heap = malloc(HEAP_SIZE);
    memset(heap, 0, USED_SIZE);

    printf("Heap: %d bytes, Used: %d byes, Stack: %d bytes, PID: %d\n", HEAP_SIZE, USED_SIZE, STACK_SIZE, getpid());
    printf("Press enter.\n");
    fgets(dummy, 2, stdin);

    free(heap);
    return 0;
}

このプログラムでは、malloc で 800 MB メモリを割り当てるがそのうち 400 MB しか使わない。ついでにスタックを 2MB 確保する。という事をやっている。動作中を観察したいのでその後 Enter を押すまでプログラムを止めている。これで色んな方法でメモリを測ってみる。

$ ./simple-memory
Heap: 800000000 bytes, Used: 400000000 byes, Stack: 2000000 bytes, PID: 26484
Press enter.

別のシェルで

$ ps -o pid,rss,sz,vsz,command -p 26484
  PID   RSS    SZ    VSZ COMMAND
26484 390936 196064 784256 ./simple-memory

$ cat /proc/26484/status | grep -e VmHWM -e VmRSS -e VmSize -e VmStk -e VmData -e VmStk -e VmExe
VmSize:   784256 kB
VmHWM:    390936 kB
VmRSS:    390936 kB
VmData:   781288 kB
VmStk:      1964 kB
VmExe:         4 kB

マニュアルを調べると各数値の意味は以下の通り

ps proc 結果 意味
RSS VmRSS 390936 物理メモリサイズ消費量
VmHWM 390936 最大物理メモリサイズ
SZ 196064 テキスト + データ + スタック?
VSZ VmSize 783280 仮想メモリ領域
VmData 781288 data size
VmStk 1964 stack size
VmExe 4 text size

これを見ると、ps の結果の一部は proc と同じ事が分かる。
このうちどれを「メモリ消費量」とみなすかは良くわからないのだが、「実際に必要とされているメモリ」という意味では VmRSS (その瞬間の物理メモリ) または VmHWM (最大で使ったメモリ) で良いのではと思う。VmStk はスタックサイズが出る。

ここで面白いのは、今回 malloc で割り当てた 800 MB のうち実際は半分しか書き込んでいないのだが、VmSize として割り当てたメモリが、VmRSS として書き込んだメモリが表示された。という事は malloc しただけでは物理メモリは使われないようだ。

さらに Valgrind で測ると次のようになる。

$ valgrind --tool=massif --time-unit=B --stacks=yes --max-stackframe=2000028 ./simple-memory
...
Heap: 800000000 bytes, Used: 400000000 byes, Stack: 2000000 bytes, PID: 8266
Press enter.

==8266== 

$ ms_print massif.out.8266
...
--------------------------------------------------------------------------------
Command:            ./simple-memory
Massif arguments:   --time-unit=B --stacks=yes
ms_print arguments: massif.out.8266
--------------------------------------------------------------------------------

    MB
764.9^                                    :                                   
     |                                    #:::::::::::::::::::::::::::::::::: 
     |                                    #                                   
     |                                    #                                   
     |                                    #                                   
     |                                    #                                   
   0 +----------------------------------------------------------------------->GB
     0                                                                   1.494
...
--------------------------------------------------------------------------------
  n        time(B)         total(B)   useful-heap(B) extra-heap(B)    stacks(B)
--------------------------------------------------------------------------------
 74    802,097,776      802,002,440      800,000,000         2,024    2,000,416
 75    802,097,776      802,002,440      800,000,000         2,024    2,000,416
99.75% (800,000,000B) (heap allocation functions) malloc/new/new[], --alloc-fns, etc.
->99.75% (800,000,000B) 0x85B0: main (simple-memory.c:16)

Valgrind は malloc を横取りして計測しているらしく、malloc した分のメモリを正確に表示する。Valgrind はコードの中で malloc していても実際に使われないメモリがある場合、使われるメモリよりも多めに報告する可能性がある。

この場合最大が heap + stack で 802,002,440 (764.9 MB) という事で、 --stacks=yes オプションを付けるとアスキーアートのグラフに出てくるメモリサイズはスタックサイズも反映している事が分かる。

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした