2012-04-03 13 views
4

if文を使用してスタックのメモリ割り当て解除を支援する必要がありますか?if文を使用してmicromanageスタック

例A:

 var objectHolder = new ObjectHolder(); 
     if (true) 
     { 
      List<DefinedObject> objectList; 
      using (var sr = new GenericStreamReader<DefinedObject>()) 
      { 
       objectList= sr.Get().ToList(); 
      } 
      if (true) 
      { 
       var DOF = new DefinedObjectFactory(); 
       objectHolder.DefinedObjects = DOF.DefineObjects(objectList); 
      } 
     } 
     //example endpoint 

例B:例エンドポイントは、例えばエンドポイントは、実施例Bに達したとき対に達したとき

 var objectHolder = new ObjectHolder(); 
     List<DefinedObject> objectList; 
     using (var sr = new GenericStreamReader<DefinedObject>()) 
     { 
     objectList= sr.Get().ToList(); 
     } 
     var DOF = new DefinedObjectFactory(); 
     objectHolder.DefinedObjects = DOF.DefineObjects(objectList); 
     //example endpoint 

ウィル例Aは、スタック上の軽いフットプリントを持っています?

+2

まったく同じマシンコードに変換されなかった場合、私は軽く驚きました。 – cHao

+0

@cHao - しかし、変数が範囲外になると、メモリは割り当て解除されませんか? –

+2

必ずしもそうではありません。地方自治体は関数の始めに割り当てられ、関数が終了したときにのみクリーンアップされます。 – cHao

答えて

5

使用法に基づいて、私はDefinedObjectFactoryがクラスであり、構造体ではないと仮定しています。したがって、スタック上の唯一のものはDefinedObjectFactoryへの参照です。実際のオブジェクトはヒープ上にあり、ガベージコレクタによって制御されます。

保存する可能性のあるスタックスペースは、1つのポインタのスペースだけなので、価値がありません。

7

if(true)は、最適化されたビルド(変数ライフスパンがメソッド全体よりも短い唯一のビルド)でコンパイルされるため、提案した2つのバージョン間には全く違いはありません。

1

これが少しでも違いがあっても、間違ったことを心配している可能性が非常に高いと思います。スタックスペースの割り当ては本当にあなたのアプリの問題ですか?

一般に、マイクロ最適化のためにコード内で「賢い」ものを実行する価値はありません。可能な限りもっともきれいで簡単な方法でコードを書くことは、通常はもっと良い考えです。実際の測定に基づいて実際にパーフォーマンス/スケーラビリティの問題がある場合は、ボトルネックである部品の書き換え/最適化を選択できます。

ほとんどの場合、コードのクリーン/直接/読み取り可能なバージョンが正常に動作することがわかります。もしそうでなければ、おそらくあなたが思っていた場所に問題はないでしょう。

+1

絶対に真実ですが、この質問は、GCを正しく理解しておらず信頼していない人からよく聞かれることがよくあります。ハイパーNIH症候群のようなもの! –

0

割り当て解除とガベージコレクションについて保証できることは、ある段階で発生します。

他の人が言っているように、if(真)が達成する唯一のことはジッタによって最適化されていることです。

あなたは既に使用して(..){}パターンを使用したので、代わりに私はこれをサポートするようにコードをリファクタリングしたい場合は(真の)ブロック使用している:に

if (true) 
{ 
    var DOF = new DefinedObjectFactory(); 
    objectHolder.DefinedObjects = DOF.DefineObjects(objectList); 
} 

を:

using (var DOF = new DefinedObjectFactory()) 
{ 
    objectHolder.DefinedObjects = DOF.DefineObjects(objectList); 
} 

それが役立つかどうかを確認してください。

ありますがを試すことができます1 otherthingですが、あなたはメモリマネージャを横取りべきではないとして、それは絶対に製品コードにはお勧めできませんですが、それは単に

GC.Collect(); 

に呼び出しを追加していますブロックを終了します。

私はそれが助けになるとは思っていませんが、なぜそれが一般的にスコープと割り当て解除について心配する価値がないのかをあなたに示すかもしれません。

12

まず第一に、スタックベースの割り当てシステムの全体ポイントは、あなたがないはどのような方法でそれを最適化する必要があるのですかということを正確です。ご心配なく。ジッタは、地元の人が再び読んだり書いたりすることがないことを完全に理解することができ、それが最良のことだと感じたらストレージを再利用します。ジッターがその仕事をするようにしましょう。それはあなたの助けを必要としません。 (*)

むしろ、ローカル変数が読者に合うようにプログラムを書いてください。それがあなたが最適化すべきものです。

最後に、新しいスコープを導入するために "if(true){}"と言う必要はありません。ちょうど新しいスコープを導入してください。言うことは完全に合法である:

void M() 
{ 
    { // new scope 
    } 

    { // another one 
    } 
} 

(*)があり、ジッタはあなたの助けを必要とする状況があり、そしてそれは地元のリソースを含む、ヒープ上のオブジェクトを参照するような状況でありますそれはによってアンマネージドコードによって使用される予定です。ジッタは、アンマネージコードがオブジェクトのリソースを使用することを知らず、誰もこのオブジェクトを使用していないと判断し、早期にクリーンアップする可能性があります。オブジェクトのファイナライザは、最終的なスレッドのリソースを解放し、アンマネージコードがリソースを使用している可能性があります。 オブジェクトは、ローカル変数が保持されているために生きているとは限りません。ローカル変数が再度読み取られない場合、ジッタはその記憶域を再利用し、参照先のオブジェクトを収集することが安全であることをガーベッジコレクタに伝え、潜在的にアンマネージドコードをクラッシュさせます。 KeepAliveを使用すると、特定のオブジェクトが生き続ける必要があり、最適化されないようにジッタをヒントできます。

関連する問題