C# 是否可以记录垃圾收集了多少对象?

C# 是否可以记录垃圾收集了多少对象?,c#,C#,我在写高频交易申请。我正试图优化我的应用程序,以尽量减少垃圾收集的对象数量 优化示例:我多次创建HashSet 所以有这样的统计数据是很有趣的:当应用程序完成时,我想知道在执行过程中有多少对象被垃圾收集。所以后面我可以将这个数字与“优化”版本进行比较,以检查“优化”是否有效 如果不可能有这样的统计数据,那么如何测试我的优化是否有效,即是否实际减少了GC使用?在.NET中,您不需要优化收集的对象数量。收集的对象花费的收集时间为零(只要它们不需要最终确定,而且大多数不需要) 您真正应该优化的是活动对

我在写高频交易申请。我正试图优化我的应用程序,以尽量减少垃圾收集的对象数量

优化示例:我多次创建
HashSet

所以有这样的统计数据是很有趣的:当应用程序完成时,我想知道在执行过程中有多少对象被垃圾收集。所以后面我可以将这个数字与“优化”版本进行比较,以检查“优化”是否有效


如果不可能有这样的统计数据,那么如何测试我的优化是否有效,即是否实际减少了GC使用?

在.NET中,您不需要优化收集的对象数量。收集的对象花费的收集时间为零(只要它们不需要最终确定,而且大多数不需要)

您真正应该优化的是活动对象的数量。GC时间与您拥有的GC数量成正比。通过使用各种内存分析工具(包括空闲内存),您可以看到您拥有多少内存

原因是在.NET中,GC通过遍历所有活动对象并简单地通过移动它们使它们彼此相邻来“压缩”它们来工作。死物从来不会以任何方式进入这个区域。他们只是被忽视了。它们最终会被新的分配覆盖


在.NET中,真正的成本是每秒分配数万个对象,它们彼此之间以及与现有活动对象之间存在着深刻的相互关联。例如,您不断添加和删除其节点的树。

如何计算已处理的对象取决于您的实现,但您可以获得
GC通知

垃圾收集通知 这是在.NET3.5SP1中的GC中引入的,用于在GC收集即将开始且GC收集成功完成时生成通知。因此,如果您处于应用程序的资源密集型阶段之间,GC通知将允许您得到GC即将到来的通知,这样您就可以停止当前进程并等待GC完成。这使您的应用程序能够顺利运行

获取GC通知的步骤如下:
  • 调用
    GC.RegisterForFullGCNotification
    以允许在GC接近时发出通知
  • 从应用程序创建一个新线程,并以无限循环的方式开始轮询方法
    GC.WaitForFullGCApproach
    和/或
    GC.WaitForFullGCComplete
    方法
  • 当必须发出通知时,这两种方法都返回
    GCNotificationStatus.successed
  • 在调用线程时,使用
    GC.CancelFullGCNotification
    取消注册通知进程
示例代码实现
公共类主程序
{
公共静态列表lst=新列表();
公共静态void Main(字符串[]args)
{
尝试
{
//注册通知。
GC.登记处发出通知(10,10);
//使用WaitForFullGCProc启动线程。
线程开始滚动=新线程(()=>
{
while(true)
{
//检查是否有接近集合的通知。
GCNotificationStatus s=GC.WaitForFullGCApproach(1000);
如果(s==GCNotificationStatus.successed)
{
//呼叫事件
Console.WriteLine(“GC即将开始”);
GC.Collect();
}
否则如果(s==GCNotificationStatus.cancelled)
{
//取消注册
}
否则如果(s==GCNotificationStatus.Timeout)
{
//发生超时。
}
//检查已完成集合的通知。
s=GC.WaitForFullGCComplete(1000);
如果(s==GCNotificationStatus.successed)
{
//呼叫事件
Console.WriteLine(“GC已结束”);
}
否则如果(s==GCNotificationStatus.cancelled)
{
//取消注册
}
否则如果(s==GCNotificationStatus.Timeout)
{
//发生超时
}
睡眠(500);
}
});
startpolling.Start();
//分配大量内存以对GC施加压力
分配记忆();
//注销进程
GC.CancelFullGCNotification();
}
捕获{}
}
私有静态void AllocateMemory()
{
while(true)
{
char[]bbb=new char[1000];//创建一个包含1000个字符的块
lst.Add(bbb);//添加到列表可确保对象不会超出范围
int计数器=GC.CollectionCount(2);
WriteLine(“GC收集的{0}个对象”,计数器);
}
}
}
参考:

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);

        }
    }

}