MattyD Posted yesterday at 02:47 PM Posted yesterday at 02:47 PM Hi folks, I was looking at writing something that spits out time code - but in order to have any chance of succeeding we need to work to a consistent clock. After doing a bit of reading this is where I've landed, but of course if anyone has a better method I'm very open to suggestion. The goal here to kick something off every 33.33ms without tying up too much of the CPU. I don't think this does a terrible job, but a few ticks can still be off the money. With time code I think we can get away with dropping a few messages. So if a pulse say >5ms late, I'd probably just ignore it and shoot for the next frame whenever it rolls around. Local $nFrame = (1000/30) ;30fps (33.33ms) Local $nElapsed, $nTarget = $nFrame, $nShift Local $hTimer = TimerInit() Local $iTimeout = 30000 Do ;Sleep until 10ms before the next tic is due. Exiting sleep does chew up some time. Sleep(($nFrame - $nShift) - 10) ;Spin-Lock Do $nElapsed = TimerDiff($hTimer) Until $nElapsed >= $nTarget ;See how much we've missed by! $nShift = $nElapsed - $nTarget ConsoleWrite(StringFormat("%0.2f", $nFrame + $nShift) & @CRLF) $nTarget += $nFrame Until $nTarget >= $iTimeout It's also worth mentioning that when you push the frequency of the clock past ~55Hz, the combination of Sleeps/ConsoleWrites() can't seem to keep up with the clock (at least on my laptop). So I guess that's one indicator as to how far you can push things.
Nine Posted yesterday at 03:01 PM Posted yesterday at 03:01 PM Have you tried the QueryPerformanceCounter function (profileapi.h) ? “They did not know it was impossible, so they did it” ― Mark Twain Spoiler Block all input without UAC Save/Retrieve Images to/from Text Monitor Management (VCP commands) Tool to search in text (au3) files Date Range Picker Virtual Desktop Manager Sudoku Game 2020 Overlapped Named Pipe IPC HotString 2.0 - Hot keys with string x64 Bitwise Operations Multi-keyboards HotKeySet Recursive Array Display Fast and simple WCD IPC Multiple Folders Selector Printer Manager GIF Animation (cached) Screen Scraping Multi-Threading Made Easy
MattyD Posted yesterday at 03:54 PM Author Posted yesterday at 03:54 PM Thanks mate - That should help fine tune the spin lock I'd dare say. When a tick is late its because we're slow coming out of sleep - so the super fine time stamp probably won't help us there!
Werty Posted yesterday at 04:37 PM Posted yesterday at 04:37 PM There's also the old highprecisionsleep() by monoceres... other variants throughout the thread. argumentum and MattyD 2 Some guy's script + some other guy's script = my script!
MattyD Posted 21 hours ago Author Posted 21 hours ago (edited) Just awesome. You do still need the spin lock - but that's helped quite a bit. Oops I made a mistake, and we weren't actually sleeping (example updated!). I'll have a closer look, but just eyeballing it I don't think the result was much better than a normal sleep... Without the spin lock that function jumps around quite a bit. expandcollapse popupGlobal $nFrame = (1000/30) ;30fps (33.33ms) Global $nElapsed, $nTarget = $nFrame, $nShift Global $hTimer = TimerInit() Global $iTimeout = 30000 ;~ _Original() _WithSpinLock() ;~ _WithoutSpinLock() Func _Original() Do ;Sleep until 10ms before the next tic is due. Exiting sleep does chew up some time. Sleep(($nFrame - $nShift) - 10) ;Spin-Lock Do $nElapsed = TimerDiff($hTimer) Until $nElapsed >= $nTarget ;See how much we've missed by! $nShift = $nElapsed - $nTarget ConsoleWrite(StringFormat("%0.2f", $nFrame + $nShift) & @CRLF) $nTarget += $nFrame Until $nTarget >= $iTimeout EndFunc Func _WithSpinLock() Do ;Sleep until 10ms before the next tic is due. Exiting sleep does chew up some time. _HighPrecisionSleep((($nFrame - $nShift) - 10) * 1000) ;Spin-Lock Do $nElapsed = TimerDiff($hTimer) Until $nElapsed >= $nTarget ;See how much we've missed by! $nShift = $nElapsed - $nTarget ConsoleWrite(StringFormat("%0.2f", $nFrame + $nShift) & @CRLF) $nTarget += $nFrame Until $nTarget >= $iTimeout EndFunc Func _WithoutSpinLock() Do _HighPrecisionSleep(($nFrame - $nShift) * 1000) $nElapsed = TimerDiff($hTimer) $nShift = $nElapsed - $nTarget ConsoleWrite(StringFormat("%0.2f", $nFrame + $nShift) & @CRLF) $nTarget += $nFrame Until $nTarget >= $iTimeout EndFunc Func _HighPrecisionSleep($iMicroSeconds,$hDll=False) Local $hStruct, $bLoaded If Not $hDll Then $hDll=DllOpen("ntdll.dll") $bLoaded=True EndIf $hStruct=DllStructCreate("int64 time;") DllStructSetData($hStruct,"time",-1*($iMicroSeconds*10)) DllCall($hDll,"dword","ZwDelayExecution","int",0,"ptr",DllStructGetPtr($hStruct)) If $bLoaded Then DllClose($hDll) EndFunc Edited 21 hours ago by MattyD
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now