简体   繁体   English

用C#衡量执行时间

[英]Measure execution time in C#

I want to measure the execution of a piece of code and I'm wondering what the best method to do this is? 我想测量一段代码的执行情况,我想知道最好的方法是什么?

Option 1: 选项1:

DateTime StartTime = DateTime.Now;

//Code

TimeSpan ts = DateTime.Now.Subtract(StartTime);
string elapsedTime = String.Format("{0:00}:{1:00}:{2:00}.{3:00}",
        ts.Hours, ts.Minutes, ts.Seconds,
        ts.Milliseconds / 10);
Console.WriteLine(elapsedTime, "RunTime");

Option 2: using System.Diagnostics; 选项2:使用System.Diagnostics;

    Stopwatch stopWatch = new Stopwatch();
    stopWatch.Start();

    //Code

    stopWatch.Stop();
    // Get the elapsed time as a TimeSpan value.
    TimeSpan ts = stopWatch.Elapsed;

    // Format and display the TimeSpan value.
    string elapsedTime = String.Format("{0:00}:{1:00}:{2:00}.{3:00}",
        ts.Hours, ts.Minutes, ts.Seconds,
        ts.Milliseconds / 10);
    Console.WriteLine(elapsedTime, "RunTime");

This isn't simply for benchmarking, its actually part of the application. 这不仅仅是基准测试,它实际上是应用程序的一部分。 The time the function takes to execute is relevant data. 函数执行的时间是相关数据。 It doesn't however need to be atomic or hyper-accurate. 然而,它不需要是原子的或超精确的。

Which option is better for production code, or does anybody else use something different and perhaps better? 哪个选项更适合生产代码,还是其他人使用不同的东西,也许更好?

The Stopwatch class is specifically designed to measure elapsed time and may (if available on your hardware) provide good granularity/accuracy using an underlying high-frequency hardware timer. Stopwatch类专门用于测量经过的时间,并且可能(如果在您的硬件上可用)使用底层高频硬件计时器提供良好的粒度/准确度。 So this seem the best choice. 所以这似乎是最好的选择。

The IsHighResolution property can be used to determine whether high resolution timing is available. IsHighResolution属性可用于确定高分辨率计时是否可用。 Per the documentation, this class offers a wrapper on the 'best available' Win32 APIs for accurate timing: 根据文档,该类提供了“最佳可用”Win32 API的包装器,以实现准确的计时:

Specifically, the Frequency field and GetTimestamp method can be used in place of the unmanaged Win32 APIs QueryPerformanceFrequency and QueryPerformanceCounter . 具体来说,可以使用Frequency字段和GetTimestamp方法代替非托管Win32 API QueryPerformanceFrequencyQueryPerformanceCounter

There is detailed background on those Win32 APIs [here] and in linked MSDN docs 2 . 有关Win32 API [此处]和链接的MSDN文档2的详细背景信息。

High-Resolution Timer 高分辨率计时器

A counter is a general term used in programming to refer to an incrementing variable. 计数器是编程中用于指代递增变量的通用术语。 Some systems include a high-resolution performance counter that provides high-resolution elapsed times. 某些系统包括一个高分辨率性能计数器,可提供高分辨率的经过时间。

If a high-resolution performance counter exists on the system, you can use the QueryPerformanceFrequency function to express the frequency, in counts per second. 如果系统上存在高分辨率性能计数器,则可以使用QueryPerformanceFrequency函数以每秒计数表示频率。 The value of the count is processor dependent. 计数值取决于处理器。 On some processors, for example, the count might be the cycle rate of the processor clock. 例如,在某些处理器上,计数可能是处理器时钟的循环速率。

The QueryPerformanceCounter function retrieves the current value of the high-resolution performance counter. QueryPerformanceCounter函数检索高分辨率性能计数器的当前值。 By calling this function at the beginning and end of a section of code, an application essentially uses the counter as a high-resolution timer. 通过在代码段的开头和结尾调用此函数,应用程序实际上将计数器用作高分辨率计时器。 For example, suppose that QueryPerformanceFrequency indicates that the frequency of the high-resolution performance counter is 50,000 counts per second. 例如,假设QueryPerformanceFrequency指示高分辨率性能计数器的频率为每秒50,000个计数。 If the application calls QueryPerformanceCounter immediately before and immediately after the section of code to be timed, the counter values might be 1500 counts and 3500 counts, respectively. 如果应用程序在要定时的代码段之前和之后立即调用QueryPerformanceCounter ,则计数器值可能分别为1500计数和3500计数。 These values would indicate that .04 seconds (2000 counts) elapsed while the code executed. 这些值表示执行代码时经过了0.04秒(2000个计数)。

It's not just that StopWatch is more accurate, but also that DateTime.Now will give incorrect results in some circumstances. 这不仅仅是StopWatch更准确,而且DateTime.Now在某些情况下会给出错误的结果。

Consider what happens during a daylight saving time switch-over, for example — using DateTime.Now can actually give a negative answer! 考虑在夏令时切换期间发生的事情,例如 - 使用DateTime.Now实际上可以给出否定答案!

I generally use StopWatch for this kind of situation. 我通常在这种情况下使用StopWatch

From MSDN page: 来自MSDN页面:

