Page 1 of 2
High Resolution Timer Research
Posted: Sun Mar 04, 2012 9:39 pm
by Guimauve
Hello everyone,
I currently experimenting with some of depth time function in the "UNIX" based operating system (Linux, Mac OS, FreeBSD and so on)
I have found a web site (
http://www.songho.ca/misc/timer/timer.html) describing the way about how to create a High Resolution Timer class in C++. The following code is inspired from this example but I don't know if I do a mistake or it's normal but "gettimeofday()" function is supposed to fill this structure :
Code: Select all
Structure TimeVal
Second.l
MicroSecond.l
EndStructure
but the MicroSecond field value is always equal to "0". Any clue about this ?
Thanks beforehand.
Guimauve
Code: Select all
; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
; Project name : High Resolution Timer Research
; File Name : High Res Timer.pb
; File version: 1.0.0
; Programming : Bugged or inappropriate use of gettimeofday()
; Programmed by : Guimauve
; Date : 04-03-2012
; Last Update : 04-03-2012
; PureBasic code : 4.61 Beta 1 x 64
; Platform : Linux, MacOS X
; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
; Source : http://www.songho.ca/misc/timer/timer.html
;
; This is an experience to create a High Resolution Timer
; all platform compilant.
;
; For Windows :
; - QueryPerformanceCounter_()
; - QueryPerformanceFrequency_()
;
; For Linux, MacOS or any UNIX Based operating systems
; - gettimeofday()
;
; For Windows it's already OK (Tested by many forum
; members) but on a UNIX Based system it don't work
; properly. Apparently the "gettimeofday()" return
; the MicroSecond always equal to "0".
;
; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
Structure TimeVal
Second.l
MicroSecond.l
EndStructure
Macro GetTimeValSecond(TimeValA)
TimeValA\Second
EndMacro
Macro GetTimeValMicroSecond(TimeValA)
TimeValA\MicroSecond
EndMacro
Macro ResetTimeVal(TimeValA)
GetTimeValSecond(TimeValA) = 0
GetTimeValMicroSecond(TimeValA) = 0
EndMacro
; The "TimeZone" Structure has been declared here only
; to Import the "gettimeofday()" function. It should not
; be used anywere.
Structure TimeZone
MinutesWest.L
DestinationTime.l
EndStructure
ImportC ""
gettimeofday(*TimeValA.TimeVal, *TimeZoneA.TimeZone)
EndImport
Var1.TimeVal
Var2.TimeVal
WaitTime.l = 3498
gettimeofday(@Var1, #Null)
Delay(WaitTime)
gettimeofday(@Var2, #Null)
EllipsedTime.d = (Var2\second - Var1\second) * 1000000 + (Var2\Microsecond - Var1\Microsecond)
Debug StrD(EllipsedTime, 10)
Debug "; If you see something very different from " + Str((WaitTime * 1000)) + " you should call the Houston Space Center and say :"
Debug "; " + Chr(34) + "Houston we have a Problem !" + Chr(34)
Delta = Int(Abs(EllipsedTime - WaitTime * 1000))
Debug "; The MicroSecond Delta is : " + Str(Delta)
If Delta > 5000
Debug "; Completely unacceptable For High Resolution Timer"
Else
Debug "; Accaptable for High Resolution Timer"
EndIf
; <<<<<<<<<<<<<<<<<<<<<<<
; <<<<< END OF FILE <<<<<
; <<<<<<<<<<<<<<<<<<<<<<<
Re: High Resolution Timer Research
Posted: Sun Mar 04, 2012 11:13 pm
by dhouston
Re: High Resolution Timer Research
Posted: Mon Mar 05, 2012 2:18 am
by Guimauve
I will take a look, thanks.
Best regards.
Guimauve
Re: High Resolution Timer Research
Posted: Mon Mar 05, 2012 7:07 am
by wilbert
@Guimauve, on OS X and Ubuntu 11 your code works fine.
gettimeofday does return microseconds on OS X as well as on Ubuntu 11 (on my computer).
For OS X you can also use nanoseconds as I posted yesterday
http://www.purebasic.fr/english/viewtop ... 19&t=49359
Re: High Resolution Timer Research
Posted: Mon Mar 05, 2012 12:44 pm
by Guimauve
wilbert wrote:@Guimauve, on OS X and Ubuntu 11 your code works fine.
gettimeofday does return microseconds on OS X as well as on Ubuntu 11 (on my computer).
For OS X you can also use nanoseconds as I posted yesterday
http://www.purebasic.fr/english/viewtop ... 19&t=49359
Code: Select all
; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
; AUTOMATICALLY GENERATED CODE, DO NOT MODIFY
; UNLESS YOU REALLY, REALLY, REALLY MEAN IT !!
; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
; Code generated by : Dev-Type V3.139.671
; Project name : High Resolution Timer
; File name : HighResTimer.pb
; File Version : 0.1.9
; Programmation : In progress
; Programmed by : Guimauve
; Creation Date : 04-03-2012
; Last update : 04-03-2012
; Coded for PureBasic V4.60
; Platform : Windows, Linux, MacOS X
; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
; Notes :
;
; This is a Try to create a Windows, Linux and
; MacOS X compliant High Resolution Timer sustem.
;
; It's insperated from Timer Class found here :
; http://www.songho.ca/misc/timer/timer.html
;
; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
CompilerIf #PB_Compiler_OS <> #PB_OS_Windows
Structure TimeVal
Second.l
MicroSecond.l
EndStructure
Macro GetTimeValSecond(TimeValA)
TimeValA\Second
EndMacro
Macro GetTimeValMicroSecond(TimeValA)
TimeValA\MicroSecond
EndMacro
Macro ResetTimeVal(TimeValA)
GetTimeValSecond(TimeValA) = 0
GetTimeValMicroSecond(TimeValA) = 0
EndMacro
; The "TimeZone" Structure has been declared here only
; to Import the "gettimeofday()" function. It should not
; be used anywere.
Structure TimeZone
MinutesWest.L
DestinationTime.l
EndStructure
ImportC ""
gettimeofday(*TimeValA.TimeVal, *TimeZoneA.TimeZone)
EndImport
CompilerEndIf
; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
; <<<<< Structure declaration <<<<<
Structure HighResTimer
Stopped.b
StartMicroSec.d
StopMicroSec.d
CompilerIf #PB_Compiler_OS = #PB_OS_Windows
Frequency.q
StartCount.q
EndCount.q
CompilerElse
StartCount.TimeVal
EndCount.TimeVal
CompilerEndIf
EndStructure
; <<<<<<<<<<<<<<<<<<<<<<<<<<<
; <<<<< The observators <<<<<
Macro GetHighResTimerStopped(HighResTimerA)
HighResTimerA\Stopped
EndMacro
Macro GetHighResTimerStartMicroSec(HighResTimerA)
HighResTimerA\StartMicroSec
EndMacro
Macro GetHighResTimerStopMicroSec(HighResTimerA)
HighResTimerA\StopMicroSec
EndMacro
CompilerIf #PB_Compiler_OS = #PB_OS_Windows
Macro GetHighResTimerFrequency(HighResTimerA)
HighResTimerA\Frequency
EndMacro
Macro GetHighResTimerStartCount(HighResTimerA)
HighResTimerA\StartCount
EndMacro
Macro GetHighResTimerEndCount(HighResTimerA)
HighResTimerA\EndCount
EndMacro
CompilerElse
Macro GetHighResTimerStartCount(HighResTimerA)
HighResTimerA\StartCount
EndMacro
Macro GetHighResTimerEndCount(HighResTimerA)
HighResTimerA\EndCount
EndMacro
CompilerEndIf
; <<<<<<<<<<<<<<<<<<<<<<<<
; <<<<< The mutators <<<<<
Macro SetHighResTimerStopped(HighResTimerA, P_Stopped)
GetHighResTimerStopped(HighResTimerA) = P_Stopped
EndMacro
Macro SetHighResTimerStartMicroSec(HighResTimerA, P_StartMicroSec)
GetHighResTimerStartMicroSec(HighResTimerA) = P_StartMicroSec
EndMacro
Macro SetHighResTimerStopMicroSec(HighResTimerA, P_StopMicroSec)
GetHighResTimerStopMicroSec(HighResTimerA) = P_StopMicroSec
EndMacro
CompilerIf #PB_Compiler_OS = #PB_OS_Windows
Macro SetHighResTimerFrequency(HighResTimerA, P_Frequency)
GetHighResTimerFrequency(HighResTimerA) = P_Frequency
EndMacro
Macro SetHighResTimerStartCount(HighResTimerA, P_StartCount)
GetHighResTimerStartCount(HighResTimerA) = P_StartCount
EndMacro
Macro SetHighResTimerEndCount(HighResTimerA, P_EndCount)
GetHighResTimerEndCount(HighResTimerA) = P_EndCount
EndMacro
CompilerElse
Macro SetHighResTimerStartCount(HighResTimerA, P_StartCount)
CopyTimeVal(P_StartCount, GetHighResTimerStartCount(HighResTimerA))
EndMacro
Macro SetHighResTimerEndCount(HighResTimerA, P_EndCount)
CopyTimeVal(P_EndCount, GetHighResTimerEndCount(HighResTimerA))
EndMacro
CompilerEndIf
; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
; <<<<< The Reset operator <<<<<
Macro ResetHighResTimer(HighResTimerA)
SetHighResTimerStopped(HighResTimerA, 0)
SetHighResTimerStartMicroSec(HighResTimerA, 0.0)
SetHighResTimerStopMicroSec(HighResTimerA, 0.0)
CompilerIf #PB_Compiler_OS = #PB_OS_Windows
SetHighResTimerFrequency(HighResTimerA, 0)
SetHighResTimerStartCount(HighResTimerA, 0)
SetHighResTimerEndCount(HighResTimerA, 0)
CompilerElse
ResetTimeVal(GetHighResTimerStartCount(HighResTimerA))
ResetTimeVal(GetHighResTimerEndCount(HighResTimerA))
CompilerEndIf
EndMacro
; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
; <<<<< Code generated in : 00.010 seconds (17200.00 lines/second) <<<<<
; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
Macro HighResTimerElapsedMilliSec(HighResTimerA)
(HighResTimerElapsedMicroSec(HighResTimerA) * 0.001)
EndMacro
Macro HighResTimerElapsedSec(HighResTimerA)
(HighResTimerElapsedMicroSec(HighResTimerA) * 0.000001)
EndMacro
; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
; <<<<< The Initialize operator <<<<<
Procedure InitializeHighResTimer(*HighResTimerA.HighResTimer)
ResetHighResTimer(*HighResTimerA)
CompilerIf #PB_Compiler_OS = #PB_OS_Windows
QueryPerformanceFrequency_(@GetHighResTimerFrequency(*HighResTimerA))
CompilerElse
ResetTimeVal(GetHighResTimerStartCount(*HighResTimerA))
ResetTimeVal(GetHighResTimerEndCount(*HighResTimerA))
CompilerEndIf
EndProcedure
; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
; <<<<< The Start operator <<<<<
Procedure StartHighResTimer(*HighResTimerA.HighResTimer)
SetHighResTimerStopped(*HighResTimerA, #False)
CompilerIf #PB_Compiler_OS = #PB_OS_Windows
If GetHighResTimerFrequency(*HighResTimerA) = 0
InitializeHighResTimer(*HighResTimerA.HighResTimer)
EndIf
QueryPerformanceCounter_(@GetHighResTimerStartCount(*HighResTimerA))
CompilerElse
gettimeofday(@GetHighResTimerStartCount(*HighResTimerA), #Null)
CompilerEndIf
EndProcedure
; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<
; <<<<< The Stop operator <<<<<
Procedure StopHighResTimer(*HighResTimerA.HighResTimer)
SetHighResTimerStopped(*HighResTimerA, #True)
CompilerIf #PB_Compiler_OS = #PB_OS_Windows
QueryPerformanceCounter_(@GetHighResTimerEndCount(HighResTimerA))
CompilerElse
gettimeofday(@GetHighResTimerEndCount(*HighResTimerA), #Null)
CompilerEndIf
EndProcedure
; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
; <<<<< The ElapsedMicroSec <<<<<
Procedure.d HighResTimerElapsedMicroSec(*HighResTimerA.HighResTimer)
CompilerIf #PB_Compiler_OS = #PB_OS_Windows
If GetHighResTimerStopped(*HighResTimerA) = #False
QueryPerformanceCounter_(@GetHighResTimerEndCount(*HighResTimerA))
EndIf
SetHighResTimerStartMicroSec(*HighResTimerA, GetHighResTimerStartCount(*HighResTimerA) * (1000000.0 / GetHighResTimerFrequency(*HighResTimerA)))
SetHighResTimerStopMicroSec(*HighResTimerA, GetHighResTimerEndCount(*HighResTimerA) * (1000000.0 / GetHighResTimerFrequency(*HighResTimerA)))
CompilerElse
If GetHighResTimerStopped(*HighResTimerA) = #False
gettimeofday(@GetHighResTimerEndCount(*HighResTimerA), #Null)
EndIf
SetHighResTimerStartMicroSec(*HighResTimerA, (GetTimeValSecond(GetHighResTimerStartCount(*HighResTimerA)) * 1000000.0) + GetTimeValMicroSecond(GetHighResTimerStartCount(*HighResTimerA)))
SetHighResTimerStopMicroSec(*HighResTimerA, (GetTimeValSecond(GetHighResTimerEndCount(*HighResTimerA)) * 1000000.0) + GetTimeValMicroSecond(GetHighResTimerStartCount(*HighResTimerA)))
CompilerEndIf
ProcedureReturn GetHighResTimerStopMicroSec(*HighResTimerA) - GetHighResTimerStartMicroSec(*HighResTimerA)
EndProcedure
; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
; <<<<< !!! WARNING - YOU ARE NOW IN A TESTING ZONE - WARNING !!! <<<<<
; <<<<< !!! WARNING - THIS CODE SHOULD BE COMMENTED - WARNING !!! <<<<<
; <<<<< !!! WARNING - BEFORE THE FINAL COMPILATION. - WARNING !!! <<<<<
; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
StartHighResTimer(HResTimer.HighResTimer)
Delay(5)
Debug StrD(HighResTimerElapsedMicroSec(HResTimer), 6)
Delay(50)
Debug StrD(HighResTimerElapsedMicroSec(HResTimer), 6)
Delay(499)
Debug StrD(HighResTimerElapsedMicroSec(HResTimer), 6)
Delay(500)
Debug StrD(HighResTimerElapsedMicroSec(HResTimer), 6)
Delay(1499)
Debug StrD(HighResTimerElapsedMicroSec(HResTimer), 6)
Delay(1501)
Debug StrD(HighResTimerElapsedMicroSec(HResTimer), 6)
; <<<<<<<<<<<<<<<<<<<<<<<
; <<<<< END OF FILE <<<<<
; <<<<<<<<<<<<<<<<<<<<<<<
For me with computer with Linux Mint 12 x64 the debugger output show this :
0.000000
0.000000
0.000000
1000000.000000
2000000.000000
4000000.000000
It's exactly like the time is rounded to the nearest second. If this command work properly, it should return something on after the Delay(5), Delay(50) and Delay(499) but always 0.000000.
I say it's not normal or I have some wrong BIOS settings, I don't know.
Best regards
Guimauve
Re: High Resolution Timer Research
Posted: Mon Mar 05, 2012 1:07 pm
by wilbert
Are you sure the problem isn't somewhere else in your code ?
The code you posted above also gives results on OS X that end on all zeros while I'm 100% sure the api call itself does fill the microseconds part.
Linux - nanosecond - alternative based on this thread
http://www.purebasic.fr/english/viewtop ... 15&t=38826
Code: Select all
#CLOCK_MONOTONIC = 1
ImportC "-lrt"
clock_gettime(clk_id, *tp)
EndImport
Structure timespec
tv_sec.i; /* seconds */
tv_nsec.l; /* nanoseconds [0 .. 999999999] */
EndStructure
clock_gettime(#CLOCK_MONOTONIC, @start_time.timespec)
Delay(75)
clock_gettime(#CLOCK_MONOTONIC, @end_time.timespec)
delta.q = (end_time\tv_sec - start_time\tv_sec) * 1e9 + end_time\tv_nsec - start_time\tv_nsec
Debug delta
Re: High Resolution Timer Research
Posted: Mon Mar 05, 2012 3:35 pm
by Guimauve
Thanks Wilbert, I finally get it to work.
Code: Select all
; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
; AUTOMATICALLY GENERATED CODE, DO NOT MODIFY
; UNLESS YOU REALLY, REALLY, REALLY MEAN IT !!
; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
; Code generated by : Dev-Type V3.139.671
; Project name : High Resolution Timer
; File name : HighResTimer.pb
; File Version : 1.0.0
; Programmation : OK
; Programmed by : Guimauve
; Creation Date : 04-03-2012
; Last update : 04-03-2012
; Coded for PureBasic V4.60
; Platform : Windows, Linux, MacOS X
; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
; Notes :
;
; This is a Try to create a Windows, Linux and
; MacOS X compliant High Resolution Timer sustem.
;
; It's insperated from Timer Class found here :
; http://www.songho.ca/misc/timer/timer.html
;
; Additional Code :
;
; - Wilbert (PureBasic English Forum)
;
; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
CompilerSelect #PB_Compiler_OS
CompilerCase #PB_OS_Linux
#CLOCK_MONOTONIC = 1
Structure TimeSpec
Second.i
NanoSecond.l
EndStructure
Macro GetTimeSpecSecond(TimeSpecA)
TimeSpecA\Second
EndMacro
Macro GetTimeSpecNanoSecond(TimeSpecA)
TimeSpecA\NanoSecond
EndMacro
Macro ResetTimeSpec(TimeSpecA)
GetTimeSpecSecond(TimeSpecA) = 0
GetTimeSpecNanoSecond(TimeSpecA) = 0
EndMacro
ImportC "-lrt"
clock_gettime(ClockID.l, *TimeSpecA.TimeSpec)
EndImport
CompilerCase #PB_OS_MacOS
ImportC "/System/Library/Frameworks/CoreServices.framework/CoreServices"
mach_absolute_time.q()
EndImport
CompilerEndSelect
; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
; <<<<< Structure declaration <<<<<
Structure HighResTimer
Stopped.b
StartMicroSec.q
StopMicroSec.q
CompilerSelect #PB_Compiler_OS
CompilerCase #PB_OS_Windows
Frequency.q
StartCount.q
EndCount.q
CompilerCase #PB_OS_Linux
StartCount.TimeSpec
EndCount.TimeSpec
CompilerCase #PB_OS_MacOS
StartCount.q
EndCount.q
CompilerEndSelect
EndStructure
; <<<<<<<<<<<<<<<<<<<<<<<<<<<
; <<<<< The observators <<<<<
Macro GetHighResTimerStopped(HighResTimerA)
HighResTimerA\Stopped
EndMacro
Macro GetHighResTimerStartMicroSec(HighResTimerA)
HighResTimerA\StartMicroSec
EndMacro
Macro GetHighResTimerStopMicroSec(HighResTimerA)
HighResTimerA\StopMicroSec
EndMacro
CompilerSelect #PB_Compiler_OS
CompilerCase #PB_OS_Windows
Macro GetHighResTimerFrequency(HighResTimerA)
HighResTimerA\Frequency
EndMacro
Macro GetHighResTimerStartCount(HighResTimerA)
HighResTimerA\StartCount
EndMacro
Macro GetHighResTimerEndCount(HighResTimerA)
HighResTimerA\EndCount
EndMacro
CompilerCase #PB_OS_Linux
Macro GetHighResTimerStartCount(HighResTimerA)
HighResTimerA\StartCount
EndMacro
Macro GetHighResTimerEndCount(HighResTimerA)
HighResTimerA\EndCount
EndMacro
CompilerCase #PB_OS_MacOS
Macro GetHighResTimerStartCount(HighResTimerA)
HighResTimerA\StartCount
EndMacro
Macro GetHighResTimerEndCount(HighResTimerA)
HighResTimerA\EndCount
EndMacro
CompilerEndSelect
; <<<<<<<<<<<<<<<<<<<<<<<<
; <<<<< The mutators <<<<<
Macro SetHighResTimerStopped(HighResTimerA, P_Stopped)
GetHighResTimerStopped(HighResTimerA) = P_Stopped
EndMacro
Macro SetHighResTimerStartMicroSec(HighResTimerA, P_StartMicroSec)
GetHighResTimerStartMicroSec(HighResTimerA) = P_StartMicroSec
EndMacro
Macro SetHighResTimerStopMicroSec(HighResTimerA, P_StopMicroSec)
GetHighResTimerStopMicroSec(HighResTimerA) = P_StopMicroSec
EndMacro
CompilerSelect #PB_Compiler_OS
CompilerCase #PB_OS_Windows
Macro SetHighResTimerFrequency(HighResTimerA, P_Frequency)
GetHighResTimerFrequency(HighResTimerA) = P_Frequency
EndMacro
Macro SetHighResTimerStartCount(HighResTimerA, P_StartCount)
GetHighResTimerStartCount(HighResTimerA) = P_StartCount
EndMacro
Macro SetHighResTimerEndCount(HighResTimerA, P_EndCount)
GetHighResTimerEndCount(HighResTimerA) = P_EndCount
EndMacro
CompilerCase #PB_OS_Linux
Macro SetHighResTimerStartCount(HighResTimerA, P_StartCount)
CopyTimeSpec(P_StartCount, GetHighResTimerStartCount(HighResTimerA))
EndMacro
Macro SetHighResTimerEndCount(HighResTimerA, P_EndCount)
CopyTimeSpec(P_EndCount, GetHighResTimerEndCount(HighResTimerA))
EndMacro
CompilerCase #PB_OS_MacOS
Macro SetHighResTimerStartCount(HighResTimerA, P_StartCount)
GetHighResTimerStartCount(HighResTimerA) = P_StartCount
EndMacro
Macro SetHighResTimerEndCount(HighResTimerA, P_EndCount)
GetHighResTimerEndCount(HighResTimerA) = P_EndCount
EndMacro
CompilerEndSelect
; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
; <<<<< The Reset operator <<<<<
Macro ResetHighResTimer(HighResTimerA)
SetHighResTimerStopped(HighResTimerA, 0)
SetHighResTimerStartMicroSec(HighResTimerA, 0.0)
SetHighResTimerStopMicroSec(HighResTimerA, 0.0)
CompilerSelect #PB_Compiler_OS
CompilerCase #PB_OS_Windows
SetHighResTimerFrequency(HighResTimerA, 0)
SetHighResTimerStartCount(HighResTimerA, 0)
SetHighResTimerEndCount(HighResTimerA, 0)
CompilerCase #PB_OS_Linux
ResetTimeSpec(GetHighResTimerStartCount(HighResTimerA))
ResetTimeSpec(GetHighResTimerEndCount(HighResTimerA))
CompilerCase #PB_OS_MacOS
SetHighResTimerStartCount(HighResTimerA, 0)
SetHighResTimerEndCount(HighResTimerA, 0)
CompilerEndSelect
EndMacro
; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
; <<<<< Code generated in : 00.010 seconds (17200.00 lines/second) <<<<<
; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
Macro HighResTimerElapsedMilliSec(HighResTimerA)
(HighResTimerElapsedMicroSec(HighResTimerA) * 0.001)
EndMacro
Macro HighResTimerElapsedSec(HighResTimerA)
(HighResTimerElapsedMicroSec(HighResTimerA) * 0.000001)
EndMacro
; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
; <<<<< The Initialize operator <<<<<
Procedure InitializeHighResTimer(*HighResTimerA.HighResTimer)
ResetHighResTimer(*HighResTimerA)
CompilerIf #PB_Compiler_OS = #PB_OS_Windows
QueryPerformanceFrequency_(@GetHighResTimerFrequency(*HighResTimerA))
CompilerEndIf
EndProcedure
; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
; <<<<< The Start operator <<<<<
Procedure StartHighResTimer(*HighResTimerA.HighResTimer)
SetHighResTimerStopped(*HighResTimerA, #False)
CompilerSelect #PB_Compiler_OS
CompilerCase #PB_OS_Windows
If GetHighResTimerFrequency(*HighResTimerA) = 0
InitializeHighResTimer(*HighResTimerA.HighResTimer)
EndIf
QueryPerformanceCounter_(@GetHighResTimerStartCount(*HighResTimerA))
CompilerCase #PB_OS_Linux
clock_gettime(#CLOCK_MONOTONIC, @GetHighResTimerStartCount(*HighResTimerA))
CompilerCase #PB_OS_MacOS
SetHighResTimerStartCount(HighResTimerA, mach_absolute_time())
CompilerEndSelect
EndProcedure
; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<
; <<<<< The Stop operator <<<<<
Procedure StopHighResTimer(*HighResTimerA.HighResTimer)
SetHighResTimerStopped(*HighResTimerA, #True)
CompilerSelect #PB_Compiler_OS
CompilerCase #PB_OS_Windows
QueryPerformanceCounter_(@GetHighResTimerEndCount(*HighResTimerA))
CompilerCase #PB_OS_Linux
clock_gettime(#CLOCK_MONOTONIC, @GetHighResTimerEndCount(*HighResTimerA))
CompilerCase #PB_OS_MacOS
SetHighResTimerEndCount(HighResTimerA, mach_absolute_time())
CompilerEndSelect
EndProcedure
; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
; <<<<< The ElapsedMicroSec <<<<<
Procedure.q HighResTimerElapsedMicroSec(*HighResTimerA.HighResTimer)
CompilerSelect #PB_Compiler_OS
CompilerCase #PB_OS_Windows
If GetHighResTimerStopped(*HighResTimerA) = #False
QueryPerformanceCounter_(@GetHighResTimerEndCount(*HighResTimerA))
EndIf
SetHighResTimerStartMicroSec(*HighResTimerA, GetHighResTimerStartCount(*HighResTimerA) * (1000000 / GetHighResTimerFrequency(*HighResTimerA)))
SetHighResTimerStopMicroSec(*HighResTimerA, GetHighResTimerEndCount(*HighResTimerA) * (1000000 / GetHighResTimerFrequency(*HighResTimerA)))
CompilerCase #PB_OS_Linux
If GetHighResTimerStopped(*HighResTimerA) = #False
clock_gettime(#CLOCK_MONOTONIC, @GetHighResTimerEndCount(*HighResTimerA))
EndIf
SetHighResTimerStartMicroSec(*HighResTimerA, GetTimeSpecSecond(GetHighResTimerStartCount(*HighResTimerA)) * 1000000 + GetTimeSpecNanoSecond(GetHighResTimerStartCount(*HighResTimerA)) / 1000)
SetHighResTimerStopMicroSec(*HighResTimerA, GetTimeSpecSecond(GetHighResTimerEndCount(*HighResTimerA)) * 1000000 + GetTimeSpecNanoSecond(GetHighResTimerEndCount(*HighResTimerA)) / 1000)
CompilerCase #PB_OS_MacOS
If GetHighResTimerStopped(*HighResTimerA) = #False
SetHighResTimerEndCount(HighResTimerA, mach_absolute_time())
EndIf
SetHighResTimerStartMicroSec(*HighResTimerA, GetHighResTimerStartMicroSec(*HighResTimerA) / 1000)
SetHighResTimerStopMicroSec(*HighResTimerA, GetHighResTimerStopMicroSec(*HighResTimerA) / 1000)
CompilerEndSelect
ProcedureReturn GetHighResTimerStopMicroSec(*HighResTimerA) - GetHighResTimerStartMicroSec(*HighResTimerA)
EndProcedure
; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
; <<<<< !!! WARNING - YOU ARE NOW IN A TESTING ZONE - WARNING !!! <<<<<
; <<<<< !!! WARNING - THIS CODE SHOULD BE COMMENTED - WARNING !!! <<<<<
; <<<<< !!! WARNING - BEFORE THE FINAL COMPILATION. - WARNING !!! <<<<<
; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
StartHighResTimer(HResTimer.HighResTimer)
Delay(1)
Debug HighResTimerElapsedMicroSec(HResTimer)
Delay(5)
Debug HighResTimerElapsedMicroSec(HResTimer)
Delay(499)
Debug HighResTimerElapsedMicroSec(HResTimer)
Delay(500)
Debug HighResTimerElapsedMicroSec(HResTimer)
Delay(1499)
Debug HighResTimerElapsedMicroSec(HResTimer)
Delay(1501)
Debug HighResTimerElapsedMicroSec(HResTimer)
; <<<<<<<<<<<<<<<<<<<<<<<
; <<<<< END OF FILE <<<<<
; <<<<<<<<<<<<<<<<<<<<<<<
Then the Debugger output :
1058
6138
505244
1005381
2504528
4005675
Best regards
Guimauve
Re: High Resolution Timer Research
Posted: Mon Mar 05, 2012 4:20 pm
by wilbert
Glad you got it to work
A little remark on OS X ... mach_absolute_time() like you are using now is the best function to use since it is very fast.
The return value however is absolute time. On most systems this seems to be identical to nanoseconds but it is not guaranteed to be so.
To make sure you get nanoseconds, you can use a simple conversion function or convert it yourself
Code: Select all
Structure tb_info
numer.l
denom.l
EndStructure
ImportC ""
mach_absolute_time.q()
mach_timebase_info(*info)
EndImport
mach_timebase_info(@info.tb_info)
micro_conv.d = 1e-3 * info\numer / info\denom
abs_time.q = mach_absolute_time()
micro_time.q = abs_time * micro_conv
AbsoluteToNanoseconds from the CoreServices framework is the easy way.
The other (more low level) way is to get information using mach_timebase_info once and when you want to convert absolute time to nanoseconds, multiply by numer and divide by denom.
Since you want microseconds, the easiest way is maybe to add a double precision value to your timer structure for OS X that you initialize once and multiply by that like the example above.
Re: High Resolution Timer Research
Posted: Mon Mar 05, 2012 5:20 pm
by Guimauve
wilbert wrote:Glad you got it to work
A little remark on OS X ... mach_absolute_time() like you are using now is the best function to use since it is very fast.
The return value however is absolute time. On most systems this seems to be identical to nanoseconds but it is not guaranteed to be so.
To make sure you get nanoseconds, you can use a simple conversion function or convert it yourself
AbsoluteToNanoseconds from the CoreServices framework is the easy way.
The other (more low level) way is to get information using mach_timebase_info once and when you want to convert absolute time to nanoseconds, multiply by numer and divide by denom.
Since you want microseconds, the easiest way is maybe to add a double precision value to your timer structure for OS X that you initialize once and multiply by that like the example above.
Like this :
Code: Select all
; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
; AUTOMATICALLY GENERATED CODE, DO NOT MODIFY
; UNLESS YOU REALLY, REALLY, REALLY MEAN IT !!
; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
; Code generated by : Dev-Type V3.139.671
; Project name : High Resolution Timer
; File name : HighResTimer.pb
; File Version : 1.1.0
; Programmation : OK
; Programmed by : Guimauve
; Creation Date : 04-03-2012
; Last update : 05-03-2012
; Coded for PureBasic V4.60
; Platform : Windows, Linux, MacOS X
; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
; Notes :
;
; This is a Windows, Linux and MacOS X compliant
; High Resolution Timer sustem.
;
; It's insperated from Timer Class found here :
; http://www.songho.ca/misc/timer/timer.html
;
; Additional Code
; - Wilbert (PureBasic English Forum)
;
; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
CompilerSelect #PB_Compiler_OS
CompilerCase #PB_OS_Linux
#CLOCK_MONOTONIC = 1
Structure TimeSpec
Second.i
NanoSecond.l
EndStructure
Macro GetTimeSpecSecond(TimeSpecA)
TimeSpecA\Second
EndMacro
Macro GetTimeSpecNanoSecond(TimeSpecA)
TimeSpecA\NanoSecond
EndMacro
Macro ResetTimeSpec(TimeSpecA)
GetTimeSpecSecond(TimeSpecA) = 0
GetTimeSpecNanoSecond(TimeSpecA) = 0
EndMacro
ImportC "-lrt"
clock_gettime(ClockID.l, *TimeSpecA.TimeSpec)
EndImport
CompilerCase #PB_OS_MacOS
Structure TimeBase
Numerator.l
Denominator.l
EndStructure
Macro GetTimeBaseNumerator(TimeBaseA)
TimeBaseA\Numerator
EndMacro
Macro GetTimeBaseDenominator(TimeBaseA)
TimeBaseA\Denominator
EndMacro
Macro ResetTimeBase(TimeBaseA)
GetTimeBaseNumerator(TimeBaseA) = 0
GetTimeBaseDenominator(TimeBaseA) = 0
EndMacro
ImportC ""
mach_absolute_time.q()
mach_timebase_info(*TimeBaseA.TimeBase)
EndImport
CompilerEndSelect
; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
; <<<<< Structure declaration <<<<<
Structure HighResTimer
Stopped.b
StartMicroSec.q
StopMicroSec.q
CompilerSelect #PB_Compiler_OS
CompilerCase #PB_OS_Windows
Frequency.q
StartCount.q
EndCount.q
CompilerCase #PB_OS_Linux
StartCount.TimeSpec
EndCount.TimeSpec
CompilerCase #PB_OS_MacOS
MicroSecConversion.d
TimeBase.TimeBase
StartCount.q
EndCount.q
CompilerEndSelect
EndStructure
; <<<<<<<<<<<<<<<<<<<<<<<<<<<
; <<<<< The observators <<<<<
Macro GetHighResTimerStopped(HighResTimerA)
HighResTimerA\Stopped
EndMacro
Macro GetHighResTimerStartMicroSec(HighResTimerA)
HighResTimerA\StartMicroSec
EndMacro
Macro GetHighResTimerStopMicroSec(HighResTimerA)
HighResTimerA\StopMicroSec
EndMacro
CompilerSelect #PB_Compiler_OS
CompilerCase #PB_OS_Windows
Macro GetHighResTimerFrequency(HighResTimerA)
HighResTimerA\Frequency
EndMacro
Macro GetHighResTimerStartCount(HighResTimerA)
HighResTimerA\StartCount
EndMacro
Macro GetHighResTimerEndCount(HighResTimerA)
HighResTimerA\EndCount
EndMacro
CompilerCase #PB_OS_Linux
Macro GetHighResTimerStartCount(HighResTimerA)
HighResTimerA\StartCount
EndMacro
Macro GetHighResTimerEndCount(HighResTimerA)
HighResTimerA\EndCount
EndMacro
CompilerCase #PB_OS_MacOS
Macro GetHighResTimerMicroSecConversion(HighResTimerA)
HighResTimerA\MicroSecConversion
EndMacro
Macro GetHighResTimerTimeBase(HighResTimerA)
HighResTimerA\TimeBase
EndMacro
Macro GetHighResTimerStartCount(HighResTimerA)
HighResTimerA\StartCount
EndMacro
Macro GetHighResTimerEndCount(HighResTimerA)
HighResTimerA\EndCount
EndMacro
CompilerEndSelect
; <<<<<<<<<<<<<<<<<<<<<<<<
; <<<<< The mutators <<<<<
Macro SetHighResTimerStopped(HighResTimerA, P_Stopped)
GetHighResTimerStopped(HighResTimerA) = P_Stopped
EndMacro
Macro SetHighResTimerStartMicroSec(HighResTimerA, P_StartMicroSec)
GetHighResTimerStartMicroSec(HighResTimerA) = P_StartMicroSec
EndMacro
Macro SetHighResTimerStopMicroSec(HighResTimerA, P_StopMicroSec)
GetHighResTimerStopMicroSec(HighResTimerA) = P_StopMicroSec
EndMacro
CompilerSelect #PB_Compiler_OS
CompilerCase #PB_OS_Windows
Macro SetHighResTimerFrequency(HighResTimerA, P_Frequency)
GetHighResTimerFrequency(HighResTimerA) = P_Frequency
EndMacro
Macro SetHighResTimerStartCount(HighResTimerA, P_StartCount)
GetHighResTimerStartCount(HighResTimerA) = P_StartCount
EndMacro
Macro SetHighResTimerEndCount(HighResTimerA, P_EndCount)
GetHighResTimerEndCount(HighResTimerA) = P_EndCount
EndMacro
CompilerCase #PB_OS_Linux
Macro SetHighResTimerStartCount(HighResTimerA, P_StartCount)
CopyTimeSpec(P_StartCount, GetHighResTimerStartCount(HighResTimerA))
EndMacro
Macro SetHighResTimerEndCount(HighResTimerA, P_EndCount)
CopyTimeSpec(P_EndCount, GetHighResTimerEndCount(HighResTimerA))
EndMacro
CompilerCase #PB_OS_MacOS
Macro SetHighResTimerMicroSecConversion(HighResTimerA, P_MicroSecConversion)
GetHighResTimerMicroSecConversion(HighResTimerA) = P_MicroSecConversion
EndMacro
Macro SetHighResTimerTimeBase(HighResTimerA, P_TimeBase)
CopyMemory(P_TimeBase, GetHighResTimerTimeBase(HighResTimerA), SizeOf(TimeBase))
EndMacro
Macro SetHighResTimerStartCount(HighResTimerA, P_StartCount)
GetHighResTimerStartCount(HighResTimerA) = P_StartCount
EndMacro
Macro SetHighResTimerEndCount(HighResTimerA, P_EndCount)
GetHighResTimerEndCount(HighResTimerA) = P_EndCount
EndMacro
CompilerEndSelect
; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
; <<<<< The Reset operator <<<<<
Macro ResetHighResTimer(HighResTimerA)
SetHighResTimerStopped(HighResTimerA, 0)
SetHighResTimerStartMicroSec(HighResTimerA, 0)
SetHighResTimerStopMicroSec(HighResTimerA, 0)
CompilerSelect #PB_Compiler_OS
CompilerCase #PB_OS_Windows
SetHighResTimerFrequency(HighResTimerA, 0)
SetHighResTimerStartCount(HighResTimerA, 0)
SetHighResTimerEndCount(HighResTimerA, 0)
CompilerCase #PB_OS_Linux
ResetTimeSpec(GetHighResTimerStartCount(HighResTimerA))
ResetTimeSpec(GetHighResTimerEndCount(HighResTimerA))
CompilerCase #PB_OS_MacOS
SetHighResTimerMicroSecConversion(HighResTimerA, 0.0)
ResetTimeBase(GetHighResTimerTimeBase(HighResTimerA))
SetHighResTimerStartCount(HighResTimerA, 0)
SetHighResTimerEndCount(HighResTimerA, 0)
CompilerEndSelect
EndMacro
; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
; <<<<< Code generated in : 00.010 seconds (17200.00 lines/second) <<<<<
; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
Macro HighResTimerElapsedMilliSec(HighResTimerA)
(HighResTimerElapsedMicroSec(HighResTimerA) * 0.001)
EndMacro
Macro HighResTimerElapsedSec(HighResTimerA)
(HighResTimerElapsedMicroSec(HighResTimerA) * 0.000001)
EndMacro
; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
; <<<<< The Initialize operator <<<<<
Procedure InitializeHighResTimer(*HighResTimerA.HighResTimer)
ResetHighResTimer(*HighResTimerA)
CompilerSelect #PB_Compiler_OS
CompilerCase #PB_OS_Windows
QueryPerformanceFrequency_(@GetHighResTimerFrequency(*HighResTimerA))
CompilerCase #PB_OS_MacOS
mach_timebase_info(@GetHighResTimerTimeBase(*HighResTimerA))
SetHighResTimerMicroSecConversion(*HighResTimerA, 1e-3 * GetTimeBaseNumerator(GetHighResTimerTimeBase(*HighResTimerA)) / GetTimeBaseDenominator(GetHighResTimerTimeBase(*HighResTimerA)))
CompilerEndSelect
EndProcedure
; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
; <<<<< The Start operator <<<<<
Procedure StartHighResTimer(*HighResTimerA.HighResTimer)
SetHighResTimerStopped(*HighResTimerA, #False)
CompilerSelect #PB_Compiler_OS
CompilerCase #PB_OS_Windows
If GetHighResTimerFrequency(*HighResTimerA) = 0
InitializeHighResTimer(*HighResTimerA)
EndIf
QueryPerformanceCounter_(@GetHighResTimerStartCount(*HighResTimerA))
CompilerCase #PB_OS_Linux
clock_gettime(#CLOCK_MONOTONIC, @GetHighResTimerStartCount(*HighResTimerA))
CompilerCase #PB_OS_MacOS
If GetHighResTimerMicroSecConversion(*HighResTimerA) = 0.0
InitializeHighResTimer(*HighResTimerA)
EndIf
SetHighResTimerStartCount(*HighResTimerA, mach_absolute_time() * GetHighResTimerMicroSecConversion(*HighResTimerA))
CompilerEndSelect
EndProcedure
; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<
; <<<<< The Stop operator <<<<<
Procedure StopHighResTimer(*HighResTimerA.HighResTimer)
SetHighResTimerStopped(*HighResTimerA, #True)
CompilerSelect #PB_Compiler_OS
CompilerCase #PB_OS_Windows
QueryPerformanceCounter_(@GetHighResTimerEndCount(*HighResTimerA))
CompilerCase #PB_OS_Linux
clock_gettime(#CLOCK_MONOTONIC, @GetHighResTimerEndCount(*HighResTimerA))
CompilerCase #PB_OS_MacOS
SetHighResTimerEndCount(*HighResTimerA, mach_absolute_time() * GetHighResTimerMicroSecConversion(*HighResTimerA))
CompilerEndSelect
EndProcedure
; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
; <<<<< The ElapsedMicroSec <<<<<
Procedure.q HighResTimerElapsedMicroSec(*HighResTimerA.HighResTimer)
CompilerSelect #PB_Compiler_OS
CompilerCase #PB_OS_Windows
If GetHighResTimerStopped(*HighResTimerA) = #False
QueryPerformanceCounter_(@GetHighResTimerEndCount(*HighResTimerA))
EndIf
SetHighResTimerStartMicroSec(*HighResTimerA, GetHighResTimerStartCount(*HighResTimerA) * (1000000 / GetHighResTimerFrequency(*HighResTimerA)))
SetHighResTimerStopMicroSec(*HighResTimerA, GetHighResTimerEndCount(*HighResTimerA) * (1000000 / GetHighResTimerFrequency(*HighResTimerA)))
CompilerCase #PB_OS_Linux
If GetHighResTimerStopped(*HighResTimerA) = #False
clock_gettime(#CLOCK_MONOTONIC, @GetHighResTimerEndCount(*HighResTimerA))
EndIf
SetHighResTimerStartMicroSec(*HighResTimerA, GetTimeSpecSecond(GetHighResTimerStartCount(*HighResTimerA)) * 1000000 + GetTimeSpecNanoSecond(GetHighResTimerStartCount(*HighResTimerA)) / 1000)
SetHighResTimerStopMicroSec(*HighResTimerA, GetTimeSpecSecond(GetHighResTimerEndCount(*HighResTimerA)) * 1000000 + GetTimeSpecNanoSecond(GetHighResTimerEndCount(*HighResTimerA)) / 1000)
CompilerCase #PB_OS_MacOS
If GetHighResTimerStopped(*HighResTimerA) = #False
SetHighResTimerEndCount(*HighResTimerA, mach_absolute_time() * GetHighResTimerMicroSecConversion(*HighResTimerA))
EndIf
SetHighResTimerStartMicroSec(*HighResTimerA, GetHighResTimerStartCount(*HighResTimerA))
SetHighResTimerStopMicroSec(*HighResTimerA, GetHighResTimerEndCount(*HighResTimerA))
CompilerEndSelect
ProcedureReturn GetHighResTimerStopMicroSec(*HighResTimerA) - GetHighResTimerStartMicroSec(*HighResTimerA)
EndProcedure
; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
; <<<<< !!! WARNING - YOU ARE NOW IN A TESTING ZONE - WARNING !!! <<<<<
; <<<<< !!! WARNING - THIS CODE SHOULD BE COMMENTED - WARNING !!! <<<<<
; <<<<< !!! WARNING - BEFORE THE FINAL COMPILATION. - WARNING !!! <<<<<
; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
StartHighResTimer(HResTimer.HighResTimer)
Delay(1)
Debug HighResTimerElapsedMicroSec(HResTimer)
Delay(5)
Debug HighResTimerElapsedMicroSec(HResTimer)
Delay(499)
Debug HighResTimerElapsedMicroSec(HResTimer)
Delay(500)
Debug HighResTimerElapsedMicroSec(HResTimer)
Delay(1499)
Debug HighResTimerElapsedMicroSec(HResTimer)
Delay(1501)
Debug HighResTimerElapsedMicroSec(HResTimer)
; <<<<<<<<<<<<<<<<<<<<<<<
; <<<<< END OF FILE <<<<<
; <<<<<<<<<<<<<<<<<<<<<<<
I don't have a Mac so I can't test this code. I hope it work !
Best regards
Guimauve
Re: High Resolution Timer Research
Posted: Mon Mar 05, 2012 5:37 pm
by wilbert
I assumed you had a Mac
I tested your code but get an error message 'Too many parameters' for this line
Macro GetHighResTimerTimeBase(HighResTimerA, P_TimeBase)
You have so many macros that I don't know where to look for a solution.
A little other remark, both information from
mach_timebase_info(..) and
QueryPerformanceFrequency_(..) does not change while the system is running so instead of adding information to each timer, you could also use a global variable for this and run these functions only once.
Re: High Resolution Timer Research
Posted: Mon Mar 05, 2012 6:16 pm
by Guimauve
wilbert wrote:I assumed you had a Mac
Of course not, I only have a old notebook with Windows XP, a more recent notebook with LinuxMint 12 and a PC also with LinuxMint 12.
wilbert wrote:I tested your code but get an error message 'Too many parameters' for this line
Macro GetHighResTimerTimeBase(HighResTimerA, P_TimeBase)
You have so many macros that I don't know where to look for a solution.
It's corrected in my previous code, It's an error in the macro definition on line 236 or something.
wilbert wrote:A little other remark, both information from mach_timebase_info(..) and QueryPerformanceFrequency_(..) does not change while the system is running so instead of adding information to each timer, you could also use a global variable for this and run these functions only once.
It's really an issue when you use many timer but when you use only one it don't change anything to have these parameters has a local field within the structure. But I can modify my code to remove them from the timer structure then set them once as a Global variables. I will do it this afternoon, now it's time to lunch.
Best regards.
Guimauve
Re: High Resolution Timer Research
Posted: Mon Mar 05, 2012 6:48 pm
by wilbert
It's complaining now about *HighResTimerA not having a structure on this line
SetHighResTimerEndCount(HighResTimerA, mach_absolute_time() * GetHighResTimerMicroSecConversion(*HighResTimerA))
For myself your code is more than I need but I like your cross platform approach.
Based on your code I put together a simple single procedure
ElapsedNanoseconds()
The Linux timings however seem to be inaccurate and vary quite a bit between difference runs.
I don't know if the clock_gettime function itself is to blame or if it has to do because my Linux runs on Virtualbox.
Code: Select all
; *** nano_time.q = ElapsedNanoseconds() ***
; EnableExplicit
CompilerSelect #PB_Compiler_OS
CompilerCase #PB_OS_Windows
Global hr_timer_conv.d
Define hr_timer_freq.q
QueryPerformanceFrequency_(@hr_timer_freq)
hr_timer_conv = 1e9
hr_timer_conv / hr_timer_freq
Procedure.q ElapsedNanoseconds()
Protected counter.q
QueryPerformanceCounter_(@counter)
ProcedureReturn counter * hr_timer_conv
EndProcedure
CompilerCase #PB_OS_Linux
#CLOCK_MONOTONIC = 1
Structure timespec
tv_sec.i
tv_nsec.l
EndStructure
ImportC "-lrt"
clock_gettime(clk_id, *tp)
EndImport
Procedure.q ElapsedNanoseconds()
Protected time.timespec
clock_gettime(#CLOCK_MONOTONIC, @time)
ProcedureReturn time\tv_sec * 1e9 + time\tv_nsec
EndProcedure
CompilerCase #PB_OS_MacOS
Structure tb_info
numer.l
denom.l
EndStructure
ImportC ""
mach_absolute_time.q()
mach_timebase_info(*info)
EndImport
Global hr_timer_conv.d
Define hr_tb_info.tb_info
mach_timebase_info(@hr_tb_info)
hr_timer_conv = hr_tb_info\numer
hr_timer_conv / hr_tb_info\denom
Procedure.q ElapsedNanoseconds()
ProcedureReturn mach_absolute_time() * hr_timer_conv
EndProcedure
CompilerEndSelect
; *** test the procedure ***
Define.q start_time, end_time
start_time = ElapsedNanoseconds()
Delay(25)
end_time = ElapsedNanoseconds()
MessageRequester("nano timing", Str(end_time - start_time))
Re: High Resolution Timer Research
Posted: Mon Mar 05, 2012 7:17 pm
by Guimauve
@Wilbert
I have just try your code, the result after 6 runs
25100222
25085239
25085865
25086024
25071758
25086026
About the complain about *HighResTimerA not having a structure on this line if you check carefully you will see the pointer don't have the asterisk symbol.
If should be
Code: Select all
SetHighResTimerEndCount(*HighResTimerA, mach_absolute_time() * GetHighResTimerMicroSecConversion(*HighResTimerA))
instead of
Code: Select all
SetHighResTimerEndCount(HighResTimerA, mach_absolute_time() * GetHighResTimerMicroSecConversion(*HighResTimerA))
I will correct this.
Best regards.
Guimauve
Re: High Resolution Timer Research
Posted: Mon Mar 05, 2012 7:26 pm
by wilbert
Line 401 and 402 have the same issue.
After correcting them to *HighResTimerA your code works fine on OS X
Thanks for your timings.
They seem more more accurate on your computer.
Re: High Resolution Timer Research
Posted: Mon Mar 05, 2012 7:37 pm
by Guimauve
wilbert wrote:Line 401 and 402 have the same issue.
After correcting them to *HighResTimerA your code works fine on OS X
Thanks for your timings.
They seem more more accurate on your computer.
Also corrected. It's fun to know it work on MacOS
It's difficult to debug a code for a specific plat-form when you don't have it. By the way I have also place your ElapsedNanoseconds() inside my toolbox, I will use it to reach a better control over the Frame rate. See
http://www.purebasic.fr/english/viewtop ... ol#p334296
But I will need a NanoSleep() ou NanoDelay() function to do it.
Best regards
Guimauve