2009-06-02 19 views
4

私はいくつかのテキスト処理の一時バッファとしてメモリブロック(約1000バイト)を必要とするC++アプリケーションを作成しています。この操作は1秒に10,000回まで繰り返すことができます。オーバーライトと割り当て/割り当て解除の効率 - 効率

バッファを必要とするたびに新しいメモリを割り当てるのは、固定バッファを持ってクリアするよりも、スマートなポインタで新しいメモリ、スコープ外でメモリが解放されていることを誰かが確認できますか?処理が完了するたびに、そのすべてのバイトに0を書き留めます)。

C++の常識のように聞こえますが、インターネット上で何かを見つけることはできません。

自動ガベージコレクション機能(Java、.netなど)を使用するコンピュータ言語の状況は異なりますか?

+0

静的バッファが明らかに! すべてのメモリをゼロにする必要がある場合は、memsetを使用する必要があります。 – toto

答えて

16

あなたがそれを必要とする度にメモリを割り当てて解放するのはおそらくもっと高価ですが、もっと大きな質問があります。それがどのように正しく動作し、メモリが漏れ/壊れないかを知る最も簡単な方法を書いてください。あなたのパフォーマンスが十分でない場合にのみ、コードをプロファイルして、改善できる場所を見てください。

+3

1秒あたり10,000個の割り当てを維持することが重要です.1秒で9,999回の繰り返しが少なすぎると...リアルタイム制約がある場合、必要かもしれない。すべての設計時間「最適化」が早すぎるわけではありません。 –

+1

私はクリスが頭の爪に当たったと思う。スループットレベルを保証するには、コードのアルゴリズムの複雑さを慎重に考慮する必要があります。静的割り当てとローカル割り当ては、予測可能なパフォーマンスを備えています。これは、動的割り当てには当てはまりません。 – Constantin

6

私はあなたの学術「確認」を与えることはできませんが、この考えてみます。

CPUが命令を実行するたびに、それは時間がかかります。バッファを破棄してから再割り当てすると、CPUはデアロケート/再割り当て命令を実行する必要があります。バッファーを再利用する場合、それらの操作を実行する必要はありません。

再利用が速いと言うのはおそらく安全です(同じメモリをCPUキャッシュに置くことができるメモリの局所性についても言及していません)。

これは、リアルタイムアプリケーションのように、実際にはきつい(実際のアプリケーションのように)必要があるものを書いていないか、パフォーマンス測定を行っている間にこのバッファ作業をボトルネックと認識していない限り)、私はそれを最も理にかなった方法で書いていると言い、維持するのが最も簡単です。現代のマシンでは、メンテナンスコストは、ソフトウェアの総コストのうち、1,000バイトを管理する場合のパフォーマンスコストよりも大きくなる可能性があります。

1

いつもと同じように、これを両方の方法で実装し、両方のソリューションが実際の比較を行い、思考や意見を自分の経験に基づいて判断するのではなく、 (あなたが気づいていない方法であなたと違うかもしれません)。

4

(newまたはmallocを使用して)メモリを割り当ててもそれがクリアされません。メモリを使用する前にメモリを0に設定しなければならない場合は、いずれかの方法でクリアする必要があります。その場合、静的バッファを使用することが大きな利点です。さらに、バッファの一部のみを使用する場合は、使用された量を追跡し、使用済みの部分をクリアする必要があります。

callocはバッファ全体を0に設定しますが、malloc + memsetよりもはるかに高速であるとは思いません。

2

に関するJavaは:

大きな違いは、Javaの保証は、新たに0になるようにメモリを割り当てられ、おそらくこれより速くあなたが手動で行う場合よりもないことです。また、Javaのガーベッジ・コレクタは、短命オブジェクトの割当てと割当て解除時に非常に効率的ですが、一方、不要に長生きしたオブジェクトは余分な作業を引き起こす可能性があります。したがって、C++よりもJavaでパフォーマンスが向上するたびに配列を再配置する可能性が高くなります。

