我需要找到一个瓶颈,并需要尽可能准确地测量时间。
下面的代码片段是衡量性能的最佳方法吗?
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);
当前回答
我刚刚在Vance Morrison的博客上找到了一篇关于他写的CodeTimer类的文章,这个类可以让使用StopWatch变得更容易,并在旁边做一些整洁的事情。
其他回答
这是正确的方法:
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来获得准确的性能计数器。
如果你想要一些快速和肮脏的东西,我建议使用秒表代替更大程度的精度。
Stopwatch sw = new Stopwatch();
sw.Start();
// Do Work
sw.Stop();
Console.WriteLine("Elapsed time: {0}", sw.Elapsed.TotalMilliseconds);
或者,如果你需要一些更复杂的东西,你可能应该考虑使用第三方分析器,如ANTS。
这篇文章说,首先你需要比较三个替代品,秒表,日期时间。Now AND DateTime.UtcNow。
它还显示在某些情况下(当性能计数器不存在时)Stopwatch正在使用DateTime。UtcNow +一些额外的处理。因此,在这种情况下,DateTime很明显。UtcNow是最好的选择(因为其他使用它+一些处理)
然而,事实证明,计数器几乎总是存在的-参见关于高分辨率性能计数器及其与. net秒表相关的存在的解释?
这是一个性能图表。请注意UtcNow的性能成本与其他选项相比有多低:
X轴是样本数据的大小,Y轴是样本的相对时间。
秒表更好的一点是它能提供更高分辨率的时间测量。另一个原因是它更加面向对象。然而,围绕UtcNow创建一个OO包装器并不难。
将基准测试代码放入实用程序类/方法中是很有用的。StopWatch类不需要在错误时被丢弃或停止。最简单的为动作计时的代码是
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);
}
这不够专业:
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配置文件中轻松分离不同的代码间隔。