执行相同的方法消耗的时间要少得多

时间:2014-03-05 18:54:24

标签: c# performance datetime time stopwatch

当我分析我的old posts确切解决方案时,我发现了一个矛盾,所以我尝试在Form1构造函数中编写代码(在InitializeComponent();之后)

Stopwatch timer = Stopwatch.StartNew();
var timeStartGetStatistic = DateTime.Now.ToString("HH:mm:ss:fff");
var timeEndGetStatistic = DateTime.Now.ToString("HH:mm:ss:fff"); 
timer.Stop();
Console.WriteLine("Convert take time {0}", timer.Elapsed);

Console.WriteLine("First StopWatch\nStart:\t{0}\nStop:\t{1}",
    timeStartGetStatistic, timeEndGetStatistic);

Stopwatch timer2 = Stopwatch.StartNew();
var timeStartGetStatistic2 = DateTime.Now.ToString("HH:mm:ss:fff");
var timeEndGetStatistic2 = DateTime.Now.ToString("HH:mm:ss:fff");
timer2.Stop();
Console.WriteLine("Convert take time {0}", timer2.Elapsed);

Console.WriteLine("Second StopWatch\nStart:\t{0}\nStop:\t{1}",
    timeStartGetStatistic2, timeEndGetStatistic2);  

结果

  

转换时间00:00:00.0102284

     

First StopWatch

     

开始时间:02:42:29:929

     

停止:02:42:29:939

     

转换时间00:00:00.0000069

     

Second StopWatch

     

开始时间:02:42:29:940

     

停止:02:42:29:940

我发现只有第一 DateTime.Now.ToString("HH:mm:ss:fff");消耗 10ms 其他3 消耗 10us 在相同的范围内,我可以知道确切的原因吗​​?

是因为第一个代码在内存上生成代码,所以后面的3个有利于它消耗更多时间来做同样的事情吗?感谢。

3 个答案:

答案 0 :(得分:4)

起初,我认为它确实是JIT ..但它没有意义,因为框架本身是在安装时编译的AOT。

我认为它正在加载当前的文化(ToString这样做,实际上它是需要时间的函数)

================编辑=============

我做了一些测试,第一次调用时有两件事需要时间。

DateTime.Now调用内部方法TimeZoneInfo.GetDateTimeNowUtcOffsetFromUtc,占用大约一半的消耗时间......

其余部分被字符串消耗..

如果不是调用DateTime.Now而是调用DateTime.UtcNow,那么您就不会注意到获得本地时间偏移的第一次影响。

和大约ToString - 正在消耗大部分运行时间的是为当前文化生成DateTimeFormat。

我认为这很好地回答了你的问题:)

答案 1 :(得分:2)

首先调用类中的任何单个方法都需要JIT,因此第一次调用总是很慢(除非使用NGen对程序集进行预处理)。

根据与第一次呼叫相关的方法,加载必要的资源/数据还需要额外的费用。即可能DateTime.NowDateTime.ToString需要加载/预处理某些区域设置数据。

使用秒表测量性能的标准方法是调用您想要测量的函数/代码,以启动与代码相关的所有JIT,而不是进行测量。通常你会多次运行代码并获得平均结果。

// --- Warm up --- ignore time here unless meauring startup perf.
var timeStartGetStatistic = DateTime.Now.ToString("HH:mm:ss:fff");
var timeEndGetStatistic = DateTime.Now.ToString("HH:mm:ss:fff"); 


// Actual timing after JIT and all startup cost is payed.
Stopwatch timer2 = Stopwatch.StartNew();
// Consider multiple iterations i.e. to run code for about a second.
var timeStartGetStatistic2 = DateTime.Now.ToString("HH:mm:ss:fff");
var timeEndGetStatistic2 = DateTime.Now.ToString("HH:mm:ss:fff");
timer2.Stop();
Console.WriteLine("Convert take time {0}", timer2.Elapsed);

Console.WriteLine("Second StopWatch\nStart:\t{0}\nStop:\t{1}",
    timeStartGetStatistic2, timeEndGetStatistic2);  

答案 2 :(得分:0)

正如已经提到的,你的测量是错误的。您不应该首先调用任何代码,因为它需要被引用,将包含该时间。

依靠结果只运行一次也不好;你需要运行代码次数,你应该计算平均花费的时间。

请确保在没有附加调试器的发布模式下执行此操作。