11

2 つの異なるバージョンのメモリ割り当てシステムを持つ画像圧縮アプリケーションがあります。元のものでは、malloc がどこでも使用され、2 番目のものでは、メモリのチャンクを割り当て、そのメモリの一部を myalloc() 呼び出しに返す単純なプール アロケータを実装しました。

malloc を使用すると、膨大なメモリ オーバーヘッドが発生することがわかっています。メモリ使用量が最も多い場合、malloc() コードは 1920x1080x16bpp のイメージに約 170 メガバイトのメモリを必要としますが、プール アロケータは 48 メガバイトしか割り当てず、そのうち 47 メガバイトを割り当てます。プログラムによって使用されます。

メモリ割り当てパターンに関しては、プログラムはテスト イメージで 8 バイト (ほとんど)、32 バイト (多く)、1080 バイト ブロック (いくつか) を割り当てます。これらとは別に、コードには動的なメモリ割り当てはありません。

テスト システムの OS は Windows 7 (64 ビット) です。

メモリ使用量をどのようにテストしましたか?

カスタム アロケーターを使用すると、すべての malloc 呼び出しがアロケーターに委ねられるため、メモリの使用量を確認できます。malloc() を使用して、デバッグ モードでコードをステップ実行し、タスク マネージャーでメモリ使用量を確認しました。リリース モードでも同じことを行いましたが、コンパイラが多くのものを最適化して取り除くため、細粒度は低くなりました。そのため、コードを 1 つずつステップ実行することはできませんでした (リリースとデバッグの間のメモリの違いは約 20 MB であり、これが原因であると考えられます)。最適化とリリース モードでのデバッグ情報の欠如)。

このような巨大なオーバーヘッドの原因は、malloc だけでしょうか? もしそうなら、malloc内でこのオーバーヘッドを正確に引き起こしているのは何ですか?

4

3 に答える 3

8

Windows 7 では、HeapSetInformation() を明示的に呼び出して要求することなく、常に断片化の少ないヒープ アロケーターを取得します。そのアロケータは、断片化を減らすために仮想メモリ空​​間を犠牲にします。あなたのプログラムは実際には 170 メガバイトを使用していません。同じようなサイズの割り当てを待っている空きブロックの束が横たわっているだけです。

このアルゴリズムは、断片化を減らすために何もしないカスタム アロケータを使用すると、非常に簡単に打ち負かされます。プログラムを単一のデバッグセッションよりも長く実行し続けるまで、副作用は見られませんが、これはうまくいくかもしれません。それが予想される使用パターンである場合は、数日または数週間安定していることを確認する必要があります。

最善の方法は、それについて心配しないことです。170 MB はかなり小さいポテトです。これは仮想メモリであることを覚えておいてください。費用はかかりません。

于 2012-10-25T09:42:12.557 に答える
6

まず、malloc はポインターを 16 バイト境界に揃えます。さらに、戻り値の前のアドレスに少なくとも 1 つのポインター (または割り当てられた長さ) を格納します。次に、おそらく魔法の値またはリリース カウンターを追加して、リンク リストが壊れていないこと、またはメモリ ブロックが 2 回解放されていないことを示します (2 回解放するための解放 ASSERTS)。

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

int main(int ac, char**av)
{
  int *foo = malloc(4);
  int *bar = malloc(4);
  printf("%d\n", (int)bar - (int)foo);
}

リターン: 32

于 2012-10-25T08:51:37.533 に答える
4

注意: Visual Studio またはアタッチされたデバッガーでプログラムを実行すると、デフォルトで malloc の動作が大幅に変更され、低フラグメンテーション ヒープは使用されず、メモリ オーバーヘッドは実際の使用量を表していない可能性があります ( https:/ /stackoverflow.com/a/3768820/16673 )。環境変数 _NO_DEBUG_HEAP=1 を使用して、これによる影響を回避するか、デバッガーで実行していないときにメモリ使用量を測定する必要があります。

于 2012-10-25T09:40:09.257 に答える