Visual Studio 2017 CRT实现的std :: chrono :: system_time使用哪个时钟?

时间:2019-02-28 20:41:45

标签: c++ windows visual-c++

chrono标头中的注释只是说

// wraps GetSystemTimePreciseAsFileTime/GetSystemTimeAsFileTime

但是它实际使用哪一个(即,我希望达到什么精度)?该实现调用_Xtime_get_ticks,但是该函数是不透明的。

3 个答案:

答案 0 :(得分:2)

long long _Xtime_get_ticks()
{   /* get system time in 100-nanosecond intervals since the epoch */
FILETIME ft;
__crtGetSystemTimePreciseAsFileTime(&ft);
return ((((long long)ft.dwHighDateTime) << 32)
    + (long long)ft.dwLowDateTime - EPOCH);
}

答案 1 :(得分:2)

CRT在可用时调用GetSystemTimePreciseAsFileTime,在其他情况下调用GetSystemTimeAsFileTimeGetSystemTimePreciseAsFileTime给您highest possible level of precision (<1us)

有时在运行时初始化期间,会调用一个名为initialize_pointers的函数,该函数基本上会执行以下操作(反编译和简化):

HMODULE hModule = GetModuleHandleW(L"kernel32.dll");

__encodedKERNEL32Functions[0] = (void *)GetProcAddress(hModule, "FlsAlloc");
__encodedKERNEL32Functions[1] = (void *)GetProcAddress(hModule, "FlsFree");
__encodedKERNEL32Functions[2] = (void *)GetProcAddress(hModule, "FlsGetValue");
__encodedKERNEL32Functions[3] = (void *)GetProcAddress(hModule, "FlsSetValue");

...


__encodedKERNEL32Functions[24] = (void *)GetProcAddress(hModule, "GetSystemTimePreciseAsFileTime");

...

在装有Windows 8或更高版本__encodedKERNEL32Functions[24]的系统上,该值为非零。

然后归结为:

std::chrono::system_clock::now()
-> _Xtime_get_ticks
   -> __crtGetSystemTimePreciseAsFileTime(FILETIME *)

void __crtGetSystemTimePreciseAsFileTime(FILETIME *lpSystemTimeAsFileTime)
{
    void (*f)(FILETIME *) = (void (*)(FILETIME *))__encodedKERNEL32Functions[24];
    if (f)                         // if GetSystemTimePreciseAsFileTime exists
        f(lpSystemTimeAsFileTime); // call it
    else
        GetSystemTimeAsFileTime(lpSystemTimeAsFileTime);
}

至少(大约)这是在 msvcp140.dll msvcp140d.dll 14.16.27024.1 版本中实现的方式。< / p>

所有这些当然都是无证的,随时可能更改。

如果您需要使用GetSystemTimePreciseAsFileTime,则应该write your own clock,而不要依赖于实现细节。

答案 2 :(得分:1)

让我们在这里做一些研究。首先,让我们在Visual C ++运行时库中找到“ _Xtime_get_ticks”:

C:\Windows\SysWOW64>dumpbin /exports msvcp140.dll|findstr /I "Xtime"
       1483  5CA 0000B5D0 _Xtime_diff_to_millis
       1484  5CB 0000B610 _Xtime_diff_to_millis2
       1485  5CC 0000B650 _Xtime_get_ticks
       1515  5EA 0000B730 xtime_get

然后,我在同一目录中的dumpbin /disasm msvcp140.dll文件中使用msvcp140.i386.pdb

__Xtime_get_ticks:
  1000B650: ... boilerplate ...
  1000B659: E8 22 50 02 00     call        ___crtGetSystemTimePreciseAsFileTime

此反汇编函数中的任何地方都没有call的{​​{1}}指令,因此很明显GetSystemTimeAsFileTime确实是为底层实现调用的唯一函数。