StopWatch 跑表

Provides a set of methods and properties that you can use to accurately measure elapsed time. 提供一组方法和属性,可用于准确测量经过的时间。

In the following post I use it to compare the execution time of LINQ vs PLINQ: 在以下文章中,我用它来比较LINQ与PLINQ的执行时间:

Parallel LINQ (PLINQ) with Visual Studio 2010 与Visual Studio 2010并行LINQ(PLINQ)

Neither will hurt the performance, because you say it is not that critical. 也不会损害性能,因为你说这不是那么重要。 StopWatch seems more appropriate - you are only subtracting time from time and not one date from another. StopWatch似乎更合适 - 你只是从时间减去时间而不是从另一个减去一个日期。 Date stuff takes a tad more memory and CPU time to deal with. 日期内容需要更多的内存和CPU时间来处理。 There are also ways to make the code cleaner, in case you plan on reusing it in several places. 如果您计划在多个地方重复使用,还有一些方法可以使代码更清晰。 Overloading using comes to mind. 重载using浮现在脑海中。 I will search for an example. 我会搜索一个例子。 Ok, code stolen from: 好的,代码被盗:

http://stevesmithblog.com/blog/great-uses-of-using-statement-in-c/ http://stevesmithblog.com/blog/great-uses-of-using-statement-in-c/

public class ConsoleAutoStopWatch : IDisposable
{
    private readonly Stopwatch _stopWatch;

    public ConsoleAutoStopWatch()
    {
        _stopWatch = new Stopwatch();
        _stopWatch.Start();
    }

    public void Dispose()
    {
        _stopWatch.Stop();
        TimeSpan ts = _stopWatch.Elapsed;

        string elapsedTime = String.Format("{0:00}:{1:00}:{2:00}.{3:00}",
                                           ts.Hours, ts.Minutes, ts.Seconds,
                                           ts.Milliseconds / 10);
        Console.WriteLine(elapsedTime, "RunTime");
    }
}

private static void UsingStopWatchUsage()
{
    Console.WriteLine("ConsoleAutoStopWatch Used: ");
    using (new ConsoleAutoStopWatch())
    {
        Thread.Sleep(3000);
    }
}

Both will likely fit your needs just fine, but I would say use StopWatch . 两者都可能很好地满足您的需求,但我会说使用StopWatch Why? 为什么? Cause it's meant for the task you're doing. 因为它意味着你正在做的任务。

You've got one class that's built to return the current date/time, which as it happens can be used for timing things, and you've got one class specifically designed for timing things. 你有一个专门用来返回当前日期/时间的类,它可以用来计时,你有一个专门用于计时的课程。

In this case the differences only really exist if you need millisecond accuracy (In which case StopWatch is more accurate), but as a general principal if a tool exists specifically for the task you're looking for then it's the better one to use. 在这种情况下,如果您需要毫秒精度(在这种情况下StopWatch更准确),差异才真正存在,但作为一个通用原则,如果一个工具专门用于您正在寻找的任务,那么它是更好的使用。

I have a little class to do this sort of thing ad hoc. 我有一个小班,专门做这类事。 It uses the stopwatch class - c# micro perfomance testing . 它使用秒表类 - c#微性能测试

eg. 例如。

var tester = new PerformanceTester(() => SomeMethod());
tester.MeasureExecTime(1000);
Console.Writeline(string.Format("Executed in {0} milliseconds", tester.AverageTime.TotalMilliseconds));

I took Hamish's answer simplified it and made it a bit more general in case you need to log to somewhere else: 我把Hamish的答案简化了一下,如果你需要登录到其他地方,它会更加通用:

public class AutoStopWatch : Stopwatch, IDisposable {

    public AutoStopWatch() {
        Start();
    }

    public virtual void Dispose() {
        Stop();
    }
}

 public class AutoStopWatchConsole : AutoStopWatch {

    private readonly string prefix;

    public AutoStopWatchConsole(string prefix = "") {
        this.prefix = prefix;
    }

    public override void Dispose() {
        base.Dispose();

        string format = Elapsed.Days > 0 ? "{0} days " : "";
        format += "{1:00}:{2:00}:{3:00}.{4:00}";

        Console.WriteLine(prefix + " " + format.Format(Elapsed.Days, Elapsed.Hours, Elapsed.Minutes, Elapsed.Seconds, Elapsed.Milliseconds / 10));
    }
}

private static void Usage() {

    Console.WriteLine("AutoStopWatch Used: ");
    using (var sw = new AutoStopWatch()) {
        Thread.Sleep(3000);

        Console.WriteLine(sw.Elapsed.ToString("h'h 'm'm 's's'"));
    }

    Console.WriteLine("AutoStopWatchConsole Used: ");
    using (var sw = new AutoStopWatchConsole()) {
        Thread.Sleep(3000);
    }

}

Use below code 使用以下代码

DateTime dExecutionTime;
dExecutionTime = DateTime.Now;
      TimeSpan span = DateTime.Now.Subtract(dExecutionTime);
                  lblExecutinTime.Text = "total time taken " +   Math.Round(span.TotalMinutes,2) + " minutes .   >>---> " + DateTime.Now.ToShortTimeString();

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM