什么是计算时间跨度的最佳方法

5
在我的 C# 程序中,我需要计算一个 foreach 循环中的业务逻辑执行时间,并将其存储为 TimeSpan。我使用以下代码:
for (int i = 0; i < 100; i++)
{
    DateTime start= DateTime.Now; 
    // Business logic
    DateTime end= DateTime.Now; 
    TimeSpan time = start.Subtract(end);
    // Save timespan in log file
}

请帮我纠正是否使用了正确的代码,或者需要做一些修改以获得更好的性能和结果。


2
我认为你会对Stopwatch更感兴趣。 - V4Vendetta
在编程中,几乎从不使用DateTime.Now而是使用DateTime.UtcNow是正确的做法(但在这种情况下,StopWatch更好)。 - Ian Mercer
可能是重复的问题:DateTime.Now是衡量函数性能的最佳方式吗? - Michael Freidgeim
4个回答

19
你应该使用一个Stopwatch。相比于系统的墙上时间钟,Stopwatch更加准确用于时间测量。
var sw = Stopwatch.StartNew();
// business logic
sw.Stop();
TimeSpan time = sw.Elapsed;

谢谢,信息很有用。我还有两个问题:1. 因为我正在使用for循环,所以不需要在每次循环中创建Stopwatch实例(我是对的吗?)2. 如果总时间少于1分钟,则希望以秒为单位计算,否则以分钟为单位计算,请问有什么信息吗? - Hemant Kothiyal

2

1

看起来你正在使用时间跨度来衡量性能。你的代码没问题,但是你应该知道DateTime只有这么精确(大多数机器上约为10-15毫秒--请参见“无用计时器机制”部分这里进行解释)。

DateTime也不连续;如果第一个DateTime在夏令时开始之前刚好被检索出来,而后一个DateTime在夏令时开始之后呢?一个需要一秒钟的操作可能会显示为需要一个小时,甚至是负时间。即使所有时间都在UTC中,当用户手动更改时间或计算机进入睡眠状态并唤醒时引起的跳跃等问题也存在潜在问题。

更好的选择是使用Stopwatch,它专门设计用于此类事情,并使用高精度计时器内部(通过QueryPerformanceCounter() Win32函数)。


1
回答您的后续问题,(1) 您是正确的,您不需要在每次迭代中重新实例化一个 StopWatch。您只需要使用 restart 方法,像这样:
Stopwatch sw = new Stopwatch();
sw.Start(); // To initialize
for (int i = 0; i < 100; i++)
{
    sw.Restart();
    // Business logic 
    TimeSpan time = sw.Elapsed;
    // Save timespan in log file
}

(2) 如果时间小于一分钟,你可能需要编写几行代码来返回以秒为单位的值,如果大于一分钟则返回分钟,但以下是一个示例(假设这是保存了上面示例中的时间段后的下一行):

TimeSpan time = sw.Elapsed;
int iSecondsOrMinutes = time.TotalSeconds < 60 ? time.Seconds : (int)time.TotalMinutes;

这个例子使用三元运算符来保存分钟或秒的整数。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接