【发布时间】:2016-07-22 19:05:21
【问题描述】:
编辑:这两种情况的反汇编也根据给定的注释附加在工具 > 选项 > 调试 > 'Suppress JIT optimization on module load' > 取消选中(清除此选项,执行 JIT即使在调试模式下也可以优化)。可以看出,在有伪代码的情况下,生成的机器码并不好! 在快速版本中,代码直接使用 CPU 寄存器,但在其他版本中,它会在每次迭代中从内存中加载 p1.x 和 p1.y!我不知道我们怎么能控制这种行为!
当我试图测量一个代码块的执行时间以进行性能测试时,我发现了一些让我感到困惑的违规行为:如果我在实际测量循环之前添加一些(伪)代码块,则总运行时间会增加一个很大的因素(从 120 毫秒到 220 毫秒,即大约慢 1.8 倍!在我的 2 GHz PC 中)。 请注意,在实际情况下,这些伪代码是初始化或类似目的所需的一些不同代码。
注意: 我在 发布模式 下构建应用程序并通过 Start without Debug (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 types(?) 有关。
你知道是什么原因以及如何解决吗?
编辑(4 月 4 日):我检查并发现这种行为只发生在 struct 类型而不是 class 类型。正如我们所知,结构通常是堆栈而不是堆中的值类型。这可能在这里起作用,但我不知道..
另一个注意事项:我还发现如果我在项目属性>构建选项卡中取消选中“优化代码”选项,那么代码实际上运行得更快!
【问题讨论】:
-
只是为了确定 - 您在 VS 之外使用 Release 构建?
-
我无法重现该问题。在同一运行会话中,我的结果从 100 到 600 不等,无论 2 行是否注释。发布版本,没有调试器。
-
注意:我在
release mode中构建应用程序,然后按Start Without Debug。如果没有这些设置,结果不会被 Visual Studio 优化,并且每次都不同! -
@MarcinJuraszek:该帖子还经过编辑,提到它是在发布模式下构建并通过“无调试启动”命令运行的。
-
已知更长的方法会导致代码效率降低。我相信有人可以针对这种特定情况分析 CIL,但如果您需要一般解释,请参阅 dotnetperls.com/method-size。您可以尝试将初始化代码重构为另一种方法,并检查是否可以提高性能。
标签: c# .net optimization performance-testing jit