No announcement yet.

Light macro timers

  • Filter
  • Time
  • Show
Clear All
new posts

  • Light macro timers

    In view of recent posts, I thought that it may be a good idea to resurrect my timer macros. However, the latest version, published some time ago, is probably much more powerful than most people's needs so below is a stripped down version.

    Essentially we may use up to 16 timers, 0 to15.

    The Performance Counter is used. In the 'old days,' the frequency varied, slightly, between Windows sessions but that is no longer the case with modern systems. On Windows 10 the frequency is 10MHz giving then a resolution of 100 nano-seconds.
    Global qFreq, qStart(), qStop() As Quad
    Global sFuncName() As String
    Macro InitializeTimers
      Dim qStart( 0 To 15) As Global Quad
      Dim qStop( 0 To 15 ) As Global Quad
      Dim sFuncName( 0 To 15 ) As Global String
      QueryPerformanceFrequency qFreq
      QueryPerformanceCounter qStart(0) ' Intel suggestion. First use may be suspect
      Reset qStart(0)
    End Macro
    Macro sPCF = LTrim$(Format$(qFreq, "###,###,###,###"))
    ' Starting & Stopping timers
    ' ********************
    Macro StartTimer(i)
      sFuncName(i) = FuncName$
      QueryPerformanceCounter qStart(i)
    End Macro
    Macro StopTimer(i) = QueryPerformanceCounter qStop(i)
    ' ********************
    ' Display
    ' In the following
    ' i is the ith timer
    ' 0 <= j <= 3 for 0 to 3 decimal places in ms
    ' 4 <= j <= 7 for 0 to 3 decimal places in µs
    ' If j > 7 then j is clipped To 7
    ' flag = 0 => non-verbose output in ms or µs only
    ' flag = 1 => verbose output including Timer index and Function name
    ' ********************
    Macro Function sTimeTaken( i, j, flag )
      MacroTemp s, k
      Local s As String, k As Long
      k = Min&(Abs(j),7)
      s = Choose$(k+4*(k>3)+1, "####", "####.#", "####.##","####.###")
      s = " " + Format$((qStop(i) - qStart(i))*IIf&(k<4, 1000, 1000000)/qFreq, s) + IIf$(k<4, "ms", "µs")
      If IsTrue flag Then
        s = "[" + LTrim$(Str$(i)) + "] in " + sFuncName(i) + s
      End If
      Reset qStart(i)
    End Macro = s
    Macro Function nTimeTaken(i)
      MacroTemp n
      Local n As Double
      n = (qStop(i) - qStart(i))*1000/qFreq
      Reset qStart(i)
    End Macro = n
    ' ********************
    Example usage:
    #Compile Exe
    #Dim All
    #Include ""
    #Include "C:\PBWin\Timers\" ' Change to your path
    Function PBMain () As Long
    Local x As Double
    Local i As Long
      InitializeTimers ' We must not forget this
      ? sTimeTaken(0,1,0)
    '  Waitkey$
    End Function
    Sub Test
    Local i As Long
    Local x As Double
        For i = 1 To 20000000
          x = Rnd
    End Sub

    With regard sTimeTaken: The first parameter is the timer index; the second parameter is 0 to 3 for 0 to 3 decimal places in milli-seconds and 4 to 7 for 0 to 3 decimal places in micro-seconds; the third parameter is 0 for non-verbose output and 1 for verbose output which includes the timer index and Function name.

    For non-verbose sTimeTaken(0,1,1) will look like this 241.7ms and in verbose will look like this [0] in TEST 241.7ms

    nTimeTaken(0) would give simply 241.6547 as a Double.

    sPCF gives, as a string, the Performance Counter Frequency. On Windows 10 that is 10,000,000.
    Last edited by David Roberts; 18 Mar 2019, 02:21 PM.

  • #2
    It is worth noting that with a PCF of 10MHz, with Windows 10, giving a resolution of 100 nano-seconds, that is one-tenth of a micro-second, then using 6 or 7 in sTimeTaken's second parameter will not work - one decimal place will be as good as it gets.

    If we enable HPET in the bios and run 'bcdedit /set useplatformclock true' (and reboot) in admin mode command prompt then the PCF increases to 14,318,180, which is what I used with Win7, and now we will get more than one decimal place with 6 or 7 in sTimeTaken's second parameter.

    I find it bizarre when we disable HPET in the bios but keep the above command prompt to find we get a PCF of 3,579,545 which is the same frequency as the crystal used for NTSC colour TVs.

    If we now run 'bcdedit /deletevalue useplatformclock' (and reboot) we get the 10MHz back.

    The jury was always 'out' on whether to enable the HPET and since it is old technology I would rather steer clear of it so I use a PCF of 10MHz. I really do not need to go beyond one decimal place in micro-second timing.

    I am not sure how Microsoft manages to provide a PCF of exactly 10MHz. Both Microsoft and Intel have done some clever stuff in recent years, the Time Stamp Counter is now invariant - that is the same for all cores.


    • #3

      In another thread party pooper Paul Dixon had the audacity to question the accuracy of my macro timers. I agree with him. The granularity of the Performance Counter is inadequate for very small timings using a Counter frequency of 14,318,180. The situation is worse with a frequency of 10MHz, the default for Windows 10.

      To err on the side of caution I am recommending that TIX be used if my macro timers return a time of less than five microseconds.