CAT724_malloc

CAT724の出荷状態で、アプリケーションで使用できるメモリ量を調査した。

条件

  • linux-3.0.4 出荷状態のconfigration
  • 出荷状態から追加したアプリ/プロセス/デーモン無し
  • 起動直後

freeコマンドの結果

# free
              total         used         free       shared      buffers
  Mem:       254980        36324       218656            0            0
 Swap:            0            0            0
Total:       254980        36324       218656

swapは無しのため218656kbyte (218Mbyte)の空きがあるとのこと

試験1

1メガバイトずつmalloc()で確保し、0で埋めていく。

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

#define MEGABYTE (1024*1024)

int main(){
        int i=0;
        char *p;

        while(1){
                printf("%d megabyte\n",++i);
                p = malloc(MEGABYTE); /*メモリアロケーション*/
                if(p==NULL){
                        printf("out of memory\n");
                        exit(1);
                }
                memset(p,0,MEGABYTE); /* ゼロ埋め */
        }
}

結果

# ./a.out
1 megabyte
2 megabyte
3 megabyte
...略...
220 megabyte
221 megabyte
222 megabyte
a.out invoked oom-killer: gfp_mask=0x200da, order=0, oom_adj=0, oom_score_adj=0

222メガバイト目のmalloc()は成功したが、実際にアクセスしたときに oom-killer (out of memoryでプロセスの終了) が発生した。

試験2

似たような試験だが少し改造して nメガバイトmalloc()で確保、ゼロ埋めし、解放する。確保できる最大メモリを調べる。

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

#define MEGABYTE (1024*1024)

int main(){
        int i=0;
        char *p;

        while(1){
                printf("%d megabyte\n",++i);
                p = malloc(i * MEGABYTE); /*メモリアロケーション*/
                if(p==NULL){
                        printf("out of memory\n");
                        exit(1);
                }
                memset(p,0,i * MEGABYTE); /* ゼロ埋め */
                free(p);  /* 解放 */
        }
}

結果

# ./a.out
1 megabyte
2 megabyte
3 megabyte
...略...
220 megabyte
221 megabyte
222 megabyte
223 megabyte
out of memory

同様の傾向で 222メガバイトは成功、223メガバイトのmalloc()は失敗した。

考察

  • linuxのmalloc()はデマンドページングを採用しているため、malloc()だけでは実際の物理メモリはアサインされない事がある。malloc()したあと、実際にそのメモリ番地(仮想空間)にライトしたときに初めて物理メモリがマップされる。そのためにmemset()でゼロ埋めをしている。(厳密に言うとlibcが確保したヒープで足りないときに、ヒープ拡張の際にデマンドページングが発生する)
  • malloc()したときはメモリがあったが、実際にアクセスしたときに物理メモリが無くなっていたときに発生するのがoom-killer。これは全てのlinuxで同じアルゴリズムを採用しているためアーキテクチャによらず(PCでもARMでも)起こりえる。
  • CAT724は /tmp や /var が RAMDISK になっている。起動直後は /tmp や /var に置くファイルが少ないが、ここが増えてくればその分アプリで使用できるメモリは減少する。
  • プログラムサイズが大きくなればRAMを消費する。他に起動しているプロセスが増えればRAMを消費する

以上を考慮すると

  • 実験の結果確保できたメモリの最大は222Mバイトだった
  • 実用的には200Mバイト程度と見込んでおく

と思われる。

関連