-1

私はHFT取引アプリケーションを書いています。ガベージコレクションされるオブジェクトの数を最小限に抑えるために、アプリケーションを最適化しようとしています。

new Instrument(ticker)最適化の例:何度も呼び出す代わりに、HashSet<string /*ticker*/, Instrument>

したがって、このような統計があると興味深いでしょう。アプリケーションが終了したときに、実行中にガベージコレクションされたオブジェクトの数を知りたいのです。したがって、後者では、この数値を「最適化」バージョンと比較して、「最適化」が実際に機能していることを確認できます。

そのような統計を取得できない場合、最適化が機能するかどうか、つまり実際にGCの使用を減らすかどうかをテストするにはどうすればよいですか?

4

2 に答える 2

3

.NET では、収集されるオブジェクトの数を最適化する必要はありません。収集されたオブジェクトの収集時間はゼロです (ファイナライズする必要がなく、ほとんどがファイナライズする必要がない場合)。

本当に最適化する必要があるのは、ライブオブジェクトの数です。GC 時間は、それらの数に比例します。無料のCLR Profilerなど、さまざまなメモリ プロファイリング ツールを使用して、メモリの数を確認できます。

その理由は、.NET では、GC がすべてのライブ オブジェクトを調べて、それらを移動することで単純に「圧縮」して、オブジェクトが互いに隣接するようにすることです。死んだオブジェクトがこれに入ることは決してありません。彼らはただ無視されます。それらは最終的に新しい割り当てによって上書きされます。

.NET で実際にコストがかかるのは、毎秒何万ものオブジェクトを割り当て、それらが相互に、また既存のライブ オブジェクトと深く相互接続されている場合です。ノードを常に追加および削除するツリーなど。

于 2012-06-23T08:04:21.967 に答える
1

破棄されたオブジェクトをカウントする方法は、実装によって異なりますが、を取得できますGC Notifications

ガベージコレクションの通知

これは、.NET 3.5 SP1のGCで導入され、GC収集が開始され、GC収集が正常に完了するたびに通知を生成します。したがって、アプリケーションの非常にリソースを消費するフェーズの間にある場合、GC通知を使用すると、GCが近づいていることを通知できるため、現在のプロセスを停止して、GCが完了するのを待つことができます。これにより、アプリケーションがスムーズに実行されます。

GC通知を取得するための手順:

  • GC.RegisterForFullGCNotificationGCが近づいたときに通知を許可するために呼び出します。
  • GC.WaitForFullGCApproachアプリケーションから新しいスレッドを作成し、メソッドやメソッドへの無限ループで継続的にポーリングを開始しGC.WaitForFullGCCompleteます。
  • GCNotificationStatus.Succeeded通知を発行する必要がある場合は、両方のメソッドが戻ります。
  • 呼び出しスレッドGC.CancelFullGCNotificationで、通知プロセスの登録を解除するために使用します。

サンプルコードの実装

public class MainProgram
{
    public static List<char[]> lst = new List<char[]>();
    public static void Main(string[] args)
    {
        try
        {
            // Register for a notification. 
            GC.RegisterForFullGCNotification(10, 10);

            // Start a thread using WaitForFullGCProc.
            Thread startpolling = new Thread(() =>
            {
                while (true)
                {
                    // Check for a notification of an approaching collection.
                    GCNotificationStatus s = GC.WaitForFullGCApproach(1000);
                    if (s == GCNotificationStatus.Succeeded)
                    {
                        //Call event

                        Console.WriteLine("GC is about to begin");
                        GC.Collect();

                    }
                    else if (s == GCNotificationStatus.Canceled)
                    {
                        // Cancelled the Registration
                    }
                    else if (s == GCNotificationStatus.Timeout)
                    {
                        // Timeout occurred.
                    }

                    // Check for a notification of a completed collection.
                    s = GC.WaitForFullGCComplete(1000);
                    if (s == GCNotificationStatus.Succeeded)
                    {
                        //Call event
                        Console.WriteLine("GC has ended");
                    }
                    else if (s == GCNotificationStatus.Canceled)
                    {
                        //Cancelled the registration
                    }
                    else if (s == GCNotificationStatus.Timeout)
                    {
                        // Timeout occurred
                    }

                    Thread.Sleep(500);
                }


            });
            startpolling.Start();

            //Allocate huge memory to apply pressure on GC
            AllocateMemory();

            // Unregister the process
            GC.CancelFullGCNotification();

        }
        catch { }
    }

    private static void AllocateMemory()
    {
        while (true)
        {

            char[] bbb = new char[1000]; // creates a block of 1000 characters
            lst.Add(bbb);                // Adding to list ensures that the object doesnt gets out of scope   
            int counter = GC.CollectionCount(2);
            Console.WriteLine("GC Collected {0} objects", counter);

        }
    }

}

参照:.NET4.0でのガベージコレクションの通知

于 2012-06-23T08:18:09.327 に答える