2017-05-22 15 views
2

オブジェクトの数が増えるにつれてメモリがどのように割り当てられるかを理解しようとしています。テストプログラムには、400万個のオブジェクトが作成され、そのメモリ占有量は約23GBです。C++オブジェクトメモリ管理

なぜ単一のオブジェクトサイズがわずか16バイトである間に、このような膨大なメモリを占有しますか?理想的には私はそれが4億倍の16倍になるはずだと思います。

struct class1 { 
     long long id; 
     double value=0.0; 
     class1(long long id) { 
       this.id = id; 
     } 
}; 

for (int i=1;i<=400000000;i++) { 
    class1 *t = new class1(i); 
} 
+1

ダイナミックに割り当てられたブロックは、通常、サイズを丸めます(実際には、使用可能なサイズは通常、新しいオペレータが求めたサイズよりもやや大きい)、管理データオーバーヘッドを少し追加します。動的に割り当てられたものは通常かなり広がっています(キャッシュの局所性が悪い)。これはできるだけ多くの新しい/ malloc呼び出しを割り当てることをお勧めします。 – PSkocik

+1

クラスフットプリント(https://stackoverflow.com/questions/937773/how-do-you-determine-the-size-of-an-object-in-cを参照)、パディング、およびコンパイラフラグも調べます。 – ioanb7

+1

小さな割り当てをたくさんすると、メモリ空間が断片化する傾向があります。また、あなたのメモリアロケータは、一度に16バイト(一度に1ページのような)よりも大きなチャンクを一度に割り当てるかもしれません。また、あなたのクラスはちょうど16バイトではないかもしれません。そこにはパディングがあります(アロケータオーバーヘッド)。良いことは、あなたが*メモリに書き込まないならば、OSは物理的なページ(少なくともLinuxカーネルではない)で割り振りを元に戻すわけではないので、何もコストがかからないということです。 –

答えて

0

すべての割り当てには、ブロックに関する追加情報を含む「ヘッダー」があります。ブロックのサイズが含まれていたので、ブロックが空いているか割り当てられていないかどうかを自由に言うことができます。配列の要素数(配列の場合)などです。

2つのブロックを割り当て、ポインタを減算すると、実際のサイズが各ブロックで占有されます。

次に、これらのオブジェクトの大規模な配列(たとえば100,000)を割り当て、次に1つだけを割り当て、それらのポインタを減算します。そのブロックにはヘッダーが1つしかないので、16 * 100,000サイズに近いものを表示するはずです。

+1

を参照してください。あなたは、あなたが話している特定のアロケータに名前を付けることなく、「それはどういうものなのか」と言うことはできません。 –

+0

私は一般人で話していました。詳細はさまざまですが、ほぼすべてのアロケータはほぼ同じように動作します。 –

2

問題が同じ数のオブジェクトとメモリフットプリントを減らしたプログラムを書く方法であれば、新しい演算子と削除演算子がオーバーロードされ、16バイトのブロックを除外する独自のアロケータを作成する大きなプールから。

汎用アロケータは一般目的であるため非効率的であり、小さなオブジェクトを割り当てるときにメモリを節約するのではなく、高速であるように記述されています。ほとんどのプログラムは、数百万の小さな割り当てでマシン容量を強調しません。