追踪 .NET 4.0 引发的 GC 的来源
我正在使用 PerfMonitor.exe ( http://bcl.codeplex.com/wikipage?title=PerfMonitor )来跟踪使用一些第三方库(其中一些是本机代码)的 .NET 4.0 应用程序的一些 .NET 性能问题。
当我运行 Perfmonitor GCTime 报告时,它会列出各个 GC 并以多种方式对它们进行分类。报告中的一栏称为“原因”。一些 GC 的 Reason=“Induced”,另一些 GC 的 Reason=“SmallAlloc”。
我假设标记为“SmallAlloc”的 GC 是由常规分配(New Object())引起的,标记为“Induced”的 GC 是由调用“System.GC.Collect”引起的。如果您认为我做出了错误的假设,请告诉我。
我试图找到调用 System.GC.Collect 的代码,但没有成功。我使用 MSVS 2010 Professional 在 System.GC.Collect 中设置了一个断点,并通过编写一个包含对 System.GC.Collect 的调用的简单测试函数来确保该断点有效。但是,我正在调整的应用程序不会在该断点处中断,这使我相信没有任何代码调用 System.GC.Collect。
我想也许有本机代码通过直接调用 mscorwks.dll 中的本机函数来引发 GC,并绕过 System.GC.Collect。我看到 System.GC.Collect 在 mscorwks 中的 JitHelpers.cpp 中调用 _Collect。有没有办法在该函数中设置断点?
I'm using PerfMonitor.exe ( http://bcl.codeplex.com/wikipage?title=PerfMonitor ) to track down some .NET performance issues of a .NET 4.0 app that uses some third party libraries some of which are native code.
When I run the Perfmonitor GCTime report, it lists the individual GC's and classifies them in several ways. One column in the report is called "Reason". Some GC's have Reason="Induced" and others have Reason="SmallAlloc".
I assume that the GCs labelled "SmallAlloc" are caused by regular allocation (New Object()) and GCs labelled "Induced" are caused by a call to "System.GC.Collect". Please let me know if you think I've made an incorrect assumption.
I'm trying to find the code that is calling System.GC.Collect but I've been unsuccessful. Using MSVS 2010 Professional, I set up a breakpoint in System.GC.Collect, and made sure that this breakpoint works by writing a simple test function that contains a call to System.GC.Collect. However, my app that I'm tuning does not break at that breakpoint which makes me believe that none of the code calls System.GC.Collect.
I'm thinking maybe there is native code that induces the GC by calling a native function in mscorwks.dll directly and bypasses System.GC.Collect. I see that System.GC.Collect calls _Collect in JitHelpers.cpp which is in mscorwks. Is there a way to set a breakpoint in that function?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
我仔细查看了 PerfMonitor.exe 的输出。我不确定每个标记为“诱导”的 GC 实际上是由 System.GC.Collect 诱导的。似乎所有 Gen 1 GC 都标记为 Reason="Induced",而所有 Gen 0 GC 都标记为 Reason="SmallAlloc"。 Gen2 GC 标记为 Reason="LowMemory"。
有一个性能计数器用于跟踪 .NET 引发的 GC。我监控了该性能计数器,它在我的进程中没有显示任何诱导的 GC。所以我得出结论是 Perfmonitor.exe 误导了我。
I looked a little closer at the output of PerfMonitor.exe. I'm not sure that every GC labelled "Induced" is actually induced by System.GC.Collect. It appears that all Gen 1 GC's are labelled Reason="Induced", while all Gen 0 GC's are labelled Reason="SmallAlloc". Gen2 GCs are labelled Reason="LowMemory".
There is a performance counter for tracking .NET Induced GCs. I monitored that performance counter and it does not show any induced GC's in my process. So I conclude that Perfmonitor.exe has misled me.
看来您已经推断出 GC.Collect() 不是您的问题,但作为参考,我过去成功地在 GC.Collect 中放置了断点,当时我可以从诱导 GC 计数器中看到肯定存在诱导 GC正在发生。
您可以将断点位置设置为 System.GC.Collect 并尝试一下。使用这种策略,我有时可以成功设置框架断点,有时则不能。我不知道这是因为方法/属性调用被优化了,还是其他原因。但它总是值得一试。您可能需要执行一些操作,例如在“工具”->“选项”->“调试”部分中禁用“仅我的代码”。
It seems you've deduced that GC.Collect() is not your issue here, but for reference, I have succeeded in putting breakpoints in GC.Collect in the past when I could see from the Induced GC counter that there were definitely induced GCs happening.
You can set the breakpoint location to System.GC.Collect and give it a go. Using this tactic, I'm sometimes successful in setting Framework breakpoints, sometimes not. I don't know if it's because methods/property calls are optimised out, or some other reason. But it's always worth a try. You may have to do things such as disabling "Just My Code" in the Tools->Options->Debug section.