It is currently Tue Nov 12, 2019 1:16 am

All times are UTC + 1 hour




Post new topic Reply to topic  [ 19 posts ]  Go to page 1, 2  Next
Author Message
 Post subject: High Resolution Timer Research
PostPosted: Sun Mar 04, 2012 9:39 pm 
Offline
Enthusiast
Enthusiast
User avatar

Joined: Wed Oct 22, 2003 2:51 am
Posts: 743
Location: Canada
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:
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:
; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
; 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 <<<<<
; <<<<<<<<<<<<<<<<<<<<<<<


Top
 Profile  
Reply with quote  
 Post subject: Re: High Resolution Timer Research
PostPosted: Sun Mar 04, 2012 11:13 pm 
Offline
Enthusiast
Enthusiast
User avatar

Joined: Tue Aug 21, 2007 2:44 pm
Posts: 430
Location: USA (Cincinnati)
I can't help with your problem but here are a few links I saved a couple of years back when I was researching the same issue.

http://www.kernel.org/doc/man-pages/online/pages/man2/clock_settime.2.html
http://www.kernel.org/doc/man-pages/online/pages/man2/nanosleep.2.html
http://elinux.org/High_Resolution_Timers

_________________
http://davehouston.org
Mac Mini (Intel) 10.6.8 - iMac G4 (PPC) 10.4.11
Dell Dimension 2400 W98SE,W2K,XP,Vista,W7,Debian,Ubuntu,Kubuntu,Xubuntu,Fedora,Mandriva,Mint
(on swappable HDDs)
Vizio VTAB1008 - Android 3.1
MK808 miniAndroidPC (Android 4.1)


Top
 Profile  
Reply with quote  
 Post subject: Re: High Resolution Timer Research
PostPosted: Mon Mar 05, 2012 2:18 am 
Offline
Enthusiast
Enthusiast
User avatar

Joined: Wed Oct 22, 2003 2:51 am
Posts: 743
Location: Canada
I will take a look, thanks.

Best regards.
Guimauve


Top
 Profile  
Reply with quote  
 Post subject: Re: High Resolution Timer Research
PostPosted: Mon Mar 05, 2012 7:07 am 
Offline
PureBasic Expert
PureBasic Expert

Joined: Sun Aug 08, 2004 5:21 am
Posts: 3515
Location: Netherlands
@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
viewtopic.php?f=19&t=49359


Top
 Profile  
Reply with quote  
 Post subject: Re: High Resolution Timer Research
PostPosted: Mon Mar 05, 2012 12:44 pm 
Offline
Enthusiast
Enthusiast
User avatar

Joined: Wed Oct 22, 2003 2:51 am
Posts: 743
Location: Canada
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
viewtopic.php?f=19&t=49359


Code:
; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
; 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 :

Quote:
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


Top
 Profile  
Reply with quote  
 Post subject: Re: High Resolution Timer Research
PostPosted: Mon Mar 05, 2012 1:07 pm 
Offline
PureBasic Expert
PureBasic Expert

Joined: Sun Aug 08, 2004 5:21 am
Posts: 3515
Location: Netherlands
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
viewtopic.php?f=15&t=38826
Code:
#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


Top
 Profile  
Reply with quote  
 Post subject: Re: High Resolution Timer Research
PostPosted: Mon Mar 05, 2012 3:35 pm 
Offline
Enthusiast
Enthusiast
User avatar

Joined: Wed Oct 22, 2003 2:51 am
Posts: 743
Location: Canada
Thanks Wilbert, I finally get it to work.

Code:
; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
; 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 :
Quote:
1058
6138
505244
1005381
2504528
4005675


Best regards
Guimauve


Top
 Profile  
Reply with quote  
 Post subject: Re: High Resolution Timer Research
PostPosted: Mon Mar 05, 2012 4:20 pm 
Offline
PureBasic Expert
PureBasic Expert

Joined: Sun Aug 08, 2004 5:21 am
Posts: 3515
Location: Netherlands
Glad you got it to work :D

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:
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.


Top
 Profile  
Reply with quote  
 Post subject: Re: High Resolution Timer Research
PostPosted: Mon Mar 05, 2012 5:20 pm 
Offline
Enthusiast
Enthusiast
User avatar

Joined: Wed Oct 22, 2003 2:51 am
Posts: 743
Location: Canada
wilbert wrote:
Glad you got it to work :D

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:
; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
; 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


Last edited by Guimauve on Mon Mar 05, 2012 7:30 pm, edited 3 times in total.

Top
 Profile  
Reply with quote  
 Post subject: Re: High Resolution Timer Research
PostPosted: Mon Mar 05, 2012 5:37 pm 
Offline
PureBasic Expert
PureBasic Expert

Joined: Sun Aug 08, 2004 5:21 am
Posts: 3515
Location: Netherlands
I assumed you had a Mac :shock:

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.


Top
 Profile  
Reply with quote  
 Post subject: Re: High Resolution Timer Research
PostPosted: Mon Mar 05, 2012 6:16 pm 
Offline
Enthusiast
Enthusiast
User avatar

Joined: Wed Oct 22, 2003 2:51 am
Posts: 743
Location: Canada
wilbert wrote:
I assumed you had a Mac :shock:

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


Top
 Profile  
Reply with quote  
 Post subject: Re: High Resolution Timer Research
PostPosted: Mon Mar 05, 2012 6:48 pm 
Offline
PureBasic Expert
PureBasic Expert

Joined: Sun Aug 08, 2004 5:21 am
Posts: 3515
Location: Netherlands
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:
; *** 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))


Top
 Profile  
Reply with quote  
 Post subject: Re: High Resolution Timer Research
PostPosted: Mon Mar 05, 2012 7:17 pm 
Offline
Enthusiast
Enthusiast
User avatar

Joined: Wed Oct 22, 2003 2:51 am
Posts: 743
Location: Canada
@Wilbert

I have just try your code, the result after 6 runs

Quote:
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:
SetHighResTimerEndCount(*HighResTimerA, mach_absolute_time() * GetHighResTimerMicroSecConversion(*HighResTimerA))

instead of
Code:
SetHighResTimerEndCount(HighResTimerA, mach_absolute_time() * GetHighResTimerMicroSecConversion(*HighResTimerA))


I will correct this.

Best regards.
Guimauve


Top
 Profile  
Reply with quote  
 Post subject: Re: High Resolution Timer Research
PostPosted: Mon Mar 05, 2012 7:26 pm 
Offline
PureBasic Expert
PureBasic Expert

Joined: Sun Aug 08, 2004 5:21 am
Posts: 3515
Location: Netherlands
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.


Top
 Profile  
Reply with quote  
 Post subject: Re: High Resolution Timer Research
PostPosted: Mon Mar 05, 2012 7:37 pm 
Offline
Enthusiast
Enthusiast
User avatar

Joined: Wed Oct 22, 2003 2:51 am
Posts: 743
Location: Canada
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 :D

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/viewtopic.php?f=12&t=43033&p=334296&hilit=FrameRateControl#p334296

But I will need a NanoSleep() ou NanoDelay() function to do it.

Best regards
Guimauve


Top
 Profile  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 19 posts ]  Go to page 1, 2  Next

All times are UTC + 1 hour


Who is online

Users browsing this forum: No registered users and 1 guest


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
Jump to:  

 


Powered by phpBB © 2008 phpBB Group
subSilver+ theme by Canver Software, sponsor Sanal Modifiye