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