2

linq クエリでガベージ コレクションがどのように処理されるかについて質問があります。処理するリクエストのリストが与えられたとします。各リクエストは非常に大量のデータ セットを生成しますが、フィルタが適用されて、リクエストされた各ロードからの重要なデータのみが保持されます。

//Input data
List<request> requests;
IEnumerable<filteredData> results = requests.Select(request => Process(request)).Select(data => Filter(data));

したがって、フィルター処理された各データ項目が要求されるまで、データ項目ごとにクエリが延期されることがわかっているので、それで問題ありません。しかし、その中間のメモリ集約型の部分は、列挙型が完了するまで持続しますか?

私が望んでいるのは、各データ要素がフィルタリングされた段階を通過するとすぐにガベージコレクションできることです。これにより、リスト全体を処理するのに十分なメモリがあることを確認できます。これは事実ですか、それとも、クエリ全体が終了するまで、中央の列挙型がすべてを保持しますか? もしそうなら、これに対処するlinqの方法はありますか?


注: Process() 関数は、メモリ集約型のデータを生成します...それが私が心配していることです

4

3 に答える 3

4

の戻り値が内部で使用される「大きなデータ項目」への参照を保持Process(...)Filter(...)ない限り、そのプロセスで使用されるメモリはルート化されず、各要素が処理された後に GC の候補になります。

これは、それが収集されるという意味ではなく、候補になるということだけです。メモリの負荷が高くなると、GC がそれを収集する可能性が高くなります。

于 2010-07-01T18:42:12.770 に答える
4

ガベージ コレクターは .NET で非常に積極的であり、ループ内であっても参照されなくなった中間オブジェクトをクリーンアップできます。実際、参照されているオブジェクトが二度とアクセスされないことがわかっている場合は、そのオブジェクトをクリーンアップする場合があります。

このコードを実行すると、オブジェクトが非常に迅速にクリーンアップされ、クエリが完了するまでハングアップしないことが示されます (決して実行されません)。

public class MyClass1 { ~MyClass1() { Console.WriteLine("Cleaned up MyClass1"); } }
public class MyClass2 { ~MyClass2() { Console.WriteLine("Cleaned up MyClass2"); } }

public class Program
{
    static IEnumerable<MyClass1> lotsOfObjects()
    {
        while (true)
            yield return new MyClass1();
    }

    static void Main()
    {
        var query = lotsOfObjects().Select(x => foo(x));
        foreach (MyClass2 x in query)
            query.ToString();
    }

    static MyClass2 foo(MyClass1 x)
    {
        return new MyClass2();
    }
}

結果:

MyClass1 をクリーンアップしました
MyClass1 をクリーンアップしました
MyClass1 をクリーンアップしました
MyClass2 のクリーンアップ
MyClass2 のクリーンアップ
MyClass1 をクリーンアップしました
MyClass2 のクリーンアップ
等...
于 2010-07-01T18:47:42.057 に答える
1

投稿したものは実際にはコンパイルされないため (Selectを生成しIEnumerable<T>ますが、に割り当てているため、質問に答えるのは困難です。関数が a を返すList<T>と仮定すると、クエリを呼び出して格納する必要があります)。Filter(data)filteredDataToList()results

requestsすでにデータが入力されていると思います。このリストは、通常のガベージ コレクション規則に従います。あなたが心配しているのはProcess関数の結果だと思います。Filterあなたの機能が何をするのかもわからないので、具体的に何が起こるかは言えません。Filter関数の結果がそのパラメーターへの参照 (つまり、関数の結果) を保持しない限り、 によってProcess作成されたオブジェクトProcessは、クエリの完了時に完全に範囲外になり、通常のガベージ コレクション ルールに従います。 .

これらの規則は、収集の資格を管理することに注意してください。アプリケーションの存続期間中にオブジェクトが収集されることが保証されることはありません。ただし、結果は適格であるため、GC はそれらを収集できます

于 2010-07-01T18:44:42.283 に答える