Corinna Vinschen wrote:
On Mar 21 23:59, Christian Franke wrote:
clock_getres(CLOCK_REALTIME,&ts) queries the actual resolution through
NtQueryTimerResolution (&coarsest,&finest,&actual) during its
first call and returns this value unchanged afterwards.
This returns a global Windows setting which may be temporarily
modified by other applications by using e.g. timeBegin/EndPeriod().
For example playing a flash video in browser sets the resolution to
1ms. It is reset to default ~15ms when the browser is closed.
As a consequence the actual resolution might be much lower than
reported by clock_getres() when clock_gettime() is used for
measurements later. It would IMO be better to return the 'coarsest'
instead of the 'actual' value.
clock_getres already returns the coarsest time. Did you mean the
setting in hires_ms::resolution, by any chance? It's using the
actual setting right now.
No. Yes.
No, clock_getres(CLOCK_REALTIME, .) returns gtod.resolution() which
calls hires_ms::resolution().
Yes, I mean this function which returns the 'actual' value from
NtQueryTimerResolution(:-).
If clock_setres() is used, this setting should be returned instead
of the 'actual' value at the time of the setting.
Well, I'm not overly concerned about clock_setres, given that it's
probably not used at all :)
Yes, it is not POSIX and does not exist on Linux, FreeBSD, ...
It IMO is useful as CLOCK_REALTIME does only provide a rather coarse
default resolution on Cygwin.
BTW: GetSystemTimeAsFileTime() apparently provides the same
resolution (at least on Win7 x64). So the more complex use of
SharedUserData.InterruptTime may have less benefit than expected.
On pre-Vista, the accuracy of GetSystemTimeAsFileTime is 15.625 ms,
fixed. On Vista and later it seems to be 15ms or better, but its
resultion is not constant anymore.
Here a run of a test program (attached) and some concurrent activities.
Program prints observable resolutions of 3 clocks (clock_getres()
results in parentheses):
[1] ./testres started/stopped to read default resolutions.
SystemTime CLOCK_REALTIME (getres) CLOCK_MONOTONIC (getres)
0.0156000 0.015600000 (0.015600000) 0.000000301 (0.000000301) ...
^C
[2] flash video started in SeaMonkey
[3] ./testres started
SystemTime CLOCK_REALTIME (getres) CLOCK_MONOTONIC (getres)
0.0010000 0.001000000 (0.001000000) 0.000000302 (0.000000301) ...
0.0005000 0.000500000 (0.001000000) 0.000000302 (0.000000301) [4]
0.0010000 0.001000000 (0.001000000) 0.000000301 (0.000000301) [5]
0.0156000 0.015600000 (0.001000000) 0.000000302 (0.000000301) [6]
Where:
[4] VM started in VirtualBox
[5] VM closed
[6] SeaMonkey closed
Conclusions:
- clock_getres() returns the 'actual' resolution from its first call.
IMO this is a bug.
- The actual resolution may change without notice unless an application
sets the min resolution (500us on this machine) itself.
- On Win7, GetSystemTimeAsFileTime() provides same resolution as
InterruptTime and timeGetTime(). Could not test this on older Windows
versions yet.
- Unlike on e.g. Linux, CLOCK_REALTIME does not provide a better
resolution than gettimeofday().
But I'm not shure either, if the timeGetTime_ns shuffle has any positive
effect. Given that we allow a jitter of 40 ms, we''re potentially worse
off than by just calling GetSystemTimeAsFileTime and be done with it.
Also, all processes would be guaranteed to be on the same time, not only
the processes within the same session sharing gtod.
If this is also the case for older Windows versions, it would be
probably better to revert to GetSystemTimeAsFileTime().
Christian
#include <stdio.h>
#include <time.h>
#include <unistd.h>
#include <windows.h>
static long long get_win32_time(int)
{
FILETIME ft;
GetSystemTimeAsFileTime(&ft);
LARGE_INTEGER it = { { ft.dwLowDateTime, ft.dwHighDateTime } };
return it.QuadPart;
}
static long long get_posix_time(int id)
{
timespec ts;
if (clock_gettime(id, &ts))
return -1;
return ts.tv_sec * 1000000000LL + ts.tv_nsec;
}
static long long get_posix_res(int id)
{
timespec ts;
if (clock_getres(id, &ts))
return -1;
return ts.tv_sec * 1000000000LL + ts.tv_nsec;
}
static long long guess_resolution(long long (*f)(int), int id = -1)
{
long long r = ~0ULL>>1;
for (int i = 0; i < 5; i++) {
long long t1 = f(id), t2;
do
t2 = f(id);
while (t2 >= 0 && t2 == t1);
if (t2 - t1 < r)
r = t2 - t1;
}
return r;
}
int main(int argc, char **argv)
{
printf("SystemTime CLOCK_REALTIME (getres) CLOCK_MONOTONIC (getres)");
long long r1 = -1, r2 = -1, r3 = -1;
int cnt = 0;
for (;;) {
long long r1n = guess_resolution(get_win32_time);
long long r2n = guess_resolution(get_posix_time, CLOCK_REALTIME);
long long r3n = guess_resolution(get_posix_time, CLOCK_MONOTONIC);
if (r1 == r1n && r2 == r2n && llabs(r3-r3n) <= 1) {
printf("%s%5d", (cnt ? "\b\b\b\b\b" : ""), cnt); fflush(stdout);
sleep(1);
cnt++;
}
else {
r1 = r1n; r2 = r2n; r3 = r3n;
printf("\n%.7f %.9f (%.9f) %.9f (%.9f)",
r1/10000000.0,
r2/1000000000.0, get_posix_res(CLOCK_REALTIME) /1000000000.0,
r3/1000000000.0, get_posix_res(CLOCK_MONOTONIC)/1000000000.0);
fflush(stdout);
cnt = 0;
}
}
return 0;
}
--
Problem reports: http://cygwin.com/problems.html
FAQ: http://cygwin.com/faq/
Documentation: http://cygwin.com/docs.html
Unsubscribe info: http://cygwin.com/ml/#unsubscribe-simple