51

典型的な実世界のプログラムにおけるメモリの割り当て/割り当て解除は、どの程度のボトルネックですか? 通常、パフォーマンスが問題となるあらゆる種類のプログラムからの回答を歓迎します。malloc/free/garbage collection の適切な実装は、いくつかのまれなケースでボトルネックにすぎないほど十分に高速であるか、またはほとんどのパフォーマンスが重要なソフトウェアは、メモリ割り当ての量を抑えようとするか、より高速な malloc/free/ を使用することで大幅にメリットがありますガベージコレクションの実装?

注:ここではリアルタイムのことについて話しているわけではありません。パフォーマンスが重要とは、スループットが重要であるものの、レイテンシが必ずしも重要ではないことを意味します。

編集: malloc について言及していますが、この質問はC/C++ 固有のものではありません。

4

12 に答える 12

41

特に断片化が大きくなり、アロケーターが要求する連続した領域をより大きなヒープでより多く探し回らなければならない場合、これは重要です。ほとんどのパフォーマンスに敏感なアプリケーションは、通常、この問題を回避するために、独自の固定サイズのブロック アロケータを記述します (たとえば、一度に 16MB のメモリを OS に要求し、それを 4kb、16kb などの固定ブロックに分割します)。

ゲームでは、malloc()/free() の呼び出しが CPU の 15% を消費するのを見たことがあります (不適切に作成された製品の場合)。または、慎重に作成され最適化されたブロック アロケーターを使用すると、わずか 5% しか消費しません。ゲームが 60 ヘルツの一貫したスループットを持たなければならないことを考えると、ガベージ コレクターがときどき実行されている間に 5​​00 ミリ秒停止することは実用的ではありません。

于 2009-01-22T20:41:25.603 に答える
23

Nearly every high performance application now has to use threads to exploit parallel computation. This is where the real memory allocation speed killer comes in when writing C/C++ applications.

In a C or C++ application, malloc/new must take a lock on the global heap for every operation. Even without contention locks are far from free and should be avoided as much as possible.

Java and C# are better at this because threading was designed in from the start and the memory allocators work from per-thread pools. This can be done in C/C++ as well, but it isn't automatic.

于 2009-01-22T20:49:11.750 に答える
11

まず、malloc と言ったので、C または C++ について話していると思います。

メモリの割り当てと割り当て解除は、実際のプログラムにとって重大なボトルネックになる傾向があります。メモリを割り当てたり割り当てを解除したりすると、「内部」で多くのことが行われますが、そのすべてがシステム固有です。メモリは実際に移動またはデフラグされ、ページは再編成される可能性があります。影響がどうなるかを知るプラットフォームに依存しない方法はありません。一部のシステム (多くのゲーム コンソールなど) もメモリの最適化を行わないため、これらのシステムでは、メモリが断片化されるにつれてメモリ不足エラーが発生し始めます。

典型的な回避策は、できるだけ多くのメモリを前もって割り当て、プログラムが終了するまでそれを保持することです。そのメモリを使用して、大きなモノリシックなデータ セットを格納するか、メモリ プールの実装を使用してチャンクで処理することができます。多くの C/C++ 標準ライブラリの実装は、まさにこの理由から、一定量のメモリ プール自体を実行します。

ただし、時間に敏感な C/C++ プログラムを使用している場合、大量のメモリ割り当て/割り当て解除を行うと、パフォーマンスが低下します。

于 2009-01-22T20:47:19.617 に答える
7

一般に、ほとんどのアプリケーションでは、ロックの競合、アルゴリズムの複雑さ、またはその他のパフォーマンスの問題によって、メモリ割り当てのコストはおそらく小さくなります。一般的に、これはおそらく私が心配するパフォーマンスの問題のトップ 10 に入っていないと思います。

ここで、メモリの非常に大きなチャンクを取得することが問題になる可能性があります。そして、メモリを取得しても適切に削除しないことは、私が心配していることです。

Java および JVM ベースの言語では、オブジェクトの新規作成が非常に高速になりました。

これは、自分のことを知っている人によるまともな記事の1つであり、下部に関連リンクへの参照がいくつかあります: http://www.ibm.com/developerworks/java/library/j-jtp09275.html

于 2009-01-22T20:42:05.257 に答える
4

Java VMは、アプリケーションコードが実行していることとはほとんど関係なく、オペレーティングシステムからメモリを要求して解放します。これにより、メモリを大きなチャンクで取得して解放できます。これは、手動のメモリ管理で得られるように、小さな個別の操作で行うよりもはるかに効率的です。

この記事は2005年に作成されたものであり、JVMスタイルのメモリ管理はすでに進んでいます。それ以来、状況は改善されただけです。

生の割り当てパフォーマンスが速いのは、Java言語とC / C ++のどちらの言語ですか?答えはあなたを驚かせるかもしれません-最新のJVMでの割り当ては、最高のパフォーマンスを発揮するmalloc実装よりもはるかに高速です。HotSpot 1.4.2以降のnewObject()の一般的なコードパスは約10のマシン命令(Sunが提供するデータ。リソースを参照)ですが、Cで最高のパフォーマンスを発揮するmalloc実装では、呼び出しごとに平均60〜100の命令が必要です( Detlefs、et。al .;「参考文献」を参照)。そして、割り当てのパフォーマンスは、全体的なパフォーマンスの些細な要素ではありません。ベンチマークは、PerlやGhostscriptなどの多くの実際のCおよびC++プログラムを示しています。

于 2009-07-06T09:23:58.777 に答える
4

