c# - DateTime.Now是衡量函数性能的最佳方法吗?




8 Answers

不,这不对。 使用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关于DateTime.Now精度的博文,了解最佳总结。

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

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

下面的代码片段是衡量性能的最佳方式吗?

DateTime startTime = DateTime.Now;

// Some execution process

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



这篇文章说,首先你需要比较三种选择, StopwatchDateTime.NowDateTime.UtcNow

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

但事实证明,计数器几乎总是存在 - 请参阅有关高分辨率性能计数器的说明及其与.NET Stopwatch相关的说明?

这是一个性能图。 请注意UtcNow与其他方案相比性能低下的成本:

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

StopwatchStopwatch的一点是它提供了更高分辨率的时间测量。 另一个是它更多的面向对象的性质。 但是,围绕UtcNow创建OO包装并不难。




stopwatch功能会更好(精度更高)。 我也推荐下载其中一款流行的配置文件,不过( DotTraceANTS是我用过的最多的... DotTrace的免费试用版功能齐全,不像其他的一些其他版本)。




同上秒表,它更好。

关于性能测量,您还应该检查您的“//某个执行过程”是否是一个非常短的过程。

另外请记住,“//某个执行过程”的第一次运行可能会比后续运行慢。

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




@ 肖恩钱伯斯

仅供参考,.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中的设计器工具箱中找到它




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

微软的模式和实践小组在Visual Studio团队系统性能测试指导中有一些指导。




我对这种性能检查做了很少的工作(我倾向于认为“这很慢,使速度更快”),所以我几乎一直都是这样做的。

谷歌确实揭示了很多资源/文章进行性能检查。

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

编辑:

看到StopWatch的会谈..很好! 我学到了一些东西:)

这看起来像一篇好文章




这不够专业:

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配置文件中轻松分隔不同的代码间隔。




Related

c# .net performance datetime timer