ガベージコレクションのパフォーマンスは予測するのが非常に難しいので、どちらの方法で行っても、どちらが速いのかを確認するだけです。それはおそらくここで質問してすべての答えを読むよりも時間がかかりません。

+0

ありがとうございます。私はあなたが解放されたメモリを制御できないことを知っているので、Javaの質問に尋ねました。ただし、自分でクリアする必要がある場合、割り当てられたメモリはC++とは異なり、ゼロで埋められることを指摘してください。 – Andy

1

他の誰もがそれをカバーしているので、標準の「最適化について心配しないでください」をスキップします。あなたのバッファをあなたの関数のローカルとして宣言し、memsetを使ってそのバッファを0にするのが最も速くなります。ローカルバッファでは、スタックポインタを正しいバイト数だけ移動するだけで、コンパイラによって空間が「割り当てられる」。割り当てはそれより速くはなりません。ビジュアルスタジオでは、#pragma intrinsic(memsetを追加できます)。 gccは組み込み関数もサポートしていますが、それらを使用する方法を覚えていません。私は、最新のバージョンでは、これまでに言及されていない限り、それらを使用すると思います。 intrinsic memsetは、プロセッサにメモリの範囲を0に指示する、いくつかのインライン化された命令に展開されます。それ以上のスピードを出すことはありません。それは、あなたがする必要がない場合は、メモリをゼロにしないでください。

さらに、ローカルで宣言されたバッファを使用するだけで、コードははるかに明確になります。あなたが言ったことから、あなたのバッファは、それを使用するルーチンの範囲外に存続する必要はありません。 1000バイトは現代的には小さいです。自動メモリの代わりにダイナミックメモリを使用すると、テストして管理する必要がある一連のコードが追加されます。それをしないでください。自動メモリは明らかな選択肢です。

+0

スタック領域は必ずしも無制限であるとは限らず、任意に大きなスタックオブジェクトを割り当てることができない場合があります。 –

+0

真。ビジュアルスタジオのデフォルトスタックサイズは1Mです。 –

1

アルゴリズム効率(大きな表記法など)の研究を行ったことがあれば、ほとんどのフリーストアの実装では、新しい/ malloc()要求を満たすためにフリーストア内の利用可能なブロックを見つけるために実行されるアルゴリズムの反復の境界です。

1つの固定バッファを繰り返し使用することで、数桁のパフォーマンスが向上します。特に、ガベージコレクションサイクルが実行されるまで未使用のメモリブロックがフリーストアに残ることがあります。

+0

実際には保証があります。再利用で得られるものであるO(1)の保証はありません。 –

+0

無料ストアアルゴリズムの効率性のオンライン分析がわかりました。 –

0

大きなメモリ割り当てになると、何かを割り当てる必要があるたびに1回行うのではなく、1回行うほうがよいでしょう。その理由は、メモリが断片化され、速度が遅くなる(メモリに大量のものを作成して削除するために多くのリソースが必要になるためです)。あなたの操作のために十分な量のメモリを予約するデータ構造があれば、より良いことがあります。そうすることのダウンサイジングは、あなたの記憶の大部分が取られることです。

#include <cstdlib> 
using std::malloc; 
using std::free; 
#include <new> 
using std::bad_alloc; 

void * operator new(size_t n) 
{ 
    void * p = malloc(n); 
    if(!p) throw bad_alloc(); 
    return p; 
} 

void operator delete (void *p) 
{ 
    if (p) free(p); 
} 

新を行うと、すべての時間は高価なことができます削除します。ここでは

はどのように新しいとC++でのボンネットの下にルックスを削除しています!これが、C#やJavaなどの言語がC++よりも遅い理由です。ガベージコレクタの唯一の利点は、プログラムのすべてのものをメモリにまとめて(メモリをデフラグする)ことができることです。これは、あなたのプログラムのためにメモリにたくさんのものがあるならば、コストがかかるかもしれません。

また、STLのアルゴリズムを見てください。これは、特定の操作を最適化することによって役立ちます。

+0

これはなぜ役に立たなかったのですか? – Partial

関連する問題