Am I right in saying SetTimer is 15ms resolution whereas Sleep is 10ms and if so how many instructions are executed in 5ms? I think 5ms is 5/1000s of a second? so that is a big difference right?
Further if I do Sleep, 0 or Sleep, 1 that is effectively Sleep, 10?
I may be incorrect, but windows is not a real time operating system, meaning the exact time it will take is going to vary depending on your system, and what your system is doing.
SetTimer is going to generate a message that is going to be processed by DispatchMessage either to your timer proc, or to the window with WM_TIMER message, depending on how many messages are in that thread's queue may also affect when it is seen. Sleep() on the other hand is going to sit right where the sleep is.... meaning it is basicly going to be limited in accuracy by context switching.
OK good info and I had considered that may be part of the answer ty :bg.... my main interest is in the comparison of the functions.... whether Sleep has higher resolution to SetTimer.... Currently I use Sleep,1 in my apps however if SetTimer has the same resolution it would be a better match....
To give a bit of context I am currently using Sleep, 1 for a FPS limiter checker
On a single CPU machine you can check the cycles burned using RDTSC.
Sleep() represents the MINIMUM amount of time you expect the OS to go do something else.
Sleep() is generally used to yield your task, and pace polling loops which would otherwise saturate the CPU. If you want to do that more effectively something like WaitForSingleObject() would be the way to go.
If you want things to run on a more linear time line, you could pull the Sleep() time in/out using GetTickCount() so the slip/drift does not accumulate. For example if you wanted to poll at 10 Hz (roughly), and the first Sleep(100) yielded 150 ms, you'd request 50 ms the next time around.
OK so I kinda get what you're saying Clive but your experience dwarfs my understanding :lol
I want the CPU to be freed up so while the scene is displaying the CPU usage drops rather than looping at 100% CPU.... My app currently calls Sleep, 1 then checks if it is time for next frame then if not Sleep, 1 again ad infinitum....
Does WaitForSingleObject continue to beast the processor/ have better resolution....
I have used RDTSC before however I dont know how to make that yeild
EDIT: Reread and taken in what you said about RDTSC will do some testing ty for your time guys
I come from a embedded/hardware/driver background so some of my experiences won't be too helpful.
Your biggest problem here is knowing what the Time Quantum is (amount of run time allocated to each runable thread/task, differs from OS to OS, and Workstation vs Server) and how many other threads/tasks of the same or higher priority are running. I think you'll find Windows isn't very timely when it comes to user space code. Even with timers, you are sharing a common resource and queuing for it like everyone else. Sometimes you'll get lucky, other times you won't.
The closer you can get your Sleep() time, or WaitForSingleObject() timeout, to fall at the point you expect the "frame" to arrive the better. ie it would help you in the scheduler if your thread awakens once, rather than runs/yields a dozen times and gets pushed to the back of the list each time.
With both RDTSC and GetTickCount() permit you take snap shots and then compute the delta time. RDTSC has much finer granularity, but it comes from the CPU you are running on, and will likely be effected by things like SpeedStep or other dynamic clock throttling.
WaitForSingleObject() is designed to completely stop execution of the thread/task until either the event is signalled or the timeout expires.
Quote from: clive on May 19, 2010, 09:07:30 PM
ie it would help you in the scheduler if your thread awakens once, rather than runs/yields a dozen times and gets pushed to the back of the list each time.
Awesome, ty for your input guys.... If nothing else (and I havent had a chance to go fully through your replys yet) this will help me improve my app to some degree
Here, is an old article from MSDN Magazine: Implement a Continuously Updating, High-Resolution Time Provider for Windows, 2004 (http://msdn.microsoft.com/en-us/magazine/cc163996.aspx). It's long and tedious, but explains the difficulties involved with obtaining a highly accurate (~10 ms) time from the Windows Operating System. Clive is fairly close to the truth.
QuoteThe problem...is that it didn't take into account the preemptiveness of the Windows NT scheduler. There is no guarantee, for example, that a thread context switch won't take place between...two lines of code, resulting in a delay of an unknown period of time.
:lol nothing's ever simple is it..... ty baltoro that is most useful :bg
oex,
In ring3 any timing technique finds accuracy limits and as you get down to intervals of about 20ms and lower it gets progressively less reliable. You can increase the accuracy with a multimedia timer but you get higher processor usage from doing it. Have a look in the masm32 example code "example10\sleepex" for the multimedia timer example.
The CPU usage is the all important factor.... I want to free up as much cpu time as possible for background tasks and my own 'get ahead' code for 3D be it decompressing images or calculating physics for the next frame.... The problem comes between frames where you want to keep the frames regular ie 33,66,100,133ms etc so you have to delay the next frame's processing.... If you loop you have 100% CPU but accuracy with RDTSC, you can also use settimer function but *I think* a loop with Sleep,1 has better accuracy (though I havent setup a testbed that assumption is just from reading random posts on the web)
If the frame takes 25ms to draw there are 8 ms just sitting there doing sweet FA.... Terribly inefficient :lol.... If Sleep has a MINIMUM resolution of 10ms you start invading on the next frames time which might take 37 ms to display so then things start messing up and you start dropping frames
It gets still worse at 60 FPS (or even 120 FPS) because you just dont have the resolution to find free time
EDIT: Not that I have the code to fill the time yet :lol but I'm working on it :bg
Clocking frame rates is much the target of a multimedia timer, you can get them to run down to a few milliseconds but most animation does not require that frame rate, 20ms is 50 frames a second and from memory DVDs only run at about 28 frames a second, depends on what you are going to display. The games guys are playing with higher frame rates but they tend to work the GPU a lot harder than the CPU.
A multicore processor is the way to go if you are bashing around large amounts of video data, one thread doing diskIO while another is doing the image processing and display. Games are one area that take big advantage of dual and quad core hardware as the more threads you can maintain the more data you can move around at high speed. I would also be inclined to look at some of the SSE instructions as many of them are geared to do exactly this type of work.
As far as I know the Sleep function and timers created by SetTimer both have an effective resolution of 10 or 15 milliseconds, depending on the version of Windows and/or the system hardware. On every system that I have tested the effective resolution for both was 10 milliseconds. The attachment is a test app that uses the high-resolution performance counter to compare the delay periods for Sleep(1) and Sleep(10).
The Microsoft. Win32. API provides 4 functions for dealing with waitable timer objects, providing very high resolution (100 nSec.)
http://www.codeguru.com/cpp/w-p/system/timers/print.php/c2837
The authors are probably wrong about the 100ns. Another road to go is timeBeginPeriod (http://msdn.microsoft.com/en-us/library/dd757624(VS.85).aspx), but it increases slightly CPU usage.
Thank you Michael and JJ both interesting posts.... I have run the test app with the following results:
Sleep(1) delay = 1.990 ms
Sleep(10) delay = 10.946 ms
You can try using the GetTime and the one-shot timer AdviseTime ( I'm using the one from DirectSound to fill the soundbuffer without the use of notifications :bg)
Let the timer run in its own thread with high priority using CreateThread and SetThreadPriority
And create a timer-event with CreateEvent
GetTime delivers the time in the type REFERENCE_TIME
coinvoke g_pDS_Timer,IReferenceClock,GetTime,addr RefClockTime ; receives the current time, in 100-nanosecond units.
coinvoke g_pDS_Timer,IReferenceClock,AdviseTime,RefClockTime,StreamTime,DS_TimerEvent,addr pdwAdviseCookie
http://msdn.microsoft.com/ja-jp/library/cc369473(v=MSDN.10).aspx
This is great guys.... So many ways to do nothing :lol
One more, using timeSetEvent. Resolution is one millisecond, and CPU usage does not increase. The attached executable needs SSE2 (sorry Michael :()
include \masm32\MasmBasic\MasmBasic.inc ; http://www.masm32.com/board/index.php?topic=12460
uselib winmm
CbTimer PROTO:DWORD,:DWORD,:DWORD,:DWORD,:DWORD
.data?
Counter SDWORD ?
Ticks dd ?
TimerID dd ?
Init
Open "O", #1, "TimerTest.txt"
mov Counter, 10000 ; will run 10 seconds, enough to check CPU usage
mov Ticks, Timer()
mov TimerID, rv(timeSetEvent, 1, 1, CbTimer, 0, TIME_PERIODIC or TIME_KILL_SYNCHRONOUS)
.if eax
.Repeat
invoke Sleep, 100
.Until Counter<=0
.endif
Close
Inkey Str$("\n\nYour puter has run %3f hours since the last boot, give it a break!", Timer()/3600000)
Exit
CbTimer proc ID:DWORD, uMsg:DWORD, dwUser:DWORD, dw1:DWORD, dw2:DWORD
dec Counter
.if Sign?
invoke timeKillEvent, TimerID
.else
mov ecx, Timer()
sub ecx, Ticks
Print #1, Str$(Counter), Tb$, Str$(ecx), CrLf$
.endif
ret
CbTimer endp
end start
Quote from: jj2007
The authors are probably wrong about the 100ns.
The resolution of the time base used by Microsoft (FILETIME) is 100 ns, the granularity of the updates are going to be significantly higher. With all these timer constructs, the event occurs when the system identifies that all the delay has been exhausted, not at the time requested. With the granularity, you don't even know the time you actually started with any real precision. What you really need is a free running hardware counter that is clocking at a known/stable frequency, ideally disciplined with GPS, NTP or IEEE-1588.
ie
CurrentTime += 5000; (CurrentTime - StartTime) >= TimeOut;
StartTime could also be set at tick 0 .. 4999
or
CurrentTime += 5000; (CurrentTime - TargetTime) >= 0;
The specific trick with video frames is not to let time slip/drift accumulate. You get the time at the beginning of playback, and increment the target time at the frame rate, and achieve addition discipline from the audio (known/stable frequency, but probably *not* synchronous to your system timebase).
The time of any specific Sleep(), or whatever method, should be irrelevant.
Clive,
My previous posts uses the MM timer, which has the required features for a more or less stable 1 ms resolution. See sample output below. The left column is the counter for Print #1, the second one is the elapsed GetTickCount since launching the timer.
9999 0
9998 0
9997 0
9996 0
9995 0
9994 0
9993 0
9992 0
9991 0
9990 0
9989 0
9988 0
9987 0
9986 15
9985 15
9984 15
9983 15
9982 15
9981 15
9980 15
9979 15
...
18 9968
17 9984
16 9984
15 9984
14 9984
13 9984
12 9984
11 9984
10 9984
9 9984
8 9984
7 9984
6 9984
5 9984
4 9984
3 9984
2 9984
1 10000
0 10000
These messages have already illuminated a glaringly obvious mistake in my code.... I was using GetTickCount in conjunction with Sleep to check if I was into the next time frame :/.... Thanks guys for your help you have saved me milliseconds!!!! :bg
you may wish to check out VideoLAN's VLC player. it is open source if you wish to see how they implement video.
E^Cube suggested NtDelayExecution (also 100ns) on another post, thought I might add a note this has been very useful info for me