【问题标题】:C# Performance Penalty from Adding Stop Watch?添加秒表会导致 C# 性能损失?
【发布时间】:2012-04-13 02:42:38
【问题描述】:

将 C# 秒表添加到对象会导致什么性能损失?

【问题讨论】:

  • 您可以使用秒表对罚分进行基准测试;)
  • 我会使用秒表创建一个微基准来计时 :)
  • 您对秒表计时的结果 所做的操作(将时间记录到文件、Debug.WriteLine 等)可能需要比秒表本身更长的时间。
  • @PopCatalin - 然后添加第三个秒表来对第二个秒表进行基准测试。
  • @SteveWellens Turtles,一路向下。

标签: c# stopwatch


【解决方案1】:
  static void Main(string[] args)
        {
            Worker(1); // jit Warmup
            var stopWatchOfStopwatchStopwatch = System.Diagnostics.Stopwatch.StartNew();
            var stopWatchOfLoop = System.Diagnostics.Stopwatch.StartNew();
            Worker(100000000);
            stopWatchOfLoop.Stop();
            Console.WriteLine("Elapsed of inner SW: " + stopWatchOfLoop.Elapsed.ToString());
            stopWatchOfStopwatchStopwatch.Stop();
            Console.WriteLine("Elapsed of outer SW: " + stopWatchOfStopwatchStopwatch.Elapsed.ToString());

            var stopwatchOfcompareLoop = System.Diagnostics.Stopwatch.StartNew();
            Worker(100000000);
            stopwatchOfcompareLoop.Stop();
            Console.WriteLine("Elapsed of inner SW: " + stopWatchOfLoop.Elapsed.ToString());
        }
        static void Worker(int iterations)
        {
            for (int i = 0; i < iterations; i++)
            {
                Console.WriteLine("bla");
            }
        }

差别不大 - 但这在很大程度上取决于您的绩效目标 :)

【讨论】:

  • 请量化“显着”。这是否意味着几秒钟、几毫秒等?
  • 在我的四核 2.83 GHZ、8 GB 内存和 x64 Win7 上进行 5000 次迭代,大约需要 0.000XXX 秒。
【解决方案2】:

在 C# 编程的上下文中不应该那么重要。如果它被证明很重要,请重新考虑您对秒表和 C# 的需求/使用。

您始终可以尝试自己对其进行基准测试,方法是执行 1000 次,计时,然后将结果除以 1000。很难准确地说出此功能对性能的要求如何,但您可以将其与其他一些简单的操作进行比较看看它是如何关联的。

【讨论】:

  • 我这样做了,平均而言,用 Stopwatch.StartNew 实例化和用 .ElapsedMilliseconds 测量的时间为 0.258 毫秒。这是在相当快的机器上处于本地调试模式。
【解决方案3】:

由于我希望在对象创建池中使用一些计时统计信息来动态优化其性能,因此我需要知道添加Stopwatch 来监控计时是否会对对象创建的性能产生不利影响。我想为典型的对象创建计时(大约 20-30 毫秒)以优化创建它们的任务的超时时间,但前提是添加 Stopwatch 不会显着减慢循环。

所以我编写了这个测试程序来分别计算Start()、Stop() 的创建开销和Stopwatch 的经过时间检索。

using System;
using System.Diagnostics;

namespace SO9925598_Stopwatch_overhead
{
    class Program
    {
        private const int nLoops = 10000;
        private const double nLoopsDouble = nLoops;
        private const int waitTime = 2; //ms

