Search code examples
c#performancedatetimetimestopwatch

Execute same method consume far less time


When I analyzed my old posts exact solution, I found a contradiction so I try to code this in Form1 constructor (after 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);  

Result

Convert take time 00:00:00.0102284

First StopWatch

Start: 02:42:29:929

Stop: 02:42:29:939

Convert take time 00:00:00.0000069

Second StopWatch

Start: 02:42:29:940

Stop: 02:42:29:940

I found that only FIRST DateTime.Now.ToString("HH:mm:ss:fff"); consumes 10ms but 3 others consume less than 10us in same scope, may I know the exact reason?

Is it because the FIRST one make the code on the memory so the following 3 get the advantage of it to consume more less time to do the same things? thanks.


Solution

  • At first, I thought it was indeed the JIT.. but it doesn't make sense because the framework itself is compiled AOT, when installed.

    I think it is loading the current culture (ToString does that, and indeed it is the function that takes time)

    ================ EDIT =============

    I did some tests, and there are two things which take time the first time they are called.

    DateTime.Now make a call to the internal method TimeZoneInfo.GetDateTimeNowUtcOffsetFromUtc which take about half of the consumed time...

    the rest is consumed by to string..

    if instead of calling DateTime.Now you had called DateTime.UtcNow, you wouldn't notice that first-time impact of getting the local time offset.

    and about ToString - what's consuming most of it's running time, was generating the DateTimeFormat for the current culture.

    I think this answered your question pretty well :)