malloc(3)
を呼んだ時、glibcはヒープ領域から指定したサイズのチャンクを確保するが、ヒープ領域が足りなかった場合glibcはbrk(2)
を呼んでヒープ領域を拡張するか、Anonymous Memoryと呼ばれる領域をmmap(2)
して新たなヒープ領域を確保する。
この動作を制御する環境変数がMALLOC_MMAP_THRESHOLD_
らしいのでこれを試しているのだけれど、効かなくて困った。
しかたがないのでglibcのソースを読んでいるとmmap(2)
を使用する最大サイズを指定するMALLOC_MMAP_MAX_
というのも見つけた、これはばっちり効いたのでこれを使おう。
1M を 3回 malloc するだけのコード
#include <stdio.h>
#include <stdlib.h>
int main(){
int i;
for(i=0;i<3;i++){
malloc(1*1024*1024);
}
return 0;
}
% strace ./a.out
(略)
mmap2(NULL, 1052672, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb7c9b000
mmap2(NULL, 2101248, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb7a9a000
mmap2(NULL, 3149824, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb7799000
既定では3回mmap(2)してる。
MALLOC_MMAP_MAX_=0
するとbrk(2)
をだけを呼ぶようになった。
MALLOC_MMAP_MAX_=1
にすると、
% strace env MALLOC_MMAP_MAX_=1 ./a.out
(略)
mmap2(NULL, 1052672, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb7cfe000
brk(0) = 0x94bc000
brk(0x95dd000) = 0x95dd000
brk(0x96dd000) = 0x96dd000
最初のmalloc(3)
だけmmap(2)
した。
単位はMbyte なのね。(MALLOC_TRIM_THRESHOLD_の単位は byte だったのに…)
これで完全に malloc(3) の中で mmap(2) を呼ぶこと無いかというと、そういう訳でもなくて、特定の条件下で mmap(2) する場合ある様なので困ったな。