        static void Main(string[] args)
        {
            Stopwatch stopwatchTimingTheTest = new Stopwatch();
            double frequencyConversionFactor = 1000.0 / Convert.ToDouble(Stopwatch.Frequency);  // ms per click
            Stopwatch stopwatchUnderTest;

            // Instantiation
            for (int i = 0; i < nLoops; i++)
            {
                stopwatchTimingTheTest.Start();
                stopwatchUnderTest = new Stopwatch();
                stopwatchTimingTheTest.Stop();
                stopwatchUnderTest = null;
            }
            long elapsed = stopwatchTimingTheTest.ElapsedTicks;
            double overhead = frequencyConversionFactor * (Convert.ToDouble(elapsed) / nLoopsDouble);
            Console.WriteLine($"Creation overhead {overhead} ms per Stopwatch instantiation. (Based on {nLoops} trials).");

            // Further tests can all use the same object
            stopwatchUnderTest = new Stopwatch();

            // Start
            stopwatchTimingTheTest.Reset();
            for (int i = 0; i < nLoops; i++)
            {
                stopwatchTimingTheTest.Start();
                stopwatchUnderTest.Start();
                stopwatchTimingTheTest.Stop();
                stopwatchUnderTest.Stop();
                elapsed = stopwatchUnderTest.ElapsedTicks;
            }
            elapsed = stopwatchTimingTheTest.ElapsedTicks;
            overhead = frequencyConversionFactor * (Convert.ToDouble(elapsed) / nLoopsDouble);
            Console.WriteLine($"Stopwatch.Start() overhead {overhead} ms.");

            // Stop
            stopwatchTimingTheTest.Reset();
            for (int i = 0; i < nLoops; i++)
            {
                stopwatchUnderTest.Start();
                stopwatchTimingTheTest.Start();
                stopwatchUnderTest.Stop();
                stopwatchTimingTheTest.Stop();
                elapsed = stopwatchUnderTest.ElapsedTicks;
            }
            elapsed = stopwatchTimingTheTest.ElapsedTicks;
            overhead = frequencyConversionFactor * (Convert.ToDouble(elapsed) / nLoopsDouble);
            Console.WriteLine($"Stopwatch.Stop() overhead {overhead} ms.");

            // Elapsed ticks
            stopwatchTimingTheTest.Reset();
            for (int i = 0; i < nLoops; i++)
            {
                stopwatchUnderTest.Start();
                stopwatchUnderTest.Stop();
                stopwatchTimingTheTest.Start();
                elapsed = stopwatchUnderTest.ElapsedTicks;
                stopwatchTimingTheTest.Stop();
            }
            elapsed = stopwatchTimingTheTest.ElapsedTicks;
            overhead = frequencyConversionFactor * (Convert.ToDouble(elapsed) / nLoopsDouble);
            Console.WriteLine($"Stopwatch.ElapsedTicks overhead {overhead} ms.");

            // Elapsed ticks
            stopwatchTimingTheTest.Reset();
            for (int i = 0; i < nLoops; i++)
            {
                stopwatchUnderTest.Start();
                stopwatchUnderTest.Stop();
                stopwatchTimingTheTest.Start();
                elapsed = stopwatchUnderTest.ElapsedMilliseconds;
                stopwatchTimingTheTest.Stop();
            }
            elapsed = stopwatchTimingTheTest.ElapsedTicks;
            overhead = frequencyConversionFactor * (Convert.ToDouble(elapsed) / nLoopsDouble);
            Console.WriteLine($"Stopwatch.ElapsedMilliseconds overhead {overhead} ms.");

            Console.WriteLine("Press any key to continue...");
            Console.ReadKey();
        }
    }
}

结果如下:

Creation overhead 0,00011756 ms per Stopwatch instantiation. (Based on 10000 trials).
Stopwatch.Start() overhead 0,000256 ms.
Stopwatch.Stop() overhead 0,00023665 ms.
Stopwatch.ElapsedTicks overhead 0,00010946 ms.
Stopwatch.ElapsedMilliseconds overhead 0,00011758 ms.

时间是基于 10000 个样本的方法每次调用的平均时间。

该程序运行在一台装有 Intel Core i7-8850H CPU、频率为 2.60 GHz 的计算机上,运行 Windows 10 操作系统。

结论:对于我的应用程序,对象创建时间为 20-30 毫秒,Stopwatch 的开销可以忽略不计。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-11-18
    • 2010-12-07
    • 2013-08-30
    • 2011-08-16
    相关资源
    最近更新 更多