Hello andrea,
good catch, its actually a bug in SystemClockAdviseThread. A patch like:
--- snip --- diff --git a/dlls/quartz/systemclock.c b/dlls/quartz/systemclock.c index 043299b..ac41a49 100644 --- a/dlls/quartz/systemclock.c +++ b/dlls/quartz/systemclock.c @@ -127,6 +127,7 @@ static DWORD WINAPI SystemClockAdviseThread(LPVOID lpParam) { it = nextit; } if (NULL != it) timeOut = (DWORD) ((it->rtBaseTime + it->rtIntervalTime) - curTime) / (REFERENCE_TIME)10000; + else timeOut = INFINITE;
/** Now Periodics Advice: semi sorted list (sort cannot be used) */ for (it = This->pPeriodicAdvise; NULL != it; it = it->next) { --- snip ---
Seems to be sufficient to fix it. I will review the code for other errors one more time, and then submit the patch.
Regarding your second question, the best timer (when using for events) is CreateWaitableTimer in my opinion. All other timers need separate threads, and need an additional wineserver call for event handling.
Regards, Sebastian
On 06.06.2015 16:28, andrea wrote:
On 01/06/15 20:43, andrea wrote:
Hi,
I'm trying to understand why AppleWin uses 100% CPU when running in wine vs ~1% in Windows.
my case is wine 1.7.43 vs Windows 7
https://appdb.winehq.org/objectManager.php?sClass=version&iId=29403 https://bugs.winehq.org/show_bug.cgi?id=34945
basically 97% time is spent in a WaitForSingleObject on a semaphore signalled by a DirectSound IReferenceClock via AdvisePeriodic. The timer period is set to 1 millisecond.
I have tried an other Windows call to create the timer: CreateWaitableTimer The latter uses about 50% CPU, so it is much better, but still not very good.
This is true even on a simple app that does nothing other than waiting for this timer all the time.
Does anybody know
- is this normal? should these waits be almost free like they are in Windows?
- what is the best implemented timer in wine that can be used for a periodic event (~1ms)?
Thanks
I've tried 4 different function to create a period timer
you can compiler it as
// winegcc -g timers.cpp -lwinmm -lole32 -lstrmiids
and then run it as
./a.out X Y
where X is the period of wait in ms, and Y the method it will wait till 10 seconds and print some statistics (you can use "time" to time it)
1 - CreateWaitableTimer 2 - IReferenceClock->AdvisePeriodic 3 - CreateTimerQueueTimer 4 - timeSetEvent
if the wait is 1 ms each time I get the following system times (out of ~10 sec of execution, compute with "time")
1 - 0.33s 2 - 4.05s 3 - 0.57s 4 - 0.54s
if I wait every 5 ms I get
1 - 0.15s 2 - 3.95s 3 - 0.28s 4 - 0.20s
It feels like option 2 (IReferenceClock) is implemented as a sort of spin lock, its system time does not decrease with longer waits.
What do you think?
Andrea