Search code examples
c++windowsc++-chrono

Chrono time counter is inaccurate when machine goes to sleep in the middle of execution?


I have the code sample bellow to measure the execution time of some piece of code:

int main()
{   
    auto before = chrono::steady_clock::now();

    Sleep(30000);

    auto after = chrono::steady_clock::now();

    int duration = (std::chrono::duration_cast<std::chrono::seconds> ((after - before)).count());
    cout << duration << endl;

    return 0;
}

Normally it works fine and prints out 30 in the cout statement.

However, during testing I observed that if the computer were to go to sleep in between the auto before = ... statement and the auto after = ... statement (due to inactivity or whatever other reason), then the printed out time also counts the entire time the machine was asleep. This makes perfect sense since we are comparing a timepoint from before the machine going to sleep and one with after.

So my question is how can I make it so that the duration the machine was asleep is not counted in my final duration? Probably will need a ticker that doesn't increment while machine is asleep rather than timepoint measurements but I'm not aware of such a ticker.

This is a Windows specific question. As I understand, MacOS has mach_absolute_time which is exactly what I'm looking for in windows. I'm using MSVC 19.29.30147.0 as my compiler.


Solution

  • After looking around and testing it out, the solution is to use QueryUnbiasedInterruptTime

    Gets the current unbiased interrupt-time count, in units of 100 nanoseconds. The unbiased interrupt-time count does not include time the system spends in sleep or hibernation.

    Running the following code snippet, I manually put my machine to sleep while the program was stuck on the sleep statement and I observed that the second print out consistently outputs 15 seconds regardless of how long I leave my machine in a sleeping state. However, the first print-out that uses GetTickCount64 will include the amount of time the machine was asleep.

    int main()
    {
    
        ULONGLONG before_query, after_query= 0;
        QueryUnbiasedInterruptTime(&before_query);
        auto beforeticks = GetTickCount64();
       
        Sleep(15000);
    
        QueryUnbiasedInterruptTime(&after_query);
      
        auto afterticks = GetTickCount64();
    
    
        cout << "Ticks from gettickcount64 is " << (double (afterticks-beforeticks))/1000 << endl;
    
        cout << "Unbiased time measure is " << double((after_query - before_query)/10000000) << endl;
    
        return 0;
    }