使用 ELT API 执行分析

跟踪探查器不仅可记录函数的进入和退出,还可维护历史调用关系图。 为了帮助实现此功能,.NET Framework 提供了分析全局静态函数,此函数包含一组称为 enter/leave/tailcall (ELT) API 的相关函数和接口。

在 .NET Framework 4 版 之前,使用 ELT 函数的跟踪探查器所产生的性能开销会随小型托管函数数目的增加而增加。从 .NET Framework 4 开始,您可以使用 ELT 版本 3 (ELT3) API 来提高 ELT 的性能,尤其是在不需要检查参数或返回值时。 性能的改进包含以下几个方面:

  • 对于 ELT 快速路径函数,实时编译代码的大小将减小。

  • 最大限度地减少所需的 ELT 参数的数目,这将减小传递给探查器的参数所需的堆栈空间。

  • 堆栈框架设置和参数检查仅在需要时执行,这将加快执行速度。

  • 在调用新的 ICorProfilerInfo3 方法时对框架和参数信息进行延迟初始化。

ELT3 接口与早期版本的 .NET Framework 中的 ELT 接口(ELT1 和 ELT2)兼容。

.NET Framework 4 在 ELT3 上实现 ELT2 函数,并使用额外的哈希表在客户端 ID 和函数 ID 之间建立映射。 在使用 ELT2 函数时,这将导致产生大量同步开销并会降低分析速度。 严重超载的多处理器计算机的性能会大大降低。不过,将探查器迁移到 ELT3 API 所需的代码更改过程非常简单,并且产生的开销很少,因此建议您采用 ELT3 以实现最佳性能。

ELT3 函数和方法。

ELT3 API 提供了三种类型的成员:

  • 通知函数,此类函数由 CLR 调用以通知探查器正在将控制权传递给目标应用程序中的函数。

  • 注册方法,此类方法由探查器调用以启用快速路径或慢速路径检查方法。

  • 检查方法,此类方法由探查器调用以检索参数或返回值信息。

ELT3 通知函数

从 .NET Framework 4 开始,可以使用六个 ELT3 通知函数中的三个 ELT3 通知函数,来通知探查器正在将控制权传递给目标应用程序(要分析的应用程序)中的函数。 ELT3 通知函数由快速路径函数和慢速路径函数组成:

  • 快速路径函数以 JIT 编译的代码为特征,此代码可直接调入探查器的 ELT 方法中,而无需任何中间代码。

  • 慢速路径函数以 JIT 编译的代码为特征,此代码在最终调入探查器的 ELT 方法中之前会先调入中间项(通常为程序集代码和编译到 CLR DLL 中的 C 代码的组合)中。

下面的三个函数为快速路径函数,它们只需要一个参数、控制权将传递到或返回到的函数的标识符或即将进行尾调用的函数的标识符:

下面的三个函数为慢速路径函数,它们需要两个参数、函数标识符和有关堆栈框架的信息的句柄:

在以上三个函数中,运行时传递给探查器的第二个参数 (eltInfo) 是一个指向在堆栈上分配的 _COR_PRF_ELT_INFO_INTERNAL 结构的不透明指针。 此结构包含由 ELT 程序集帮助器生成的平台特定的句柄。 探查器可以在 ICorProfilerInfo3::GetFunctionEnter3InfoICorProfilerInfo3::GetFunctionLeave3InfoICorProfilerInfo3::GetFunctionTailcall3Info 方法中使用 eltInfo 指针。

ELT3 注册方法

可以使用下面两个 ELT3 注册方法来设置慢速路径 ELT 函数和快速路径 ELT 函数:

在应用程序启动时,必须从探查器的 ICorProfilerCallback::InitializeICorProfilerCallback3::InitializeForAttach 回调中调用上面两个方法之一。 探查器在调用 SetEnterLeaveFunctionHooks3 方法以启用快速路径 ELT3 或调用 SetEnterLeaveFunctionHooks3WithInfo 方法以启用慢速路径 ELT3 之前,必须使用 SetEventMask 注册所需的事件标志。

快速路径 ELT3 挂钩不能与慢速路径 ELT3 挂钩混合,并且 ELT3 挂钩不能与 ELT1 或 ELT2 挂钩一起使用。 如果探查器在调入 SetEnterLeaveFunctionHooks3SetEnterLeaveFunctionHooks3WithInfo 之前,尚未指定需要慢速路径(COR_PRF_ENABLE_FUNCTION_ARGS、COR_PRF_ENABLE_FUNCTION_RETVAL 或 COR_PRF_ENABLE_FRAME_INFO)的适当事件标志,则返回 CORPROF_E_INCONSISTENT_WITH_FLAGS 错误代码以指示失败。

ELT3 检查方法

ELT3 通知函数不提供参数或返回值信息;因此,探查器必须通过调用下列 ICorProfilerInfo3 检查方法之一来显式请求所需信息:

必须通过对探查器的相应慢速路径 ELT3 函数(FunctionEnter3WithInfoFunctionLeave3WithInfoFunctionTailcall3WithInfo)的实现来调用上面的方法,并且探查器必须提供自身从 ELT 通知函数中接收到的同一 eltInfo 值。 请注意,不能通过对探查器的 ELT3 快速路径通知函数(FunctionEnter3FunctionLeave3FunctionTailcall3)的实现来调用 ELT3 检查方法,也不能从任何 ELT1 或 ELT2 通知函数调用这些方法。

请参见

概念

分析概述

其他资源

分析(非托管 API 参考)

非托管 API 参考