2
votes

Quelle horloge est utilisée par l'implémentation CRT Visual Studio 2017 de std :: chrono :: system_time?

Les commentaires dans l'en-tête du chrono indiquent simplement

// wraps GetSystemTimePreciseAsFileTime/GetSystemTimeAsFileTime

Mais qu'est-ce qu'il utilise réellement (c'est-à-dire à quelle précision puis-je m'attendre)? L'implémentation appelle _Xtime_get_ticks , mais cette fonction est opaque.


3 commentaires

" à quelle précision puis-je m'attendre " Vous pouvez demander à l'horloge quelle précision elle fournit avec system_clock :: period .


Non pas opaque ... voir la source dans C: \ Program Files (x86) \ Windows Kits \ ... \ Source


La documentation de GetSystemTimePreciseAsFileTime indique que vous pouvez vous attendre à moins d'une microseconde de précision.


3 Réponses :


2
votes
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);
}

0 commentaires

2
votes

Faisons quelques recherches ici. Tout d'abord, cherchons " _Xtime_get_ticks " dans la bibliothèque d'exécution Visual C ++:

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

Ensuite, j'utilise dumpbin / disasm msvcp140.dll avec Fichier msvcp140.i386.pdb dans le même répertoire:

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

Il n'y a pas d'instruction call pour GetSystemTimeAsFileTime n'importe où dans cette fonction désassemblée, il semble donc clair que GetSystemTimePreciseAsFileTime est en effet la seule fonction qui est appelée pour l'implémentation sous-jacente.


2 commentaires

Pourquoi sauter à travers tous ces obstacles si msvcrt est disponible dans la source?


@SergeyA C'est la méthode que j'ai l'habitude d'utiliser pour ce genre de chose.



2
votes

Le CRT appelle GetSystemTimePreciseAsFileTime lorsqu'il est disponible et GetSystemTimeAsFileTime dans le cas contraire. GetSystemTimePreciseAsFileTime vous donne le niveau de précision le plus élevé possible (.

À un moment donné lors de l'initialisation du runtime, une fonction nommée initialize_pointers est appelée qui effectue essentiellement les opérations suivantes (décompilée et simplifiée):

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

Sur un système avec Windows 8 ou plus récent, __encodedKERNEL32Functions [24] sera différent de zéro.

Il vient alors jusqu'à ceci:

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

...

Au moins, voici (approximativement) comment il est implémenté dans la version 14.16.27024.1 de msvcp140.dll et msvcp140d.dll

Tout cela est bien sûr non documenté et sujet à changement.

Si vous devez utiliser GetSystemTimePreciseAsFileTime vous devez écrire votre propre horloge an ne vous fiez pas aux détails de mise en œuvre.


0 commentaires