Какие часы использует CRT-реализация Visual Studio 2017 для std :: chrono :: system_time? - PullRequest
0 голосов
/ 28 февраля 2019

В комментариях в заголовке хронографа просто сказано:

// wraps GetSystemTimePreciseAsFileTime/GetSystemTimeAsFileTime

Но что он на самом деле использует (т.е. какую точность я могу ожидать)?Реализация вызывает _Xtime_get_ticks, но эта функция непрозрачна.

Ответы [ 3 ]

0 голосов
/ 01 марта 2019

Давайте проведем небольшое исследование здесь.Сначала давайте найдем «_Xtime_get_ticks» в библиотеке времени выполнения Visual C ++:

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 для GetSystemTimeAsFileTime, поэтому очевидно, что GetSystemTimePreciseAsFileTime действительно единственная функция, которая вызывается для базовой реализации.

0 голосов
/ 01 марта 2019

CRT вызывает GetSystemTimePreciseAsFileTime, если доступно, и GetSystemTimeAsFileTime в противном случае.GetSystemTimePreciseAsFileTime дает вам максимально возможный уровень точности (<1us) </a>.

Иногда во время инициализации среды выполнения вызывается функция с именем 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);
}

По крайней мере, это (примерно) это реализовано в 14.16.27024.1 версии msvcp140.dll и msvcp140d.dll .

Все это, конечно, недокументировано и может быть изменено.

Если вам нужно использовать GetSystemTimePreciseAsFileTime, вам следует написать свои собственные часы и не полагаться на детали реализации.

0 голосов
/ 01 марта 2019
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);
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...