编辑:根据工具>给出的评论,也会附加这两种情况的组合。选项>调试> '抑制模块负载的JIT优化' >取消选中(清除此选项,即使在调试模式下也可以进行JIT优化)。可以看出,伪代码可用时生成的机器代码不好! 在快速版本中,代码直接使用CPU Registers ,但在其他版本中,它在每次迭代中从内存加载p1.x和p1.y!我不知道我们怎么能控制这种行为呢!
当我试图测量用于性能测试的代码块的执行时间时,我发现一些让我困惑的不规则性:如果我在实际测量循环之前添加一些(伪)代码块,则总耗用时间会增加在我的2 GHz PC中,一个很大的因素(从120毫秒到220毫秒,即慢约1.8倍!)。 请注意,在实际情况中,这些伪代码是初始化或类似目的所需的一些不同代码。
注意:我在发布模式中构建应用并通过启动而不调试(Ctrl + F5)运行它以确保所有优化都是用于获得最佳效果。
我在这里展示了一个简化的场景示例:
void test()
{
Point p1 = new Point(1, 2);
Point p = p1;
//*** !!! Comment & UnComment the following 2 lines to see difference: ***
p.Offset(p1); p.Offset(p1); p.Offset(p1); p.Offset(p1);
p.Offset(p1); p.Offset(p1); p.Offset(p1); p.Offset(p1);
Stopwatch timer = new Stopwatch();
double dt = -1;
for (int repeat = 1; repeat <= 5; repeat++)
{
p = p1; //here we reset the initial p
timer.Restart();
for (int i = 0; i < 50000000; i++)
{
p.Offset(p1);
}
timer.Stop();
dt = timer.ElapsedMilliseconds;
textBox1.Text += repeat + "] " + dt + ", p: " + p + "\r\n";
Application.DoEvents(); if (this.IsDisposed) break;
}
}
private void button1_Click(object sender, EventArgs e)
{
test();
}
此问题阻止我比较我需要优化的结果。
顺便说一下,这可能与struct
类型(?)有关。
你知道是什么原因以及如何解决它?
编辑(4月4日):我检查过,发现这种行为只发生在struct
类型而非class
类型上。而且正如我们所知,结构通常是Stack中的值类型而不是堆。这可能在这里有作用,但我不知道..
另一个注意事项:我还发现如果我取消选中“优化代码”&#39;项目属性中的选项&gt;构建选项卡,然后代码实际运行得更快!
答案 0 :(得分:1)
有趣的问题。
在这些情况下,汇编程序总是告诉你真相(而不是CIL,它将完全相同!)。可能是你的东西触发了一个边界条件,它改变了最内层循环的汇编程序。
我将代码更改为控制台应用程序,进行了必要的调整(抑制优化标记等),释放模式,放置断点,F5并按下ctrl-alt-d。
注意:我注意到我还必须将测试用例增加10倍才能获得这些时间。正如我预期的那样,时间完全相同。
然而,f.ex可能存在问题。注册分配,所以让我们检查一下。汇编从不撒谎。
案例1汇编程序。
for (int i = 0; i < 500000000; i++)
00007FFE23C74526 xor ecx,ecx
{
p.Offset(p1);
00007FFE23C74528 inc r14d
00007FFE23C7452B add r15d,2
for (int i = 0; i < 500000000; i++)
00007FFE23C7452F inc ecx
00007FFE23C74531 cmp ecx,1DCD6500h
00007FFE23C74537 jl 00007FFE23C74528
}
案例2汇编程序
for (int i = 0; i < 500000000; i++)
00007FFE23C84526 xor ecx,ecx
{
p.Offset(p1);
00007FFE23C84528 inc r14d
00007FFE23C8452B add r15d,2
for (int i = 0; i < 500000000; i++)
00007FFE23C8452F inc ecx
00007FFE23C84531 cmp ecx,1DCD6500h
00007FFE23C84537 jl 00007FFE23C84528
}
<强>结论强>
汇编器输出完全相同,数据也是如此 - 换句话说:内部循环的性能也完全相同。
但是,我已经解释过,请自行检查汇编器输出。如果您有另一个版本的.NET JIT,它应该解释行为。
显然,对于如何测试发出的汇编程序代码存在一些混淆。这是正确的方法:
设置断点,F5,ctrl-alt-d,祈祷断点被击中,否则将其设置在其他地方再试一次。
我对某些评论感到有些惊讶,所以让我回顾一下: