DateTime。现在衡量函数性能的最佳方法是什么?

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

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

DateTime startTime = DateTime.Now;


// Some execution process


DateTime endTime = DateTime.Now;
TimeSpan totalTimeTaken = endTime.Subtract(startTime);
72550 次浏览

秒表功能将更好(更高的精度)。我还建议下载一个流行的分析器,尽管(DotTrace蚂蚁是我用得最多的…免费试用的DotTrace功能齐全,不像其他一些唠叨)。

不,不是。使用秒表(在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毫秒。有关DateTime.Now精度的详细摘要,请参阅约翰查普曼的博客文章

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

使用System.Diagnostics.Stopwatch类。

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


// Do some code.


sw.Stop();


// sw.ElapsedMilliseconds = the time your "do some code" took.

我很少做这种性能检查(我倾向于认为“这很慢,让它快一点”),所以我基本上都是这样做的。

谷歌确实显示了许多用于性能检查的资源/文章。

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

编辑:

看过秒表的对话..好了!我学到了一些东西:)

这篇文章看起来不错

如果你想要一些快速和肮脏的东西,我建议使用秒表代替更大程度的精度。

Stopwatch sw = new Stopwatch();
sw.Start();
// Do Work
sw.Stop();


Console.WriteLine("Elapsed time: {0}", sw.Elapsed.TotalMilliseconds);

或者,如果你需要一些更复杂的东西,你可能应该考虑使用第三方分析器,如蚂蚁

@肖恩·钱伯斯

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

秒表也一样,它好多了。

关于性能度量,你还应该检查你的“// Some Execution Process”是否是一个非常短的过程。

还要记住,“// Some Execution Process”的第一次运行可能比后续运行慢得多。

我通常通过在循环中运行1000次或100万次来测试一个方法,我得到的数据比运行一次要准确得多。

将基准测试代码放入实用程序类/方法中是很有用的。StopWatch类在出错时不需要是DisposedStopped。因此,时间 some 行动最简单的代码是

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);
}

我刚刚在Vance Morrison的博客上找到了一篇关于CodeTimer类的文章,他写的这篇文章使StopWatch的使用更容易,并在旁边做了一些整洁的事情。

Visual Studio团队系统有一些特性可以帮助解决这个问题。从本质上讲,您可以编写单元测试,并将它们混合在不同的场景中,作为压力或负载测试的一部分对您的软件运行。这可能有助于识别对应用程序性能影响最大的代码区域。

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

这些都是衡量时间的好方法,但这只是发现瓶颈的一种非常间接的方法。

在线程中找到瓶颈的最直接方法是让它运行,当它正在做任何让您等待的事情时,使用暂停或中断键停止它。这样做几次。如果你的瓶颈占用了X%的时间,那么X%就是你在每次快照中捕捉到它的概率。

这是一个更完整的解释如何和为什么它的工作

这是正确的方法:

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来获得准确的性能计数器

这篇文章表示首先你需要比较三个选项,StopwatchDateTime.NowDateTime.UtcNow

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

然而,事实证明,计数器几乎总是存在的-参见关于。net秒表高分辨率性能计数器及其存在的解释?< / >

这是一个性能图表。请注意UtcNow的性能成本与其他选项相比有多低:

Enter image description here

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

Stopwatch更好的一件事是它提供了更高分辨率的时间测量。另一个原因是它更加面向对象。然而,围绕UtcNow创建一个OO包装器并不难。

我在程序中使用的方式是使用StopWatch类,如下所示。

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




// Critical lines of code


long elapsedMs = sw.Elapsed.TotalMilliseconds;

这不够专业:

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。收集调用以将托管堆更改为已知状态,并添加Sleep调用,以便在ETW配置文件中轻松分离不同的代码间隔。

因为我不太关心精度,所以我最终比较了它们。我正在捕获网络上的大量数据包,我想在我收到每个数据包时放置时间。下面是测试500万次迭代的代码

    int iterations = 5000000;


// Test using datetime.now
{
var date = DateTime.UtcNow.AddHours(DateTime.UtcNow.Second);


var now = DateTime.UtcNow;


for (int i = 0; i < iterations; i++)
{
if (date == DateTime.Now)
Console.WriteLine("it is!");
}
Console.WriteLine($"Done executing {iterations} iterations using datetime.now. It took {(DateTime.UtcNow - now).TotalSeconds} seconds");
}


// Test using datetime.utcnow
{
var date = DateTime.UtcNow.AddHours(DateTime.UtcNow.Second);


var now = DateTime.UtcNow;


for (int i = 0; i < iterations; i++)
{
if (date == DateTime.UtcNow)
Console.WriteLine("it is!");
}
Console.WriteLine($"Done executing {iterations} iterations using datetime.utcnow. It took {(DateTime.UtcNow - now).TotalSeconds} seconds");
}


// Test using stopwatch
{
Stopwatch sw = new Stopwatch();
sw.Start();


var now = DateTime.UtcNow;


for (int i = 0; i < iterations; i++)
{
if (sw.ElapsedTicks == DateTime.Now.Ticks)
Console.WriteLine("it is!");
}
Console.WriteLine($"Done executing {iterations} iterations using stopwatch. It took {(DateTime.UtcNow - now).TotalSeconds} seconds");
}

输出结果为:

Done executing 5000000 iterations using datetime.now. It took 0.8685502 seconds
Done executing 5000000 iterations using datetime.utcnow. It took 0.1074324 seconds
Done executing 5000000 iterations using stopwatch. It took 0.9625021 seconds

总之,DateTime。如果您不太关心精度,UtcNow是最快的。这也支持这个问题的答案https://stackoverflow.com/a/6986472/637142