2

この簡単なテスト プログラムを想像してみましょう。

static void Main(string[] args)
{
    var length = 30000000;
    var c = new List<object>();
    for (int i = 0; i < length; i++)
    {
        c.Add(new object());
    }
    var start = DateTime.Now;
    GC.Collect();
    GC.WaitForFullGCComplete();
    Console.WriteLine("GC took " + (DateTime.Now - start).TotalMilliseconds + " ms");
    Console.ReadKey();
}

私のコンピューター (Framework 4.0、x64) では、出力は ~1.4 秒ですが、サンプルは ~1GB の RAM を消費します。

質問: ガベージ コレクションを高速化する方法はありますか? ベストプラクティスはありますか? クライアント アプリでの最大 1 GB のメモリ消費量は多いですが、それでもかなり妥当です。しかし、1 秒を超える遅延は、私の状況では受け入れられません。

おそらくサポートされないが、私を助けることができるアイデア:

  • 一部のオブジェクトを無視するように GC に指示できますか?
  • ヒープの一部で GC を実行するために、ヒープを複数の部分に分割できますか? (100ms の 10 倍の遅延が望ましいです。)
4

2 に答える 2

4

場合によっては、かなりの時間収集できない非常に大量のデータを扱う場合、GC が面倒になることがあります。多くの参照があり、さらに悪いことに、GC は実際には収集する可能性が低くなります時間の無駄です!ここでの 1 つのオプションは、値型の配列などの使用を検討することです。ここで重要なのは、200 万の値型の配列が 1 つの参照にすぎないということです。200 万のはコレクションに影響しません。ただし、サブ参照には影響があります (たとえば、行ごとの s など)。しかし、それは役に立ちますstring

sについて言及したのでstring、もう 1 つ確認すべきことは、基になる同じ文字の組み合わせの複数のインスタンスがあるかどうかです。たとえば、データベースまたはファイルからデータをロードすることによって。そこに手動の文字列インターンを適用することを検討してください( -を使用するのではなくstring.Intern、ロードごとの辞書などを使用します)。stringこれにより、収集のためにプレイ中の の数が再び減少します。

最終的な考えとして; データにコレクションが必要な場合は、注意が必要です。たとえば、リストには通常、リストとその下にある配列という 2 つのオブジェクトが追加で含まれます。これに数百万を掛けると、事態がややこしくなり始める可能性があります。私たちの場合、固定バッファーを使用してこれを回避しましたが、これは少し高度なトピックであり、リスト内のアイテム数に予測可能な小さな「上限」がある場合にのみ適用されます。

于 2013-02-11T10:41:53.917 に答える
0

テストは完全に人為的です。実際には、アプリケーションで GC が完了するのを明示的に待つことはありません。

ただし、コードの特定のタイム クリティカルなセクションがある場合は、GC を一時的に無効にすることができます。

于 2013-02-11T10:34:16.270 に答える