当我分析我的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个有利于它消耗更多时间来做同样的事情吗?感谢。
答案 0 :(得分:4)
起初,我认为它确实是JIT ..但它没有意义,因为框架本身是在安装时编译的AOT。
我认为它正在加载当前的文化(ToString
这样做,实际上它是需要时间的函数)
================编辑=============
我做了一些测试,第一次调用时有两件事需要时间。
DateTime.Now
调用内部方法TimeZoneInfo.GetDateTimeNowUtcOffsetFromUtc
,占用大约一半的消耗时间......
其余部分被字符串消耗..
如果不是调用DateTime.Now
而是调用DateTime.UtcNow
,那么您就不会注意到获得本地时间偏移的第一次影响。
和大约ToString
- 正在消耗大部分运行时间的是为当前文化生成DateTimeFormat。
我认为这很好地回答了你的问题:)
答案 1 :(得分:2)
首先调用类中的任何单个方法都需要JIT,因此第一次调用总是很慢(除非使用NGen对程序集进行预处理)。
根据与第一次呼叫相关的方法,加载必要的资源/数据还需要额外的费用。即可能DateTime.Now
和DateTime.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)
正如已经提到的,你的测量是错误的。您不应该首先调用任何代码,因为它需要被引用,将包含该时间。
依靠结果只运行一次也不好;你需要运行代码次数,你应该计算平均花费的时间。
请确保在没有附加调试器的发布模式下执行此操作。