Announcement

Collapse
No announcement yet.

Comments for Timer Test

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • Comments for Timer Test

    Timer Test

    Jim, I don't know why you added the FileTime method because that is linked to the Windows real-time clock, so we should not expect much difference with GetTickCount and Timer.

    There is something else that you may look at: GetSystemTimePreciseAsFileTime. MSDN says this: "The GetSystemTimePreciseAsFileTime function retrieves the current system date and time with the highest possible level of precision (<1us)." So, the frequency is greater than 1MHz.

    We need another declaration:

    Declare Sub GetSystemTimePreciseAsFileTime Lib "Kernel32.dll" Alias "GetSystemTimePreciseAsFileTime" (lpFileTime As Quad)

    I replaced the THREAD FUNCTION ProcessFileTime() with the following:
    Code:
    Thread Function ProcessFileTimePrecise(Byval yyy As Long) AS Long
    Local i As Long
    
    GetSystemTimePreciseAsFileTime(qStart)
    '---------------------------------------
    FOR i = 0 TO iLoop : NEXT i
    '---------------------------------------
    GetSystemTimePreciseAsFileTime(qStop)
    Control Set Text hDlg, 60, ""
    Control Set Text hDlg, 60, Using$("&##.###", "", (qStop - qStart)/10000000) + " seconds"
    
    End Function
    I did quite a few runs and found that TickCount and Timer agreed quite often. QueryPerformance and TIX agreed quite often returning slightly longer results, one or two milliseconds longer than TickCount and Timer. The new code above tended to be inline with QueryPerformace and TIX; not surprisingly since its resolution is comparatively high as well.

    CAVEAT: GetSystemTimePreciseAsFileTime was introduced in Windows 8 and why it is not in the latest "WinBase.inc".
    Last edited by David Roberts; 31 Jul 2019, 09:48 PM. Reason: Missed the " at end of "seconds"

  • #2
    FileTime method because that is linked to the Windows real-time clock ...
    What is the problem with being linked to the Windows real-time?
    Dale

    Comment


    • #3
      Originally posted by Dale
      What is the problem with being linked to the Windows real-time?
      Nothing but we already had two linked to the real-time clock and it is a bit of a dog's dinner to implement compared with GetTickCount and Timer.

      Come to think of it you quoted me out of context as the sentence completed with ", so we should not expect much difference with GetTickCount and Timer."

      Comment


      • #4
        Okay.(had to ask)
        Dale

        Comment


        • #5
          Guys,
          I'm up for adding it. "More the merrier." Done!

          Comment


          • #6
            BTW, Jim, with regard THREAD FUNCTION ProcessFileTime() you did not have to use FileTimeToSystemTime(). You could have just done this:
            Code:
            THREAD FUNCTION ProcessFileTime(BYVAL yyy AS LONG) AS LONG
            LOCAL i AS LONG
            
            GetSystemTimeAsFileTime2(qStart)
            '---------------------------------------
            FOR i = 0 TO iLoop : NEXT i
            '---------------------------------------
            GetSystemTimeAsFileTime2(qStop)
            CONTROL SET TEXT hDlg, 60, ""
            CONTROL SET TEXT hDlg, 60, USING$("&##.###", "", (qStop - qStart)/10000000) + " seconds
            END FUNCTION

            Comment


            • #7
              Sweet, I'm off to see the Wizard.
              Ok, now TickCount, Timer, FileTime all display the same value. Very nice. Thank you David.

              Likely there was an inefficiency in the conversion to FileTimeToSystemTime.

              Comment


              • #8
                Ideally Version 3 should have an OS query and if older than Win8 then the FileTimePrecise button should have %WS_DISABLED.

                Added: That won't work. It will compile but on running we get a message box telling us 'Entry Point Not Found' so you should mention it in the Timer Test thread.

                Comment


                • #9
                  On second thoughts could we do an OS query in WM_INITDIALOG. If older than Win8 then add the FileTimePrecise button disabled else add the FileTimePrecise button enabled and then load the library with a 'Call Dword' when required? I am sure that we can do that.

                  Comment


                  • #10
                    Sounds like a plan. I'm in the process of updating all my machines to 1903. It may take awhile.

                    Comment


                    • #11
                      Originally posted by Jim
                      Sounds like a plan. I'm in the process of updating all my machines to 1903. It may take awhile.
                      Meanwhile since I have not played with LoadLibrary for a long time I thought I would have a crack myself. You may come up with something better, Jim, as my effort is a bit of a carry on but it works.

                      With regard OS version I found some code by Pierre Bellisle which initially uses GetVersionExW. From Win8.1 GetVersionExW depends on how the application is manifested. "Applications not manifested for Windows 8.1 or Windows 10 will return the Windows 8 OS version value (6.2). Once an application is manifested for a given operating system version, GetVersionEx will always return the version that the application is manifested for in future releases." If this occured in Pierre's code we switch to RtlGetVersion in NtDll.dll. However, GetVersionExW is ideal for our purposes as our interest is whether the host is Win8 or later. Pierre's code was then stripped down to a six line Function which, after much thought, I have called OSGreaterThanOrEqualToWin8. It returns true if the host is Win8 or later.
                      Code:
                      Function OSGreaterThanOrEqualToWin8() As Long
                      Local OsInfoEx As OSVERSIONINFOEXW
                        OsInfoEx.dwOSVersionInfoSize = SizeOf(OSVERSIONINFOEXW)
                        GetVersionExW(ByVal VarPtr(OsInfoEx))
                        If OsInfoEx.dwMajorVersion = 6 and OsInfoEx.dwMinorVersion = 2 Then Function = %True
                      End Function
                      Next I added a Global:
                      Code:
                      Global hMyTimer as Dword
                      Next I removed the GetSystemTimePreciseAsFileTime declaration and added
                      Code:
                      Declare Sub MyTimer(lpFileTime As Quad)
                      I then removed 'Control Add Button, hDlg, 600,"FileTimePrecise", 20, 160, 120, 20'

                      In the DlgProc() callback I added:
                      Code:
                      Local hLib as Dword
                      In Case %WM_InitDialog, just after iLoop = 1000000000, I added:
                      Code:
                      If IsFalse OSGreaterThanOrEqualToWin8 Then
                        Control Add Button, hDlg, 600,"FileTimePrecise", 20, 160, 120, 20, %WS_DISABLED
                      Else
                        Control Add Button, hDlg, 600,"FileTimePrecise", 20, 160, 120, 20
                        hLib = LoadLibrary( "Kernel32.dll" )
                        hMyTimer = GetProcAddress( hLib, "GetSystemTimePreciseAsFileTime" )
                        FreeLibrary hLib
                      End If
                      In the Thread Function ProcessFileTimePrecise() we simply replace

                      'GetSystemTimePreciseAsFileTime(qStart)' & 'GetSystemTimePreciseAsFileTime(qStop)' with 'Call Dword hMyTimer Using MyTimer(qStart)' & 'Call Dword hMyTimer Using Mytimer(qStop)'.

                      Like I said a bit of a carry on but it works. Anyone with Win7 or earlier will see the FileTimePrecise button disabled.

                      Added: As a side note from Netmarketshare (March 2019): "The figures for desktop/laptop give Windows 10 a 43.62 per cent (+3.32 on last month) share of the pie, against Windows 7, which lest we forget has less than a year before hitting end of life, with 36.52 (-1.89).

                      I miss Win7, I really do. Never put a foot wrong. 8 and 8.1? No idea, I jumped from 7 to 10.

                      Comment


                      • #12
                        Thank you

                        Ok, I made the changes. This is what I get 0.630 - 0.635 where as FileTime, Timer, and TickCount show 0.625. Is that acceptable? If that is ok then I'll post it.

                        Comment


                        • #13
                          After giving the updates above a good workout I found effectively two sets of figures: The real-time clock timers had much the same precision and the high resolution timers had much the same precision and were slightly longer than the real-time clock figures so your results are agreeing with mine. The question is which are the more accurate. I think we have to agree that the high resolution timers are the more likely to be the more accurate. At the moment I have Version 3 running alongside the updated version above, and they appear to behaving the same - which is to be expected.

                          Regarding your editing I would go back to the beginning of my last post and work through it line by line to make sure nothing has been skipped, which can happen.

                          Comment


                          • #14
                            David,
                            I followed your directions to the letter. The higher resolution methods may be affected by processes that are not readily visible. This is the disclaimer I put in the previous version. "Eventually every method will give up erroneous results."
                            I'm inclined to accept the ones that show the same value nearly every time. To me they demonstrate stability in the platform and method. They are less affected by turbulence in the OS. I am going to try something I thought about last night. I'm going to inject REALTIME priority in each thread. Cross your fingers.

                            Interestingly it seems to help curtail the radical swings of QueryPerformance, TIX, and FileTimePrecise. Still testing...Yes much better.

                            Comment


                            • #15
                              I went back to GetSystemTimePreciseAsFileTime to see if it was helped by REALTIME priority. So far the radical swings are gone. After testing for a couple minutes I noticed 1 small glitch with QueryPerformance. 0.641

                              Version 4 is online.

                              Comment


                              • #16
                                Jim, I need a little time to digest what you wrote in post #14. What we have with low resolution timers versus high resolution timers is analogous to sampling rate.

                                Edited: I wrote other stuff but there were some ambiguities which I need to sort out.
                                Last edited by David Roberts; 2 Aug 2019, 01:58 AM. Reason: Slight ambiguity

                                Comment


                                • #17
                                  Actually, more than ambiguities - I had a right go at you, Jim, for not following my directions to the letter. Version 4 ended up with bits from Version 3 which I had indicated to remove.

                                  If we do not remove GetSystemTimePreciseAsFileTime's declaration and keep GetSystemTimePreciseAsFileTime in Thread Function ProcessFileTimePrecise() we have load-time (implicit) linking. The compiler will compile gobbledygook but that would not be an issue unless we tried to execute GetSystemTimePreciseAsFileTime. If we did try then loading would be aborted, and we'd get an 'Entry Point Not Found' message. In Win7 and earlier we cannot execute GetSystemTimePreciseAsFileTime because the FileTimePrecise button is disabled. So there I was suggesting ripping out load-time (implicit) linking and replacing it with run-time (explicit) dynamic linking via 'Call Dword' when there was no need to.

                                  So, we can safely remove the explicit linking code as follows:
                                  Code:
                                  GLOBAL hMyTimer AS DWORD
                                  DECLARE SUB MyTimer(lpFileTime AS QUAD)
                                  LOCAL hLib AS DWORD
                                  hLib = LoadLibrary( "Kernel32.dll" )
                                  hMyTimer = GetProcAddress( hLib, "GetSystemTimePreciseAsFileTime" )
                                  FreeLibrary hLib
                                  'Call Dword hMyTimer Using MyTimer(qStart)
                                  'CALL DWORD hMyTimer USING Mytimer(qStop)
                                  I noticed that you had commented the last two statements without saying why.

                                  REALTIME priority is not making a blind bit of difference to my tests.

                                  I am still pondering on sampling rate.

                                  Comment


                                  • #18
                                    David,
                                    Note: Post#15
                                    "I went back to GetSystemTimePreciseAsFileTime to see if it was helped by REALTIME priority. So far the radical swings are gone. After testing for a couple minutes I noticed 1 small glitch with QueryPerformance."
                                    That was before I posted the update.

                                    I kept your suggested insertions and just REMed them so either method could be tested easily.

                                    I'm wondering what is causing the variations in output over time. Some non thread safe processes in the API? Possible.

                                    I just reduced the loop period to 1/5th the original. The results are looking much better...

                                    Version 5 is online.

                                    Note:
                                    If the computer is speaking while you are testing you will get radical variations in results for all threads.


                                    Version 5 variations are now 0 to 7 milliseconds when alternating between tests and 0 to 3 milliseconds when running the same test over and over again.

                                    I'm thinking I'll build in more automation to do a 10 loop test and capture the lowest value. Sounds familiar, Right? Working...

                                    When doing 10 iterations of the same test it appears the first one is the smallest of the 10. Very interesting.
                                    Note: The only one I tried with 10 iterations was QueryPerformance. I did not do a 10 iteration test while the computer was speaking. Silly me.
                                    Last edited by Jim Fritts; 2 Aug 2019, 10:51 AM.

                                    Comment


                                    • #19
                                      There is one issue which we have no control over namely:-
                                      Code:
                                      FOR i = 0 TO iLoop : NEXT i
                                      That can vary all over the place.

                                      What we can do instead is to time a piece of code which we know exactly how long it takes to execute. That way every thread test is timing the same time, so to speak.

                                      I suggest this:
                                      Macro Base_Frequency = 3.5 * Exp10(9) ' Edit for your machine
                                      Macro Interval = Base_Frequency/4 ' 1/4 of a second

                                      In each Thread Function
                                      Remove 'LOCAL i as LONG' and replace with 'LOCAL qStart0, qStop0 as QUAD'
                                      Remove 'FOR i = 0 TO iLoop : NEXT i' and replace with
                                      Code:
                                      TIX qStart0
                                      Do
                                        TIX qStop0
                                      LOOP UNTIL qStop0 - qStart0 >= Interval
                                      This will stick around for as close to 1/4 of a second as we can get.

                                      This is what I am getting for 7 runs followed by "seconds"and 6 decimal places. I waited a few seconds before clicking on a button again and, obviously, that cannot be done exactly.
                                      QueryPerformance - frequency 10MHz
                                      0.249999
                                      0.249999
                                      0.249999
                                      0.249999
                                      0.249999
                                      0.249999
                                      0.249999

                                      TIX - frequency 3.5GHz
                                      0.250000
                                      0.250000
                                      0.250000
                                      0.250000
                                      0.250000
                                      0.250000
                                      0.250000

                                      TickCount - frequency 15.625ms
                                      0.250000
                                      0.250000
                                      0.250000
                                      0.250000
                                      0.235000
                                      0.250000
                                      0.250000

                                      Timer - frequency 15.625ms
                                      0.250000
                                      0.235000
                                      0.235000
                                      0.235000
                                      0.236000
                                      0.250000
                                      0.235000

                                      FileTime - frequency 15.625ms
                                      0.249983
                                      0.249984
                                      0.249979
                                      0.249978
                                      0.235529
                                      0.235481
                                      0.251141

                                      FileTimePrecise - frequency better than 1MHz
                                      0.249999
                                      0.249999
                                      0.249999
                                      0.249999
                                      0.249999
                                      0.249999
                                      0.249999

                                      So there we have it - TIX is blinding accurate and stable followed by QueryPerformance and FileTimePrecise which were neck and neck. Of the three linked to the real-time clock TickCount is amazing, Timer is a bit 'ropey' and FileTime didn't manage to get two timings the same.

                                      Other machines may vary but on my machine the higher resolution timers are in a class of their own.

                                      I went back to TickCount and gave that quite a few clicks and, occasionally, it came back with 0.235000 seconds. So Steve seems to have been 'spot on' backing GetTickCount provided the interval is not 'short'.

                                      Changing
                                      Code:
                                      Macro Interval = Base_Frequency/4 ' 1/4 of a second
                                      to
                                      Code:
                                      Macro Interval = Base_Frequency/20 ' 1/20 of a second
                                      saw all the higher resolution timers coming in at 0.050000 seconds dead and no variations. Both TickCount and Timer were coming in at 0.047000 seconds most of the time with a few 0.046000 seconds. FileTime was very 'ragged'.

                                      With the interval at 1/100 of a second, 10ms, this is below the real-time clock's radar and all the low resolution timers came in at zero. The high resolution timers came in at 0.010000 seconds dead.

                                      Conclusion: Steer clear of FileTime, sorry Dale, for any timing. For intervals with a decent number of milliseconds GetTickCount, smiles from Steve, is OK. For small intervals any one of the higher resolution timers should be brought into action. I will stay with Microsoft's advice and my macro timers using the Performance Counter unless the interval is very tiny forcing me to use TIX.

                                      Originally posted by Jim
                                      When doing 10 iterations of the same test it appears the first one is the smallest of the 10.
                                      I reckon all crystal oscillators have got their feet up when not be queried and behave like disturbing a sleeping dog when asked to work for us. This is why the Intel engineer's blog many years ago advised to 'dump' the first QueryPerformanceCounter value, but he had no idea why the first one was unreliable. Timing a bunch of Sleeps sees the first usually well out of step with the following values.

                                      Originally posted by Jim
                                      and capture the lowest value
                                      Your quote above that one and my following note is telling you not to do that. Go with the median.

                                      I ripped WinBeep out - that was asking for trouble, besides which I do not have speakers on my system. I do listen to music but that is via an AudioQuest DragonFly Red DAC and an AudioQuest Jitterbug hanging out of a USB port feeding a pair of Sennheiser HD600 head phones. I was listening to 'Orianthi Live' a few minutes ago - mind blowing. Check it out on YouTube. If I was 40 years younger I'd buy her a McDonald's Big Tasty medium meal - never fails.

                                      Right, I am out of here now - I have spent too much time, again.

                                      Comment


                                      • #20
                                        I haven't read it all but will. Sounds good. Breaking for lunch

                                        Ok I'm back temporarily

                                        I ran into some issues.

                                        This is my solution.

                                        I replaced:
                                        Code:
                                            '---------------------------------------
                                            'FOR i = 0 TO iLoop : NEXT i
                                            '---------------------------------------
                                        with this CALL DoLoop

                                        Code:
                                        SUB DoLoop
                                          LOCAL nStart AS QUAD
                                          LOCAL nStop  AS QUAD
                                        
                                          TIX nStart
                                          DO
                                            TIX nStop
                                          LOOP UNTIL nStop - nStart >= Base_Frequency/8
                                        END SUB
                                        Now getting 0.125 for all the test threads.
                                        Last edited by Jim Fritts; 2 Aug 2019, 05:28 PM.

                                        Comment

                                        Working...
                                        X