Ever wanted to do some hi-performance timing? It's useful for games certainly but it is also good for many other tasks requiring a large number of events fired per second. Here is a way that doesn't perform very well:
Code: Select all
Procedure TimerProc()
Shared i
i-1
EndProcedure
OpenWindow(0,0,0,400,240,"I'm trying to go away in 1 second",#PB_Window_SystemMenu|#PB_Window_ScreenCentered)
StartDrawing(WindowOutput(0))
DrawText(20,50,"But I can't manage it because ElapsedMilliseconds()",0,RGB(227,227,227))
DrawText(20,80,"only updates once every 15 milliseconds",0,RGB(227,227,227))
DrawText(20,110,"so I take 15 seconds to go away",0,RGB(227,227,227))
StopDrawing()
i=1000
time=ElapsedMilliseconds()
t=0
Repeat
ev=WindowEvent()
t1=ElapsedMilliseconds()
If t1-t>1
TimerProc()
t=t1
EndIf
Until ev=#PB_Event_CloseWindow Or i < 1
Debug (ElapsedMilliseconds()-time)/1000
Code: Select all
; Proof that ElapsedMilliseconds() updates 65 times
; per second, not 1000 as one might expect
; Instead of a list of 1000 values of t, each 1 higher
; than the last, we get 65 changes, each about 15 higher
; than the last.
DisableDebugger
Dim listof_ts(1000)
t=ElapsedMilliseconds()
t1=0
t2=0
quit=0
i=0
While quit=0
t1=ElapsedMilliseconds()
If t1-t2 > 0 ; ems() has changed
listof_ts(i)=t1 ; so store new value
t2=t1
i+1
EndIf
If t1-t>1000
quit=1
EndIf
Wend
EnableDebugger
numchanges=0
For i = 1 To 1000
If listof_ts(i)<>0
numchanges+1
Debug listof_ts(i)
EndIf
Next
Debug numchanges
Here is a better way:
Code: Select all
; This used to be state of the art in hi-res timing
; PBOSL's hi-res timer is based on this API
; It works pretty well but I'm not sure if it's safe in dual-core processors
Procedure TimerProc(a,b,c,d,e)
Shared i
i-1
EndProcedure
OpenWindow(0,0,0,320,240,"I go away in 1 second",#PB_Window_SystemMenu|#PB_Window_ScreenCentered)
timeSetEvent_(1,0,@TimerProc(),0,#TIME_PERIODIC) ;This will fire once per millisec
i=1000
time=ElapsedMilliseconds()
Repeat
ev=WindowEvent()
Until ev=#PB_Event_CloseWindow Or i < 1
timeKillEvent_($10)
Debug (ElapsedMilliseconds()-time)/1000
http://msdn.microsoft.com/library/defau ... essors.asp
[edit] If anyone knows if the timeSetEvent_() API method is vulnerable to the dual-core hazards or not, I would appreciate some feedback to this topic.
And here is a little implementation of it using PB v4.0's new Quad type:
Code: Select all
; Want an event that fires 3500 times per millisecond?
; Now with quads in PB v4 you can get it easily
QueryPerformanceFrequency_(@maxfreq.q)
If maxfreq <> 0
eventspermicrosecond.l=maxfreq/1000000 ; This evaluates to 3 on my machine
If eventspermicrosecond < 1 ; That's 3 million events per second
eventspermicrosecond = 1
EndIf
Else
Debug "Can't do the test"
EndIf
DisableDebugger
Procedure TimerProc()
Shared j
j+1
EndProcedure
OpenWindow(0,0,0,320,240,"I go away in 1 second",#PB_Window_SystemMenu|#PB_Window_ScreenCentered)
j=0
time=ElapsedMilliseconds()
QueryPerformanceCounter_(@t.q)
Repeat
ev=WindowEvent()
QueryPerformanceCounter_(@t1.q) ;The new standard in hi-res timing,
If t1-t>=eventspermicrosecond ;this will fire once per microsecond
TimerProc() ;without fail - it is even capable of
t=t1 ;higher resolution than that but actual
EndIf ;performance will be slowed by program overhead
Until ev=#PB_Event_CloseWindow Or ElapsedMilliseconds()-time > 1000
EnableDebugger
Debug j ; My actual measured performance is 950,000 events in 1 second
; With debugger enabled it is around 600,000