分析 API 中的代码生成

本主题讨论 Microsoft 中间语言 (MSIL) 代码到本机代码的流,并讨论探查器可以如何控制代码生成。

自动代码生成与手动代码生成

可采用以下两种方法之一将 .NET Framework 程序集中的 MSIL 编译为本机代码:

  • 手动编译:可使用本机映像生成器 (NGen.exe) 工具来创建本机映像。

  • 自动编译:公共语言运行时 (CLR) 可在运行时执行实时 (JIT) 编译。

NGen.exe 和 JIT 编译器都提供了控制代码生成的标志。

程序集加载后,CLR 将首先查找该程序集的本机映像。 如果找不到包含正确的代码生成标志集的本机映像,CLR 将在运行过程中需要程序集中的函数时对这些函数进行 JIT 编译。 即使找到并加载了本机映像,CLR 也可能会对程序集中的某些函数进行 JIT 编译。

探查器对代码生成的控制

探查器使用下表中的标志来控制代码生成。

Flag

效果

COR_PRF_USE_PROFILE_IMAGES

(需要 .NET Framework 2.0 版。)导致执行本机映像搜索,以查找增强型探查器映像 (ngen /profile)。 如果搜索未能找到给定程序集的增强型探查器本机映像,CLR 将改为在需要该程序集中的方法时对这些方法进行 JIT 编译。

对 JIT 编译的代码没有影响。

COR_PRF_DISABLE_INLINING

对本机映像搜索没有影响。

在 JIT 编译中禁用内联。 所有其他优化仍然有效。

COR_PRF_DISABLE_OPTIMIZATIONS

对本机映像搜索没有影响。

在 JIT 编译中,禁用所有优化(包括内联)。

COR_PRF_MONITOR_ENTERLEAVE

导致执行本机映像搜索,以查找增强型探查器映像 (ngen /profile)。

在 JIT 编译中,将 enter/leave 挂钩插入生成的代码。

COR_PRF_MONITOR_CODE_TRANSITIONS

导致执行本机映像搜索,以查找增强型探查器映像 (ngen /profile)。

在 JIT 编译中,在托管/非托管转换点处插入挂钩。

探查器和本机映像

NGen.exe 在创建本机映像时将执行 CLR 通常在运行时执行的许多工作(例如,类加载和函数编译)。 因此,如果在使用 NGen 时完成了工作,在运行时将不会收到下列探查器回调:

增强型探查器本机映像

通过使用 NGen.exe 创建本机映像将可启用一组代码生成标志,利用这些标志可以更轻松地分析映像,如下所示:

性能注意事项

可用于分析 NGen 生成的应用程序的方法取决于两个因素:您需要获取的数据,以及嵌入式分析挂钩对应用程序的影响。

如本主题中前面所述,有两种基本的 NGen 分析方案:

  • 常规本机映像(NGen 生成的映像,不含分析挂钩):这些映像不会导致任何分析系统开销。 但是,类加载/卸载回调将不可用于常规本机映像。 若要处理这种情况,不希望请求增强型探查器本机映像的探查器将必须在遇到 FunctionID 或 ClassID 时收集有关这些 ID 的数据。 例如,当 FunctionID 第一次进行 JIT 编译或从 NGen 生成的映像中加载时,采样探查器将不会遇到 FunctionID,原因是不会为 NGen 生成的常规映像发出类加载/卸载回调。 稍后,当样本显示进程正在函数已编译代码正文内的指令指针 (IP) 处执行时,探查器将会遇到 FunctionID。 在这种情况下,探查器将在采样过程中查询有关函数的信息,或者,它将会记录 FunctionID 或其关联的元数据标记以供在更迟时进行查询。 因此,探查器将只会在最后一刻(当它检测到实际使用的 ID 时)查询有关 FunctionID 或 ClassID 的信息,而不是在之前第一次生成 ID 时查询。

  • 增强型探查器本机映像(NGen 生成的映像,包含嵌入式分析挂钩):这些映像较大,并且它们与常规映像显著不同。 此外,当应用程序包括探查器挂钩时,它的行为可能有所不同。 因此,只有当潜在的性能和行为结果(系统开销)可接受时,您才应使用增强型探查器本机映像。

请参见

概念

分析概述