3


0

次のコードを見てください。

1000回連続して実行した場合、DoSomething1()はDoSomething2()より速いですか。 DoSomething1()を1000回呼び出す場所を指定すると、DoSomething2()を1000回呼び出すよりも高速になると思います。

私の大きなバッファをすべて静的にすることに不利な点はありますか?

#define MAX_BUFFER_LENGTH 1024 * 5 void DoSomething1(){static char buf [MAX_BUFFER_LENGTH]; memset(buf、0、MAX_BUFFER_LENGTH); }

void DoSomething2(){char buf [MAX_BUFFER_LENGTH]; memset(buf、0、MAX_BUFFER_LENGTH); }

お時間をいただきありがとうございます。

6 Answer


8


静的バッファの短所:

  • あなたがスレッドセーフである必要があるならば、静的バッファを使うことはおそらくお勧めできません。

  • プログラムの終わりまでメモリが解放されないため、メモリの消費量が多くなります。

静的バッファの利点:

  • 静的バッファの割り当ては少なくなります。 毎回スタックに割り当てる必要はありません。

  • 静的バッファを使用すると、高すぎる割り当てからスタックがオーバーフローする可能性が少なくなります。


6


VCコンパイラで/ GSが有効になっている場合、スタック割り当てはもう少し高くなります。これにより、バッファオーバーランに対するセキュリティチェックが有効になります(デフォルトでは/ GSが有効になっています)。 実際には、2つのオプションをプロファイルしてどちらが速いかを確認する必要があります。 静的メモリとスタック上のキャッシュの局所性のようなものが違いを生む可能性があります。

これは、/ O2を指定したVCコンパイラを使用した、非静的バージョンです。

PROC; COMDAT; 5行目、5124行。 00001404H call __chkstk mov eax、DWORD PTR ___security_cookie xor eax、esp mov DWORD PTR __ $ ArrayPad $ [esp 5124]、eax;ライン7プッシュ5120。 00001400H基本、DWORD PTR _buf $ [esp 5128]プッシュ0プッシュeax呼び出し_memset;行9 mov ecx、DWORD PTR __ $ ArrayPad $ [esp 5136] movsx eax、BYTE PTR _buf $ [esp 5139] add esp、12; 0000000cH xx ecx、esp call @__ security_check_cookie @ 4 add esp、5124。 00001404H ret 0 _メインENDP _テキスト終了

そしてこれが静的バージョンです。

; COMDAT _main _TEXT SEGMENT _main PROC; COMDAT;ライン7プッシュ5120。 00001400H push 0 push OFFSET?buf @?1 ?? main @@ 9 @ 4PADA call _memset; 8行目movsx eax、BYTE PTR?buf @?1?main @ @ 9 @ 4PADA 3 add esp、12; 0000000cH;行9 ret 0 _メインENDP _テキストENDS END


4


両者の間に速度差はほとんどありません。 スタックにバッファを割り当てるのは非常に速いです - それはスタックポインタを値だけ減少させることです。 ただし、スタックに非常に大きなバッファを割り当てると、スタックがオーバーフローしてセグメンテーション違反/アクセス違反が発生する可能性があります。 逆に、たくさんの静的バッファがある場合は、プログラムのワーキングセットサイズをかなり増やすことになります。

もう1つの大きな違いは、スタックバッファはスレッドセーフでリエントラントであるのに対し、スタティックバッファはスレッドセーフでもリエントラントでもないことです。


2


コードをクラスに入れることも考えられます。 例えば。 何かのようなもの

const MAX_BUFFER_LENGTH = 1024 * 5。クラスDoSomethingEngine {private:char * buffer; public:DoSomethingEngine(){buffer = new buffer [MAX_BUFFER_LENGTH]; virtual〜DoSomethingEngine(){free(buffer);} void DoItNow(){memset(buffer、0、MAX_BUFFER_LENGTH); ... }}

各トレッドが独自のエンジンを割り当てるだけであれば、これは安全です。 それはスタック上の大量のメモリの割り当てを避けます。 ヒープ上の割り当ては小さなオーバーヘッドですが、クラスのインスタンスを何度も再利用する場合、これは無視できます。


2


私がここでマルチスレッドソフトウェアに取り組んでいるのは私だけですか? 静的バッファは、そのような状況では絶対に絶対必要というわけではありません。


0


他の人が言っているように、スタック割り当ては非常に速いので、毎回再割り当てする必要がないことによるスピードアップは、おそらくArrayListやHashTable(一般的な世界ではList <>とDictionary <、>)のようなより複雑なオブジェクトのほうが大きいですまた、容量が正しく設定されていない場合は、コンテナが容量に達するたびに不要な再割り当てが発生し、新しいメモリを割り当てて古いメモリから新しいメモリに内容をコピーする必要があります。 これは、必要とされるサイズに拡張できるようにするためのList <>オブジェクトを持っていることが多いので、Clear()を呼び出すことによってそれらを再利用します。 ただし、大量のメモリを割り当てるようなルージュ呼び出しがある場合は、メモリリークに注意する必要があります。