【问题标题】:disassemble c# code to machine instructions将 c# 代码反汇编为机器指令
【发布时间】:2011-05-14 11:18:52
【问题描述】:

我正在试验编译器的性能。我有一小段代码,只有几个浮点乘法和加法。代码在循环中执行数百万次。我正在尝试用 C++、c#、java、perl、python 编译代码……然后在测量执行时间的同时运行结果。

我对 c# 的性能很不满意。我的 c# 代码比等效的 C++ 或 java 慢大约 60%。我敢肯定,我的实验中一定有一个错误。我想反汇编生成的二进制文件以了解原因。

MSIL 代码有这样的选项吗?可以在机器指令级别(x86 指令,而不是 MSIL 指令)检查 c# JIT 编译器的结果吗?

更新

代码(u、v、g* 为双精度;步数为整数)

stopwatch.Start();
for (int i = 0; i < steps; i++)
{
    double uu = g11 * u + g12 * v;
    v = g21 * u + g22 * v;
    u = uu;
}
stopwatch.Stop();

【问题讨论】:

  • 您确定您的基准测试允许 JIT 首先启动吗?也许你应该展示它。
  • @delnan:你是什么意思?如果 JIT 未编译,则代码无法运行。
  • @Guffa:问题是 JIT 时间是否应该包含在基准测试中。
  • 向我们展示代码并描述您如何运行它的场景。指定测量时间的方式和地点。请注意,您的代码及其任何 calees 在第一次被调用时都会被 JITted,这当然会带来时间损失。在那之后,没有太多理由说明代码应该比直接编译为本机二进制文件的等效代码运行得慢。是的,正是@Guffa 的意思,他只是比我更快(而且更少冗长)..
  • @Guffa, Paul Michalik - 执行时间在 3 到 5 秒之间。

标签: c# performance x86 cil ildasm


【解决方案1】:

在 Visual Studio 中调试您的代码(但在发布模式下编译),在循环中放置一个断点,并在执行在断点处停止时打开反汇编窗口(调试 -> 窗口 -> 反汇编)。

【讨论】:

  • @danatel:它有效,但您可能需要做得更好。重写程序两次运行感兴趣的代码,并在两次运行之间放置一个消息框。当消息框出现时,将调试器附加到进程。请记住,抖动知道您是否在调试。它可以并且确实在调试器运行时生成不太优化的代码,以改善调试体验。如果想知道调试器不运行时抖动在做什么,那么在抖动第一次生成代码后附上调试器。
  • @Eric Lippert:我知道debug more编译和release模式编译有很大区别,但是根据是否附加调试器也有区别吗?
  • @Guffa:可以。 jitter 知道是否附加了调试器,并且可以选择跳过一些使其难以调试的优化。
  • @Eric Lippert:感谢您的建议,但在这种情况下,即使在调试模式下也可以清楚地看到差异。 C++ 代码巧妙地将所有内容保存在 FPU 堆栈中,c# 从 RAM 中推送和拉取变量。我实验的下一步是使用 gcc 和 intel 编译器进行比较。
  • @danatel 在调试版本中(从技术上讲,任何不具有允许优化的属性的程序集)在 jitted 时停止注册变量,因此任何以这种方式查看调试版本都是愚蠢的,除非你感染运行调试构建正常!
【解决方案2】:

Ngen你的程序并反汇编结果。

【讨论】:

    【解决方案3】:

    也许您可以先ngen(编译为本机代码)二进制文件,以避免 JIT 编译。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-04-15
      • 2011-10-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多