Liu Hao wrote:
在 4/27/21 2:00 AM, Christian Franke 写道:

Which complexity do you mean - the extra cost of the system call or the extra 15 lines of code?


It's actually both.

Wall clocks are not meant to be steady, because they are free to jump back and forth due to NTP synchronization, and arithmetic operations aren't predicable either due to leap seconds.

That's all correct. But there are several use cases where a higher than this ~15.6ms (1/64s) resolution is needed and where occasional clock jumps are acceptable - for example debug logs.

If there were no use cases, the evolution
  time() -> ftime(...) -> gettimeofday(...) -> clock_gettime(CLOCK_REALTIME,...)
would possibly never have happened :-)

BTW.1: Hack:
Do this once in the program
  #ifdef _WIN32
    timeBeginPeriod(1);
  #endif
or start another program which does: Playback a video, run a VM in VBox, run VS 2019, ... ... and the resolution of GetSystemTimeAsFileTime() increases from 1/64s to 1-2ms.

BTW.2: The *ftime*() functions from newer versions of MSVC CRT also use GetSystemTimePreciseAsFileTime() if available.


Introduction of more overhead upon each call, for some unpredictable and unreliable accuracy, is futile.

I guess then it is not worth the effort to provide a related patch for clock_gettime(CLOCK_REALTIME, ...) ?-)



There are also some issues in this patch. You can't assign a `void*` to a pointer-to-function.

The 'void *' was a hack to silence this warning from gcc 10.2.0:

get_time = (GetSystemTimeAsFileTime_t) GetProcAddress (...)
"warning: cast between incompatible function types from ‘FARPROC’ {aka ‘long long int (*)()’} to ‘void (*)(struct _FILETIME *)’ [-Wcast-function-type]"

A detour via 'intptr_t' would also help but might be considered as ugly as 'void *':

get_time = (GetSystemTimeAsFileTime_t)(intptr_t) GetProcAddress (...)


And you can't use `volatile` variables for synchronization; you have to use `_Atomic` which yet adds more complexity in code.

That's right, in theory, 'volatile' would still allow to read the pointer in two halves or so. Using '_Atomic' instead actually changes the code generated by gcc 10.2.0 -O2, but only few register assignments but no memory accesses.





AFAICS, my patch would switch the Mingw-w64 column to '2'.

BTW: None of the above provide an extra high_resolution_clock:
GNU Libstdc++ Headers: using high_resolution_clock = system_clock;
Cygwin (Clang headers), MSVC16: using high_resolution_clock = steady_clock;


`high_resolution_clock` should call `QueryPerformanceCounter()` on Windows or `clock_gettime()` on POSIX systems. `gettimeofday()` is apparently not an option, as it is not suitable for measurement. The libstdc++ implementation should be considered faulty. I suggest people avoid its use.


Several issues accumulate here:
- The Mingw-w64 implementations of 'gettimeofday()' and 'clock_gettime(CLOCK_REALTIME,...)' provide only 1/64s resolution. - Mingw-w64 libstdc++ packages are usually configured with _GLIBCXX_USE_GETTIMEOFDAY set and _GLIBCXX_USE_CLOCK_REALTIME and ..._MONOTONIC unset. - Libstdc++ sets 'using high_resolution_clock = system_clock'. This should be configurable. As a consequence, the steady_clock is not steady and the high_resolution_clock has no high resolution.

- Defining _GLIBCXX_USE_CLOCK_MONOTONIC would fix the steady_clock. Drawback: Without '-static', the 'libwinpthreads-1.dll' is required. - And then  'using high_resolution_clock = steady_clock' would fix the high_resolution clock. Drawback: same as above + fix is outside Mingw-w64 source tree.

--
Best regards,
Christian Franke



_______________________________________________
Mingw-w64-public mailing list
Mingw-w64-public@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/mingw-w64-public

Reply via email to