秒表奇怪的行为

时间:2010-11-03 15:35:17

标签: c# stopwatch

            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);

输出不一样,你对此有任何解释吗?

4 个答案:

答案 0 :(得分:8)

撇开诸如你在第二个循环中创建大量对象的事实,这可能很容易导致fn()内的垃圾收集或实际的其他内容在计时时,你也只是在第二种情况下每次迭代都经过了毫秒

假设每次迭代需要0.1毫秒。第二个循环的总计将为0,因为在每次迭代时,它会将经过的时间向下舍入为0毫秒。第一个循环跟踪经过的刻度

将所有这些放在一边,你不应该经常启动和停止计时器 - 它弄乱你的结果。相反,在循环之前启动一次秒表,并在循环之后停止它。

如果你想要取消循环的开销,只需要一个循环来查找开销,然后从包含实际工作的循环中减去该开销。现在它真的不是那么简单,因为现实世界的CPU的各种复杂性 - 例如缓存未命中 - 但是微基准标记在这方面坦率地永远不会特别准确。它应该被用作指南而不是其他任何东西。

答案 1 :(得分:4)

因为StartNew()Stop()会产生开销。这就是你通常用100或1000次迭代进行这类测试的原因:最小化实际性能测量的性能开销。

答案 2 :(得分:1)

您可能正在考虑系统计时器的粒度。有时,一个简单的函数计时将返回0或10毫秒。这个错误可能会增加你的测试。

如果你运行第一个循环两次或第二个循环运行两次,你可能会看到类似的结果。

答案 3 :(得分:1)

循环的开销将远远小于重复停止/启动计时器的开销,而在重复创建新计时器的情况下甚至更少。因此,我会在循环之前启动计时器并在循环之后结束它,并将经过的时间除以迭代次数。它会给你更准确的结果。