我正在编写高频交易应用程序。我正在尝试优化我的应用程序以最小化垃圾收集的对象数量。
优化示例:new Instrument(ticker)我创建而不是多次调用HashSet<string /*ticker*/, Instrument>
所以拥有这样的统计数据会很有趣:当应用程序完成时,我想知道在执行期间有多少对象被垃圾收集。所以后来我可以将此数字与“优化”版本进行比较,以检查“优化”是否确实有效。
如果不可能有这样的统计数据,那么我如何测试我的优化是否有效,即实际上减少了 GC 使用?
我正在编写高频交易应用程序。我正在尝试优化我的应用程序以最小化垃圾收集的对象数量。
优化示例:new Instrument(ticker)我创建而不是多次调用HashSet<string /*ticker*/, Instrument>
所以拥有这样的统计数据会很有趣:当应用程序完成时,我想知道在执行期间有多少对象被垃圾收集。所以后来我可以将此数字与“优化”版本进行比较,以检查“优化”是否确实有效。
如果不可能有这样的统计数据,那么我如何测试我的优化是否有效,即实际上减少了 GC 使用?
在 .NET 中,您不需要优化收集的对象数量。收集的对象花费零收集时间(只要它们不需要最终确定,而且大多数不需要)。
您真正应该优化的是活动对象的数量。GC 时间与您拥有的数量成正比。您可以使用各种内存分析工具(包括免费的CLR Profiler)来查看您拥有多少内存。
原因是在 .NET 中,GC 的工作原理是遍历所有活动对象,并通过移动它们使它们彼此相邻来简单地“压缩”它们。死物永远不会以任何方式进入这里。他们只是被忽略了。它们最终会被新的分配覆盖。
.NET 中真正的成本是当您每秒分配数万个对象时,它们彼此之间以及与现有的活动对象紧密相连。例如你不断添加和删除其节点的树。
如何计算已处置的对象取决于您的实现,但您可以获得GC Notifications.
这在 .NET 3.5 SP1 中引入了 GC,以在 GC 收集即将开始并且 GC 收集成功完成时生成通知。因此,如果您处于应用程序的资源密集型阶段,GC 通知将允许您收到 GC 即将到来的通知,以便您可以停止当前进程并等待 GC 完成。这使您的应用程序能够顺利运行。
GC.RegisterForFullGCNotification以允许通知。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);
}
}
}