我需要找到瓶颈,并尽可能准确地测量时间。
以下代码片段是否是衡量性能的最佳方式?
DateTime startTime = DateTime.Now;
// Some execution process
DateTime endTime = DateTime.Now;
TimeSpan totalTimeTaken = endTime.Subtract(startTime);
我需要找到瓶颈,并尽可能准确地测量时间。
以下代码片段是否是衡量性能的最佳方式?
DateTime startTime = DateTime.Now;
// Some execution process
DateTime endTime = DateTime.Now;
TimeSpan totalTimeTaken = endTime.Subtract(startTime);
System.Diagnostics
中)。Stopwatch sw = Stopwatch.StartNew();
PerformWork();
sw.Stop();
Console.WriteLine("Time taken: {0}ms", sw.Elapsed.TotalMilliseconds);
秒表会自动检查高精度计时器的存在。
值得一提的是,由于需要处理时区DST等问题,DateTime.Now
通常比DateTime.UtcNow
慢得多。
DateTime.UtcNow
通常具有15毫秒的分辨率。请参阅John Chapman的博客文章,了解DateTime.Now
精度的概述。
有趣的小知识:如果您的硬件不支持高频计数器,则秒表会退回到DateTime.UtcNow
。您可以查看静态字段Stopwatch.IsHighResolution,以查看秒表是否使用硬件实现高精度。
PerformWork()
很短,那么您可以重复调用它并计算一批调用的平均值。此外,为了避免闪烁效应影响计时测量结果,建议对整个调用批次进行计时,而不是启动/停止 Stopwatch
。 - devgeezer如果您想要快速获得较高精度的结果,我建议使用 Stopwatch。
Stopwatch sw = new Stopwatch();
sw.Start();
// Do Work
sw.Stop();
Console.WriteLine("Elapsed time: {0}", sw.Elapsed.TotalMilliseconds);
如果你需要更加高级的工具,可以考虑使用第三方分析器,例如ANTS。
这篇文章指出首先需要比较三种替代方案,分别是 Stopwatch
、DateTime.Now
和 DateTime.UtcNow
。
文章还展示了在某些情况下(当性能计数器不存在时),Stopwatch 会使用 DateTime.UtcNow + 一些额外处理。因此,在这种情况下,显然 DateTime.UtcNow 是最佳选择(因为其他选项都使用它 + 一些处理)。
然而,事实证明,计数器几乎总是存在的 - 参见与.NET Stopwatch有关的高分辨率性能计数器及其存在的说明?。
这是一个性能图表。请注意 UtcNow 相对于其他替代方案具有多低的性能成本:
X轴是样本数据大小,Y轴是示例的相对时间。
Stopwatch
更擅长提供更高分辨率的时间测量。另一个是它更面向对象的特性。不过,创建一个围绕 UtcNow
的面向对象的包装器并不难。
Stopwatch
是获胜者,尽管优势微弱:https://dotnetfiddle.net/dSg3bN - undefined将您的基准测试代码推入实用程序类/方法非常有用。 StopWatch
类不需要在出现错误时Disposed
或Stopped
。 因此,计时一些操作的最简单代码是:
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);
}
Elapsed.TotalMilliseconds
以获得更高的精度。也可以参考这个问题:https://dev59.com/eWox5IYBdhLWcg3w6odg - nawfal使用System.Diagnostics.Stopwatch类。
Stopwatch sw = new Stopwatch();
sw.Start();
// Do some code.
sw.Stop();
// sw.ElapsedMilliseconds = the time your "do some code" took.
Ditto Stopwatch非常优秀。
关于性能测试,你也应该检查一下你的“//某个执行过程”是否非常短。
还要记住,“//某个执行过程”的第一次运行可能比后续运行慢得多。
通常我会在循环中运行方法1000次或者1000000次,这样可以获得比仅运行一次更准确的数据。
这是正确的方式:
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);
}
}
如果您想了解更多信息,请查看使用秒表替代DataTime以获得准确的性能计数器。
顺便提一下,.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的设计器工具箱中找到它。