首页 文章

DateTime.Now是测量函数性能的最佳方法吗?

提问于
浏览
442

我需要找到一个瓶颈,并且需要尽可能准确地测量时间 .

以下代码段是衡量性能的最佳方法吗?

DateTime startTime = DateTime.Now;

// Some execution process

DateTime endTime = DateTime.Now;
TimeSpan totalTimeTaken = endTime.Subtract(startTime);

15 回答

  • 13

    我在程序中使用的方式是使用StopWatch类,如下所示 .

    Stopwatch sw = new Stopwatch();
    sw.Start();
    
    
    // Critical lines of code
    
    long elapsedMs = sw.Elapsed.TotalMilliseconds;
    
  • 5

    Visual Studio Team System具有一些可能有助于解决此问题的功能 . 基本上,您可以编写单元测试并将它们混合在不同的场景中,以作为压力或负载测试的一部分运行 . 这可能有助于确定最能影响应用程序性能的代码区域 .

    Microsoft的模式和实践组在Visual Studio Team System Performance Testing Guidance中有一些指导 .

  • 52

    如果你想要快速和肮脏的东西,我会建议使用秒表,以获得更高的精确度 .

    Stopwatch sw = new Stopwatch();
    sw.Start();
    // Do Work
    sw.Stop();
    
    Console.WriteLine("Elapsed time: {0}", sw.Elapsed.TotalMilliseconds);
    

    或者,如果您需要更复杂的东西,您应该考虑使用第三方分析器,例如ANTS .

  • 9

    This article说首先你要比较三个选择, StopwatchDateTime.NowDateTime.UtcNow .

    它还表明在某些情况下(当性能计数器不存在时)秒表正在使用DateTime.UtcNow一些额外的处理 . 因为很明显,在那种情况下,DateTime.UtcNow是最好的选择(因为其他使用它进行一些处理)

    然而,事实证明,计数器几乎总是存在 - 见Explanation about high-resolution performance counter and its existence related to .NET Stopwatch? .

    这是一个性能图表 . 请注意UtcNow与替代品相比性能成本如何低:

    Enter image description here

    X轴是样本数据大小,Y轴是示例的相对时间 .

    Stopwatch 更好的一点是它提供了更高分辨率的时间测量 . 另一个是它更具OO性质 . 但是,围绕 UtcNow 创建一个OO包装器并不难 .

  • 7

    这不够专业:

    Stopwatch sw = Stopwatch.StartNew();
    PerformWork();
    sw.Stop();
    
    Console.WriteLine("Time taken: {0}ms", sw.Elapsed.TotalMilliseconds);
    

    更可靠的版本是:

    PerformWork();
    
    int repeat = 1000;
    
    Stopwatch sw = Stopwatch.StartNew();
    for (int i = 0; i < repeat; i++)
    {
       PerformWork();
    }
    
    sw.Stop();
    
    Console.WriteLine("Time taken: {0}ms", sw.Elapsed.TotalMilliseconds / repeat);
    

    在我的实际代码中,我将添加GC.Collect调用以将托管堆更改为已知状态,并添加Sleep调用,以便可以在ETW配置文件中轻松分隔不同的代码间隔 .

  • 88

    我刚刚在Vance Morrison的博客中发现了一篇关于a CodeTimer class的帖子,他写道,这使得使用 StopWatch 变得更容易并且做了一些整洁的东西 .

  • 16

    我做了很少的这种性能检查(我倾向于认为“这很慢,让它更快”)所以我几乎总是这样做 .

    谷歌确实揭示了许多用于性能检查的资源/文章 .

    许多人提到使用pinvoke获取性能信息 . 我研究的很多材料都只提到使用perfmon ..

    编辑:

    看过StopWatch的谈话..很好!我学到了东西:)

    This looks like a good article

  • 10

    stopwatch功能会更好(精度更高) . 我还建议只下载一个流行的分析器,但是DotTraceANTS是我和其他人一样的东西 .

  • 4

    不,这不对 . 使用Stopwatch(在 System.Diagnostics 中)

    Stopwatch sw = Stopwatch.StartNew();
    PerformWork();
    sw.Stop();
    
    Console.WriteLine("Time taken: {0}ms", sw.Elapsed.TotalMilliseconds);
    

    秒表会自动检查是否存在高精度计时器 .

    值得一提的是 DateTime.Now 通常比 DateTime.UtcNow 慢得多,因为必须使用时区,DST等工作 .

    DateTime.UtcNow通常具有15毫秒的分辨率 . 有关精彩摘要,请参阅John Chapman's blog post关于 DateTime.Now precision .

    有趣的琐事:如果你的硬件不支持高频计数器,秒表会回落 DateTime.UtcNow . 您可以通过查看静态字段Stopwatch.IsHighResolution来检查秒表是否使用硬件来实现高精度 .

  • 4

    @ Sean Chambers

    仅供参考,.NET Timer类不用于诊断,它以预设的间隔生成事件,如下所示(来自MSDN):

    System.Timers.Timer aTimer;
    public static void Main()
    {
        // Create a timer with a ten second interval.
        aTimer = new System.Timers.Timer(10000);
    
        // Hook up the Elapsed event for the timer.
        aTimer.Elapsed += new ElapsedEventHandler(OnTimedEvent);
    
        // Set the Interval to 2 seconds (2000 milliseconds).
        aTimer.Interval = 2000;
        aTimer.Enabled = true;
    
        Console.WriteLine("Press the Enter key to exit the program.");
        Console.ReadLine();
    }
    
    // Specify what you want to happen when the Elapsed event is 
    // raised.
    private static void OnTimedEvent(object source, ElapsedEventArgs e)
    {
        Console.WriteLine("The Elapsed event was raised at {0}", e.SignalTime);
    }
    

    所以这真的无法帮助你知道事情花了多长时间,只是已经过了一段时间 .

    计时器也作为System.Windows.Forms中的控件公开...你可以在VS05 / VS08的设计器工具箱中找到它

  • 18

    将基准测试代码推送到实用程序类/方法中非常有用 . StopWatch 类在出错时不需要 DisposedStopped . 所以,最简单的代码来计算时间

    public partial class With
    {
        public static long Benchmark(Action action)
        {
            var stopwatch = Stopwatch.StartNew();
            action();
            stopwatch.Stop();
            return stopwatch.ElapsedMilliseconds;
        }
    }
    

    样本调用代码

    public void Execute(Action action)
    {
        var time = With.Benchmark(action);
        log.DebugFormat(“Did action in {0} ms.”, time);
    }
    

    这是扩展方法版本

    public static class Extensions
    {
        public static long Benchmark(this Action action)
        {
            return With.Benchmark(action);
        }
    }
    

    并调用代码示例

    public void Execute(Action action)
    {
        var time = action.Benchmark()
        log.DebugFormat(“Did action in {0} ms.”, time);
    }
    
  • 613

    使用System.Diagnostics.Stopwatch类 .

    Stopwatch sw = new Stopwatch();
    sw.Start();
    
    // Do some code.
    
    sw.Stop();
    
    // sw.ElapsedMilliseconds = the time your "do some code" took.
    
  • 6

    Ditto秒表,它的方式更好 .

    关于绩效衡量,您还应该检查您的“//一些执行流程”是否是一个非常短的过程 .

    还要记住,“// Some Execution Process”的第一次运行可能比后续运行慢 .

    我通常通过在循环中运行1000次或1000000次来测试方法,并且我获得比运行一次更准确的数据 .

  • 6

    这些都是衡量时间的好方法,但这只是找到瓶颈的一种非常间接的方式 .

    在线程中找到瓶颈的最直接方法是让它运行,当它做任何让你等待的事情时,用暂停或中断键停止它 . 这样做几次 . 如果您的瓶颈占用X%的时间,则X%是您在每个快照的行为中捕获它的概率 .

    Here's a more complete explanation of how and why it works

  • 4

    这是正确的方法:

    using System;
    using System.Diagnostics;
    
    class Program
    {
        public static void Main()
        {
            Stopwatch stopWatch = Stopwatch.StartNew();
    
                // some other code
    
            stopWatch.Stop();
    
            // this not correct to get full timer resolution
            Console.WriteLine("{0} ms", stopWatch.ElapsedMilliseconds);
    
            // Correct way to get accurate high precision timing
            Console.WriteLine("{0} ms", stopWatch.Elapsed.TotalMilliseconds);
        }
    }
    

    欲了解更多信息,请浏览Use Stopwatch instead of DataTime for getting accurate performance counter .

相关问题