我想对 C# 进程进行一些基准测试,但我不想将时间用作我的向量——我想计算在特定方法调用中执行的 IL 指令的数量。这可能吗?
编辑我不是指对方法体的静态分析——我指的是执行的实际指令数——因此,例如,如果方法体包括一个循环,则计数将增加多少指令up the loop * 循环迭代的次数。
我想对 C# 进程进行一些基准测试,但我不想将时间用作我的向量——我想计算在特定方法调用中执行的 IL 指令的数量。这可能吗?
编辑我不是指对方法体的静态分析——我指的是执行的实际指令数——因此,例如,如果方法体包括一个循环,则计数将增加多少指令up the loop * 循环迭代的次数。
我认为不可能做你想做的事。这是因为 IL 仅在 JIT(即时)编译期间使用。当方法运行时,IL 已被翻译成本地机器代码。因此,虽然可以静态计算给定方法/类型/程序集中的 IL 指令数量,但在运行时没有这个概念。
您还没有说明您打算知道将被解释的 IL 指令的数量。鉴于方法体的 IL 计数与机器代码指令的实际数量之间只有松散的相关性,我看不出知道这个数字会实现什么(除了满足您的好奇心)。
好吧,这并不容易。我认为您可以使用在 IL 块之后执行的性能计数器代码来检测您的程序集后编译。例如,如果您有一部分方法将 int 加载到堆栈上,然后在优化代码下使用该 int 执行静态方法,您可以记录 int 加载和调用的计数为 2。
即使使用现有的 IL/托管程序集读/写项目,这也是一项非常艰巨的任务。
当然,您的计数器记录的一些指令可能会在即时编译到 x86/ia64/x64 期间被优化掉,但这是您尝试基于像 IL 这样的抽象语言进行分析时必须承担的风险。
您可以使用具有托管接口的ICorDebug 。在方法的开头设置一个断点,并以编程方式单步执行代码,直到它离开方法。
但是,我不确定该指标会有多大用处,人们倾向于将时间用于此类事情。一些 IL 指令比其他指令更昂贵。
我使用Code Metrics添加到 Reflector
CodeMetrics 加载项分析和计算程序集上的多个代码质量指标。此插件使用 Reflector 来计算经典指标,例如圈复杂度或更直接的指标,例如方法中的局部变量数量。所有结果都可以保存到文件中。
安装插件。选择程序集并加载方法指标。它将向您显示包含 CodeSize、CyclomaticComplexity、# of Instruction 等的网格。
我知道你不想要静态计数。但是,每条弧的静态 IL 计数加上弧一起执行的次数会为您提供 IL 计数。您需要为此检测每条弧线,这需要插入一个计数器。
(弧是一系列指令,你不能跳进或跳出。如果你执行第一条指令,你总是会执行最后一条,等等。)