首页 文章

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

提问于
浏览
1

当我分析我的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秒秒表开始:02:42:29:940停止: 02:42:29:940

我发现只有 FIRST DateTime.Now.ToString("HH:mm:ss:fff"); 消耗 10ms3 others 在同一范围内消耗的数量少于 10us ,我可否知道具体原因?

是因为第一个在内存上创建代码所以后面的3个获得它的优势,消耗更多的时间来做同样的事情?谢谢 .

3 回答

  • 4

    如前所述,你测量错了 . 您不应该包括对任何代码的第一次调用,因为它需要被引用,将包括该时间 .

    依靠结果只运行一次也不好;您需要运行代码次数,并且您应该计算平均所用时间 .

    确保在未附带调试器的发布模式下执行此操作 .

  • 0

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

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

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

    我做了一些测试,有两件事在他们第一次被调用时需要时间 .

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

    其余的被字符串消耗..

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

    关于 ToString - 运行时间是什么,为当前文化生成了DateTimeFormat .

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

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

相关问题