Stopwatch sw = new Stopwatch();
for (int i = 0; i < lines.Length; i++)
{
sw.Start();
fn(); //call function
sw.Stop();
}
Console.WriteLine(sw.ElapsedMilliseconds);
long total =0;
for (int i = 0; i < lines.Length; i++)
{
Stopwatch sw = Stopwatch.StartNew();
fn(); //call function
sw.Stop();
total += sw.ElapsedMilliseconds;
}
Console.WriteLine(total);
输出不一样,你对此有任何解释吗?
答案 0 :(得分:8)
撇开诸如你在第二个循环中创建大量对象的事实,这可能很容易导致fn()
内的垃圾收集或实际的其他内容在计时时,你也只是在第二种情况下每次迭代都经过了毫秒。
假设每次迭代需要0.1毫秒。第二个循环的总计将为0,因为在每次迭代时,它会将经过的时间向下舍入为0毫秒。第一个循环跟踪经过的刻度。
将所有这些放在一边,你不应该经常启动和停止计时器 - 它将弄乱你的结果。相反,在循环之前启动一次秒表,并在循环之后停止它。
如果你想要取消循环的开销,只需要一个空循环来查找开销,然后从包含实际工作的循环中减去该开销。现在它真的不是那么简单,因为现实世界的CPU的各种复杂性 - 例如缓存未命中 - 但是微基准标记在这方面坦率地永远不会特别准确。它应该被用作指南而不是其他任何东西。
答案 1 :(得分:4)
因为StartNew()
和Stop()
会产生开销。这就是你通常用100或1000次迭代进行这类测试的原因:最小化实际性能测量的性能开销。
答案 2 :(得分:1)
您可能正在考虑系统计时器的粒度。有时,一个简单的函数计时将返回0或10毫秒。这个错误可能会增加你的测试。
如果你运行第一个循环两次或第二个循环运行两次,你可能会看到类似的结果。
答案 3 :(得分:1)
循环的开销将远远小于重复停止/启动计时器的开销,而在重复创建新计时器的情况下甚至更少。因此,我会在循环之前启动计时器并在循环之后结束它,并将经过的时间除以迭代次数。它会给你更准确的结果。