秒表奇怪的行为

发布于 2024-09-30 03:31:22 字数 639 浏览 2 评论 0原文

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

输出不一样,你有什么解释吗?

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

The output is not the same, do you have any explanation for that?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

柠檬色的秋千 2024-10-07 03:31:22

抛开诸如在第二个循环中创建大量对象的事实不谈,这很容易导致 fn() 或其他实际上中的垃圾收集在计时时需要更长的时间,在第二种情况下,您也只需要每次迭代所经过的毫秒

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

抛开所有这些不谈,您无论如何都不应该如此频繁地启动和停止计时器 - 它会扰乱您的结果。相反,应在循环之前启动秒表一次,并在循环之后停止。

如果您想去掉循环的开销,只需计时一个循环即可找到开销,然后从包含实际工作的循环所花费的时间中减去该开销。现在事情并不是那么简单,因为现实世界的 CPU 具有各种复杂性(例如缓存未命中),但坦率地说,微基准测试在这方面从来没有特别准确。它应该被用作指南而不是其他任何东西。

Leaving aside things like the fact that you're creating loads of objects in the second loop, which could easily cause garbage collection within fn() or something else to actually make it take longer while timing, you're also just taking the elapsed milliseconds each iteration in the second case.

Suppose each iteration takes 0.1 milliseconds. Your total for the second loop would be 0, because on each iteration it would round down the elapsed time to 0 milliseconds. The first loop keeps track of the elapsed ticks.

Leaving all this aside, you shouldn't be starting and stopping the timer this frequently anyway - it will mess with your results. Instead, start the stopwatch once before the loop, and stop it after the loop.

If you want to take out the overhead of the looping, simply time an empty loop to find the overhead, and subtract that from the time taken with a loop containing actual work. Now it's not really quite that simple, because of the various complexities of real world CPUs - things like cache misses - but microbenchmarking is frankly never particularly accurate in that respect. It should be used as a guide more than anything else.

琉璃梦幻 2024-10-07 03:31:22

因为 StartNew()Stop() 会产生开销。这就是您通常使用 100 或 1000 次迭代进行此类测试的原因:最大限度地减少实际性能测量的性能开销。

Because the StartNew() and Stop() create overhead. That's the reason you normally do these kinds of tests with 100s or 1000s of iterations: to minimize the performance overhead of the actual performance measurements.

你怎么这么可爱啊 2024-10-07 03:31:22

您可能遇到了系统计时器的粒度问题。有时,对一个简单函数进行计时会返回 0 或 10 毫秒。此错误可能会在您的测试中累积起来。

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

You are probably running into the granularity of the system timer. Sometimes timing a trivial function will return 0 or 10 ms. This error could be adding up on your test.

You would probably see a similar result if you ran the first loop twice or the second loop twice as well.

梦太阳 2024-10-07 03:31:22

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

The overhead of the loop is going to be considerably smaller than the overhead of stopping/starting the timer repeatedly and even less so in the case of creating a new one repeatedly. As such, I'd start the timer before the loop and end it after the loop and divide your elapsed time by the number of iterations. It's going to give you far more accurate results.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文