24Mのメモリを要求したときにOSが割り当てる量をテストしたいと思います。
for (i = 0; i < 1024*1024; i++)
ptr = (char *)malloc(24);
このように書くと、top
コマンドからRESが32Mになります。
ptr = (char *)malloc(24*1024*1024);
しかし、少し変更すると、RESは244になります。それらの違いは何ですか?結果が244なのはなぜですか?
アロケータには、メモリも必要とする簿記に関する独自のデータ構造があります。小さなチャンクで割り当てる場合(最初のケース)、アロケータは、各チャンクが割り当てられる場所とその長さに関する多くの追加データを保持する必要があります。malloc
さらに、十分に整列されたブロックを返す必要があるため、チャンク間に未使用のメモリのギャップが生じる可能性があります。ほとんどの場合、8バイト境界にあります。
2番目のケースでは、アロケータは1つの連続したブロックのみを提供し、そのブロックに対してのみ簿記を行います。
簿記メモリのオーバーヘッドがデータ自体の量を上回る可能性があるため、多数の小さな割り当てには常に注意してください。
2番目の割り当ては、メモリにほとんど影響しません。アロケータは「大丈夫、あなたはそれを持つことができます」とあなたに言います、しかしあなたが実際にメモリに触れなければ、OSはあなたがそれを決して使わないことを望んで、実際にあなたにそれを与えることは決してありません。ポンジースキームのようなビット。一方、他の方法では、多くのページに何か(最大で数バイト)が書き込まれるため、OSは実際にメモリを提供するように強制されます。
これを確認してみてください。約24mの使用量が得られるはずです。
memset(ptr, 1, 1024 * 1024 * 24);
要するに、topはあなたがどれだけ割り当てたか、つまりあなたが何を求めたかを教えてくれませんmalloc
。プロセスに割り当てられたOSを示します。
言われていることに加えて:一部のコンパイラは、ループ内で複数の24バイトブロックを割り当て、アドレスを同じポインタに割り当て、割り当てた最後のブロックのみを保持して、他のすべてのmallocを効果的に役に立たないようにする方法に気付く可能性があります。したがって、ループ全体を次のように最適化する場合があります。
ptr = (char *)malloc(24);
i = 1024*1024;