从.NET程序中获取全局根

Jon*_*rop 3 .net c# f# profiling ants

我最近开始使用ANTS分析工具进行生产工作.除了惊讶于他们的精彩之外,我不禁想知道他们是如何工作的.例如,最有用的功能之一允许您可视化正在运行的程序的全局根,其中包含对不同类型值的引用数.

该工具如何获取该信息?

Chr*_*ich 17

(完全披露:我在Visual Studio Profiler团队,但以下信息是公开的)

您可以通过编写在您要定位的流程内运行的CLR分析器来完成此操作.CLR分析器是C++ COM对象,它们在设置COR_PROFILERCOR_PROFILING_ENABLED环境变量时由运行时实例化(参见此处).有两个主要的CLR分析界面,具体而言,ICorProfilerCallbackICorProfilerInfo. ICorProfilerCallback是什么CLR使用,向您通知您订阅特定事件(模块加载,功能JIT compliation,创建线程,GC事件),同时ICorProfilerInfo可以通过您的分析器来获得有关线程,模块,类型,方法的其他信息,和已加载程序集的元数据.您可以使用此接口获取有关已分配类型的符号信息.

使用您的探查器进程,您可以强制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_GCCOR_PRF_MONITOR_OBJECT_ALLOCATED作为事件标志的一部分来执行此操作ICorProfilingInfo::SetEventMask.

David Broman是CLR分析器的开发人员,他的博客提供了大量有关分析的大量信息,包括所有可能遇到的疯狂陷阱和问题.