Java (および適切な GC 実装を備えた他の言語) では、オブジェクトの割り当ては非常に安価です。SUN JVM では、10 CPU サイクルしか必要としません。C/c++ の malloc は、より多くの作業を行う必要があるという理由だけで、はるかにコストがかかります。

それでも、Java でのオブジェクトの割り当ては非常に安価です。Web アプリケーションの多くのユーザーに対して並行してこれを行うと、より多くのガベージ コレクターの実行がトリガーされるため、パフォーマンスの問題が発生する可能性があります。したがって、GC によって行われる割り当て解除によって発生する、Java での割り当ての間接コストがあります。これらのコストは、セットアップ (メモリの量) とアプリケーションに大きく依存するため、定量化するのは困難です。

于 2009-01-23T10:21:17.880 に答える
3

以前に答えたことは知っていますが、それはあなたの質問ではなく、他の答えに対する答えでした。

直接お話を伺うと、私の理解が正しければ、パフォーマンス ユース ケースの基準はスループットです。

これは、 NUMA 対応の allocatorsをほぼ排他的に見なければならないことを意味します。

以前の参照はありません。IBM JVM 論文、Microquill C、SUN JVM。この点をカバーするので、少なくとも AMD ABI では、NUMA が卓越したメモリ CPU ガバナーである今日のアプリケーションを非常に疑っています。

手を下げて; 現実の世界、偽の世界、どんな世界でも... NUMA 対応のメモリ要求/使用テクノロジはより高速です。残念ながら、私は現在 Windows を実行しており、Linux で利用可能な「numastat」が見つかりません。

私の友人は、FreeBSD カーネルの実装でこれについて詳しく書いています。

リモートノードの上に通常非常に大量のローカルノードメモリリクエストを表示できるにもかかわらず(パフォーマンススループットの明らかな利点を強調しています)、あなたは自分自身を無愛想にベンチマークすることができます。あなたのパフォーマンス特性は非常に具体的です。

多くの点で、少なくとも以前の 5.x VMWARE は、少なくとも当時は、リモート ノードから頻繁にページを要求する NUMA を利用していなかったため、フェアリングがかなり不十分だったことを知っています。ただし、メモリのコンパートメント化またはコンテナ化に関しては、VM は非常にユニークな獣です。

私が引用した参考文献の 1 つは、AMD ABI 用の Microsoft の API 実装です。これには、ユーザー ランド アプリケーション開発者が利用できる NUMA 割り当てに特化したインターフェイスがあります;)

これは、4 つの異なるヒープ実装を比較する一部のブラウザー アドオン開発者による、かなり最近の視覚的およびすべての分析です。当然のことながら、彼らが開発したものがトップであることが判明しました (奇妙なことに、テストを行う人々がしばしば最高のスコアを示します)。

彼らは、少なくとも彼らのユースケースでは、空間/時間の間の正確なトレードオフが何であるかをいくつかの方法で定量的にカバーしています.一般的に、彼らはLFHを特定していました.または同様に設計されたアプローチは、本質的にバットから大幅に多くのメモリを消費しますが、時間の経過とともにメモリの使用量が少なくなる可能性があります...グラフもきれいです...

ただし、よく理解した後、典型的なワークロードに基づいて HEAP 実装を選択することは良い考えだと思います;)が、ニーズをよく理解するには、これらのオッズとエンドを最適化する前に、まず基本的な操作が正しいことを確認してください;)

于 2009-06-03T07:09:06.673 に答える
3

パフォーマンスの観点から見たメモリの割り当てと解放は、比較的コストのかかる操作です。最新のオペレーティング システムでの呼び出しは、オペレーティング システムが仮想メモリ、ページング/マッピング、実行保護などを処理できるように、カーネルに至るまで行う必要があります。

一方、ほとんどすべての最新のプログラミング言語は、事前に割り当てられたバッファーを操作する「アロケーター」の背後にこれらの操作を隠しています。

この概念は、スループットを重視するほとんどのアプリケーションでも使用されます。

于 2009-01-22T20:44:16.890 に答える
2

MicroQuill SmartHeap技術仕様によると、「一般的なアプリケーション[...]は、合計実行時間の40%をメモリの管理に費やしています」。この数字を上限と見なすことができます。個人的には、一般的なアプリケーションは実行時間の10〜15%をメモリの割り当て/割り当て解除に費やしていると感じています。シングルスレッドアプリケーションのボトルネックになることはめったにありません。

マルチスレッドC/C ++アプリケーションでは、ロックの競合が原因で標準アロケータが問題になります。ここから、よりスケーラブルなソリューションを探し始めます。ただし、アムダールの法則に留意してください。

于 2009-02-02T09:08:46.323 に答える
0

他の人はC/C ++をカバーしているので、.NETに少し情報を追加します。

.NETでは、ヒープの第0世代部分のメモリを取得するだけでよいため、ヒープの割り当ては一般に非常に高速です。明らかに、これは永遠に続くことはできません。そこでガベージコレクションが発生します。メモリの圧縮中にユーザースレッドを一時停止する必要があるため、ガベージコレクションはアプリケーションのパフォーマンスに大きな影響を与える可能性があります。フルコレクトが少ないほど良いです。

.NETのガベージコレクターのワークロードに影響を与えるためにできることはさまざまです。一般に、メモリ参照が多い場合、ガベージコレクタはより多くの作業を行う必要があります。たとえば、ノード間の参照の代わりに隣接行列を使用してグラフを実装することにより、ガベージコレクターはより少ない参照を分析する必要があります。

それがアプリケーションで実際に重要であるかどうかは、いくつかの要因に依存するため、このような最適化を行う前に、実際のデータを使用してアプリケーションのプロファイルを作成する必要があります。

于 2009-02-02T09:31:12.347 に答える