测量C#中的执行时间
-
29-09-2019 - |
题
我想衡量执行一件代码,我想知道最好的方法是什么?
选项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");
选项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");
这不仅仅是用于基准测试,实际上它是应用程序的一部分。函数执行的时间是相关数据。但是,它不需要原子或超准确。
哪种选项更适合生产代码,或者其他人使用不同的东西,也许更好?
解决方案
这 Stopwatch
课程专门设计用于测量经过的时间,并且可以使用底层高频硬件计时器(如果在硬件上)(如果在硬件上)提供良好的粒度/准确性。因此,这似乎是最好的选择。
这 Ishighresolution属性 可用于确定是否可用的高分辨率正时。根据文档,该课程为“最佳可用” Win32 API提供了包装器,以进行准确的时机:
具体来说,
Frequency
字段和GetTimestamp
方法可以代替未托管的Win32 APIQueryPerformanceFrequency
和QueryPerformanceCounter
.
关于那些Win32 API [此处]和链接的MSDN文档有详细的背景 2.
高分辨率计时器
计数器是用于编程中用于引用增量变量的一般术语。一些系统包括一个高分辨率性能计数器,可提供高分辨率经过的时间。
如果系统上存在高分辨率性能计数器,则可以使用 查询性能频率函数以每秒计数表示频率。计数的价值取决于处理器。例如,在某些处理器上,计数可能是处理器时钟的周期率。
这 QueryPerformanceCounter 功能检索高分辨率性能计数器的当前值。通过在代码部分的开头和结尾调用此功能,应用程序本质上将计数器用作高分辨率计时器。例如,假设 查询性能频率 表明高分辨率性能计数器的频率为每秒50,000个计数。如果应用程序打电话 QueryPerformanceCounter 在要定时的代码部分之前和之后,计数器值可能分别为1500个计数和3500个计数。这些值表明在执行代码时,.04秒(2000个计数)经过。
其他提示
不只是那个 StopWatch
更准确,但也 DateTime.Now
在某些情况下会产生不正确的结果。
考虑在日光节省时间切换期间发生的情况,例如使用 DateTime.Now
实际上可以给 消极的 回答!
我通常使用 StopWatch
对于这种情况。
从 MSDN 页:
跑表
提供一组方法和属性,您可以使用这些方法和属性来准确测量经过的时间。
在以下文章中,我使用它比较Linq vs plinq的执行时间:
这两个都不会损害表现,因为您说这不是那么重要。秒表似乎更合适 - 您只是从时间中减去时间,而不是另一个日期。日期的东西需要更多的内存和CPU时间来处理。如果您打算在多个地方重复使用,也有一些方法可以使代码清洁器进行清洁。超载 using
想到。我将搜索一个示例。好的,代码从:
http://stevesmithblog.com/blog/great-uses-us-us-usis-sus-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);
}
}
两者都可能符合您的需求,但我想说 StopWatch
. 。为什么?因为它是为了完成您所做的任务。
您已经建立了一个课程来返回当前的日期/时间,因为它可以将其用于定时内容,并且您有一个专门设计用于计时的课程。
在这种情况下,只有在需要毫秒准确性的情况下才真正存在差异(在这种情况下 StopWatch
更准确),但是作为一般主体,如果某种工具专门用于您要寻找的任务,则可以使用更好的任务。
我有一个小课可以做这种事情。它使用秒表类 - C#微型灌注测试.
例如。
var tester = new PerformanceTester(() => SomeMethod());
tester.MeasureExecTime(1000);
Console.Writeline(string.Format("Executed in {0} milliseconds", tester.AverageTime.TotalMilliseconds));
使用以下代码
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();
我将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);
}
}