题
我最近开始使用蚂蚁分析工具进行生产工作。除了对他们的敬畏之情感到惊讶之外,我不禁想知道它们是如何工作的。例如,最有用的功能之一使您可以可视化运行程序的全局根,并包含对不同类型值的引用数量。
该工具如何掌握这些信息?
解决方案
(完全披露:我在Visual Studio Profiler团队中,但以下信息是公开的)
您可以通过编写在要定位的过程中运行的CLR Profiler来做到这一点。 CLR剖面仪是C ++ com对象,当运行时实例化时 COR_PROFILER
和 COR_PROFILING_ENABLED
设置了环境变量(请参阅 这里)。有两个主要 CLR分析界面, , 具体来说, ICorProfilerCallback
和 ICorProfilerInfo
. ICorProfilerCallback
是CLR用来向您通知您有关您订阅的特定事件的通知(模块加载,函数jit补充,线程创建,GC事件),而 ICorProfilerInfo
您的参考器可以使用有关已加载的组件的线程,模块,类型,方法和元数据的其他信息。这个界面就是你 可以 用于获取有关分配类型的符号信息。
使用您的Profiler内部处理,您可以强行加入GC ICorProfilerInfo::ForceGC
. 。 GC完成后,您的剖面人员将通过 ICorProfilerCallback2::GarbageCollectionFinished
, ,您将通过 ICorProfilerCallback2::RootReferences2
. 。当您将根参考信息与 ICorProfilerCallback::ObjectReferences
, ,您可以获取.NET应用程序的完整对象参考图。
您可以通过使用 ICorProfilerCallback::ObjectAllocated
回调以确定何时创建单个CLR对象。但是,这可能很昂贵,因为您至少会为每个分配的对象引起至少一个附加功能调用。您可以通过映射CLR分配来跟踪单个对象 ObjectID
到您自己的内部ID。一个 ObjectID
对于给定的对象是短暂的指针,因为它可以随着垃圾收集的发生而改变,这可能会导致对象在压实过程中移动。说明了此过程 这里. 。您可以使用来自 ICorProfilerCallback::MovedReferences
跟踪移动对象。
为了激活上述回调,您需要告诉CLR分析API您对它们感兴趣。您可以通过指定来做到这一点 COR_PRF_MONITOR_GC
和 COR_PRF_MONITOR_OBJECT_ALLOCATED
作为活动标志的一部分 ICorProfilingInfo::SetEventMask
.
David Broman是CLR Profiler的开发人员, 他的博客 总体上有大量有关分析的大量信息,包括您可能遇到的所有疯狂陷阱和问题。
其他提示
像蚂蚁这样的探查者使用CLR本身提出的“分析API”,这完全可以告诉您CLR内部发生了什么。例如,当对象分配,恰当地命名时发生API回调方法 纠纷(). 。同样,当输入方法,创建线程等时,也有一些事件。
原始分析API称为iCorprofilerCallback。后来的版本称为CoreProfilerCallback2和CoreProfilerCallback3。如果您搜索了这些名称,您会发现所需的答案。在Codeproject上,您可以看到一个实用的示例: 创建自定义.NET PROFILER
最后注意:API不能从托管代码(例如C#和vb.net)中使用。它仅可从不受管理的代码(例如C或C ++)获得。因此,C#应用程序无法使用此API来检查其自身的行为和对象。