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