我想衡量一段代码的执行情况,我想知道最好的方法是什么?
选项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");
这不仅仅是基准测试,它实际上是应用程序的一部分。函数执行的时间是相关数据。然而,它不需要是原子的或超精确的。
哪个选项更适合生产代码,还是其他人使用不同的东西,也许更好?
答案 0 :(得分:28)
Stopwatch
类专门用于测量经过的时间,并且可能(如果在您的硬件上可用)使用底层高频硬件计时器提供良好的粒度/准确度。所以这似乎是最好的选择。
IsHighResolution property可用于确定高分辨率计时是否可用。根据文档,该类提供了“最佳可用”Win32 API的包装器,以实现精确计时:
具体来说,
Frequency
字段和 可以使用GetTimestamp
方法 非托管Win32 API的位置QueryPerformanceFrequency
和QueryPerformanceCounter
。
有关Win32 API [此处]和链接的MSDN文档2的详细背景信息。
高分辨率计时器
计数器是用于的通用术语 编程指的是 递增变量。一些系统 包括高分辨率的表现 提供高分辨率的计数器 经过的时间。
如果是高分辨率的表现 计数器存在于系统上,你可以 使用 QueryPerformanceFrequency 用于表达频率的函数 每秒计数。的价值 count取决于处理器。一些 处理器,例如,计数 可能是的循环率 处理器时钟。
QueryPerformanceCounter 函数 检索的当前值 高分辨率性能计数器。 通过调用此函数 一节的开头和结尾 代码,应用程序本质上使用 计数器作为高分辨率 计时器。例如,假设 QueryPerformanceFrequency 表示 那个频率 高分辨率性能计数器是 每秒50,000计数。如果 应用程序调用 立即 QueryPerformanceCounter 之前和之后 要定时的代码段, 计数器值可能是1500计数 分别为3500和3500。这些 值表示.04秒 代码时已经过了(2000次) 执行。
答案 1 :(得分:13)
StopWatch
不仅更准确,而且在某些情况下DateTime.Now
会给出错误的结果。
考虑在夏令时切换期间发生的事情,例如 - 使用DateTime.Now
实际上可以给出否定答案!
答案 2 :(得分:6)
我通常会在这种情况下使用StopWatch
。
来自MSDN页面:
<强>秒表强>
提供一组方法和 您可以使用的属性 准确地测量经过的时间。
在下面的文章中,我用它来比较LINQ与PLINQ的执行时间:
答案 3 :(得分:5)
两者都不会影响性能,因为你说这不是那么重要。 StopWatch似乎更合适 - 你只是从时间减去时间而不是从另一个减去一个日期。日期内容需要更多的内存和CPU时间来处理。如果您计划在多个地方重复使用,还有一些方法可以使代码更清晰。我想到了重载using
。我会搜索一个例子。好的,代码被盗:
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);
}
}
答案 4 :(得分:1)
两者都可能适合您的需求,但我会说使用StopWatch
。为什么?因为它意味着你正在做的任务。
你有一个专门用来返回当前日期/时间的课程,它可以用来计时,你有一个专门用于计时的课程。
在这种情况下,如果你需要毫秒精度(在这种情况下StopWatch
更准确),差异才真正存在,但作为一个通用原则,如果一个工具专门用于你正在寻找的任务,那么它是更好的一个。
答案 5 :(得分:1)
我有一个小班,专门做这类事。它使用秒表类 - c# micro perfomance testing。
例如
var tester = new PerformanceTester(() => SomeMethod());
tester.MeasureExecTime(1000);
Console.Writeline(string.Format("Executed in {0} milliseconds", tester.AverageTime.TotalMilliseconds));
答案 6 :(得分:0)
使用以下代码
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();
答案 7 :(得分:0)
我把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);
}
}