4

スタックのメモリ割り当て解除を支援するために if ステートメントを使用する必要がありますか?

例 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:

        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 は、例 B で例のエンドポイントに到達したときと比較して、例のエンドポイントに到達したときのスタックのフットプリントが軽くなりますか??

4

5 に答える 5

12

まず、スタックベースの割り当てシステムの要点は、まったく最適化する必要がないということです。ご心配なく。ジッターは、ローカルが二度と読み取られたり書き込まれたりしないことを認識し、それが最善の方法であると思われる場合はそのストレージを再利用することができます。ジッターに仕事をさせてください。あなたの助けは必要ありません。(*)

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

最後に、新しいスコープを導入するために「if (true) { }」と言う必要はありません。新しいスコープを導入するだけです。次のように言うことは完全に合法です。

void M()
{
    { // new scope
    }

    { // another one
    }
} 

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

于 2012-04-04T00:12:24.903 に答える
7

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

于 2012-04-03T23:33:27.903 に答える
5

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

節約できる可能性のあるスタックスペースは、単一のポインター用のスペースだけなので、それだけの価値はありません。

于 2012-04-03T23:48:50.233 に答える
1

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

一般に、マイクロ最適化のためにコードで「巧妙な」ことを行うことは、通常、価値がありません。通常は、可能な限りクリーンで簡単な方法でコードを作成することをお勧めします。それを行った後、実際にパフォーマンス/スケーラビリティの問題があることがわかった場合 (実際の測定に基づいて)、ボトルネックになっている部分を書き直し/最適化することを選択できます。

ほとんどの場合、コードのクリーン/ストレート/読み取り可能なバージョンが問題なく動作することがわかります。そうでない場合、問題はおそらくあなたが思っていた場所にはありません。

于 2012-04-03T23:40:34.597 に答える
0

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

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

すでにusing(..){}パターンを使用しているので、if(true)ブロックを使用する代わりに、これをサポートするようにコードをリファクタリングします。

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

に:

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

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

試すことができるものがもう1つありますが、メモリマネージャーをプリエンプトするべきではないため、本番コードには絶対にお勧めしません。

GC.Collect();

ブロックを終了するとき。

私はそれが役に立たないと思いますが、スコープと割り当て解除について心配する価値がない理由をあなたに示すかもしれません。

于 2012-04-03T23:41:54.657 に答える