3 ms·
> Same issues and resolution affect all of the other mechanisms you mention. Really? On versions prior to 20H2? This gives me 16ms resolution for SetWaitableTi
by mehrdadn 6y ago
> Same issues and resolution affect all of the other mechanisms you mention.
Really? On versions prior to 20H2? This gives me 16ms resolution for SetWaitableTimer but 1ms for timeSetEvent:
#include <tchar.h>
#include <Windows.h>
#include <MMSystem.h>
#pragma comment(lib, "winmm.lib")
static unsigned int prev_time = timeGetTime();
VOID CALLBACK callback(LPVOID lpArgToCompletionRoutine, DWORD dwTimerLowValue, DWORD dwTimerHighValue)
{ unsigned int now = timeGetTime(); _tprintf(_T("%u\n"), now - prev_time); prev_time = now; }
void CALLBACK callback(UINT uTimerID, UINT uMsg, DWORD_PTR dwUser, DWORD_PTR dw1, DWORD_PTR dw2) { return callback(NULL, 0, 0); }
int _tmain(int argc, TCHAR *argv[])
{
enum { msec = 1 };
HANDLE handle = CreateWaitableTimer(NULL, FALSE, NULL);
LARGE_INTEGER due = {};
SetWaitableTimer(handle, &due, msec, callback, NULL, FALSE);
for (int i = 0; SleepEx(100, TRUE) == WAIT_IO_COMPLETION && i < 30; ++i) { }
CloseHandle(handle);
MMRESULT id = timeSetEvent(msec, 1, callback, NULL, TIME_PERIODIC | TIME_KILL_SYNCHRONOUS);
Sleep(100);
timeKillEvent(id);
}
- gambiting 6y agoI can 100% guarantee that if your system time resolution is 16ms, that timeSetEvent won't actually trigger in 1ms, no matter what it reports.
- mehrdadn 6y agoWell that's not what I'm seeing... can you paste what you get? > clockres && Temp Maximum timer interval: 15.625 ms Minimum timer interval: 0.500 ms Current timer interval: 15.621 ms 0 15 16 ... 16 15 2 1 2 ...
- gambiting 6y agoNo, because I don't have access to these Windows Server 2016(virtualized on GCP) machines anymore, and the behaviour on Windows 10 isn't the same so I can't check. All I can say is that we have spent weeks investigating this and if it was possible to wait 1ms with the timer resolution set to 16ms we would have done so.
- mehrdadn 6y agoWell I don't know what Windows Server 2016 virtualized on GCP is doing, but if you believe me that I copy-pasted this, you should be wary of making such sweeping claims about Windows... Re: your troubleshooting: wild guess, but one thing to look into (if you ever encounter it again) might be changing the "Processor scheduling" setting in sysdm.cpl -> Advanced -> Settings #1 -> Advanced to "Programs" instead of "Background services". Not sure if that affects timers, but I can't think of much else (besides the hypervisor or hard-coded kernel differences) that would cause this.
- vardump 6y agoOne shouldn't really test Windows timer behavior on virtualized platforms, it's bad enough as it is on bare metal.
- gambiting 6y agoRight, but this wasn't some sort of academic exercise - we were deploying a server for a commercial product and ran into this problem because we had to get it running in that scenario. We can of course argue that audio processing shouldn't be done on a virtualized operating system full stop, but that's not a part I had any control over.
- vardump 6y agoYou're just using timeSetEvent (which is an obsolete API, if I may add) instead of timeBeginPeriod. Which ultimately changes Windows timer interrupt frequency to the specified value. So, sure, if you change Windows timer interrupt frequency, that's what you get. It'll of course also affect Sleep while active. Back to the square one.
- mehrdadn 6y agoTry adding timeBeginPeriod(1)/timeEndPeriod(1) around the waitable timer code and you'll see it still wakes up every 16ms.
- vardump 6y agoPretty interesting. And very alarming. On Win10/1809 timeBeginPeriod does affect SetWaitableTimer resolution, as I'd have expected. On Win10/2004 timeBeginPeriod doesn't seem to affect SetWaitableTimer resolution?! This could certainly break things! SetWaitableTimer documentation lets you understand timeBeginPeriod is expected to affect the resolution. Of course, depending on hardware... but in this case both tests were running on same hardware. "You can change the resolution of your API with a call to the timeBeginPeriod and timeEndPeriod functions. How precise you can change the resolution depends on which hardware clock the particular API uses. For more information, check your hardware documentation." https://docs.microsoft.com/en-us/windows/win32/api/synchapi/nf-synchapi-setwaitabletimer https://docs.microsoft.com/en-us/windows/win32/api/synchapi/...
- mehrdadn 6y agoMight be due to my use of APCs rather than waiting on the object. Not bothered enough to try it myself but I guess you can try WaitForSingleObject on the timer to see if it behaves similarly...
- vardump 6y agoOn 2004, I tried timeBeginPeriod(1) and calling Sleep(1) 1000 times. Perplexingly it took a bit under 2 seconds. On 1809 same took about 1.3 seconds. I'm at loss... Windows timers have yet again managed to do really weird, unexpected things. I really hope this mess doesn't affect device drivers, or there could be a world of hurt coming up.