Announcement

Collapse
No announcement yet.

TimerInterval

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

  • TimerInterval

    In the thread MaximizeTimerResolution: SLL & DLL at posts #2 and #4 are MaximumTimerResolution.exe (MTR) and TimerRes.exe. MTR is a console application which allows us to set the timer interval via a command line. TimerRes simply displays, via a message box, the values of the maximum, minimum and current timer interval.

    TimerInterval combines both of these exes as follows:



    At the bottom of the dialog we are advised of the maximum and minimum timer interval. On my machine the timer interval may take up to seven values. The current timer interval is given by the set option button.

    Clicking on another option button will set the interval to whatever you choose.

    So, that covers MTR and TimerRes.

    TimeInterval goes further by being a monitor as well. If another process changes the interval to a value less than the current interval then that will be reflected in TimerInterval.

    Windows employs the principle that the current timer interval is the smallest timer interval chosen by any open procecss.

    To test I changed the timer interval from 15.6ms to 10ms. I then ran MTR with a value of 50000 giving then a new timer interval of 5ms and this was immediately reflected in TimerInterval. I then opened Google Chrome and the timer interval changed to 1ms. Closing in reverse order saw the timer interval change from 1ms to 5ms and then 5ms to 10ms.

    With Google Chrome running I chose 10ms in TimerInterval. In TimerInterval's GUI the selection was very briefly shown and the 1ms was very briefly unset but this was reversed just as quickly to reflect the current resolution set by Google Chrome. Closing Google Chrome saw the timer interval change to 10ms, the value we chose with TimerInterval.

    With a current timer interval of 15.6ms no change was made when Internet Explorer was opened. On visiting YouTube's home page the interval oscillated between 15.6ms and 2.5ms. Clicking on a video saw the interval oscillate between 10ms and 2.5ms. On leaving YouTube the interval changed to a steady 10ms and remained at 10ms for the rest of the IE session.

    With a current timer interval of 15.6ms, playing mp3s in Window's Media Player saw an interval of 10ms and mp4s saw an interval of 2.5ms.

    Attached is a zipped TimerInterval.exe.
    Attached Files
    Last edited by David Roberts; 30 Aug 2014, 05:25 AM.

  • #2
    very slick research Dave!
    MSDN could do with an update now
    -

    Comment


    • #3
      MSDN is a fantastic resource but I no longer regard it as definitive. Sometimes, to find out what is really going on we have to roll our sleeves up and get our hands dirty.

      For me, TimerInterval comes into its own for testing our own applications. We can vary the timer interval to see how they are affected without having to open our source code editor. Running one of Rodney Hick's applications saw little difference as I moved up one interval at a time from 15.6ms. However, a quick change from 15.6ms to 1ms saw a dramatic change.

      It should be noted that any change made by TimerInterval will be revoked on its closing. For a change to persist then leave it running; and minimized is best because it runs topmost.

      Comment


      • #4
        Slightly improved interface and more efficient logic employed - new version updated in post#1.

        Comment


        • #5
          I was recently advised that after selecting 1.0ms an application saw no change when there should have been one.

          It transpired that TimerInterval was closed after the selection.

          The answer is in the first post.
          Windows employs the principle that the current timer interval is the smallest timer interval chosen by any open process.
          As soon as TimerInterval is closed it's selection is revoked.

          To have a selected interval persist we should keep TimerInterval open and if it gets in the way of an application then simply minimize it.

          We can examine this by executing TimerInterval, when the current timer interval is 15.6ms, selecting, say, 5.0ms and then move the window to one side. If we now execute a second instance of TimerInterval then it will display 5.0ms, the current timer interval. If the first instance is now closed then the second instance will now display 15.6ms showing that the first instance's selection has been revoked.

          The following has been mentioned in other threads but it is worth mentioning again.

          If, after testing selections, it is found that an application benefits from a timer interval of 1.0ms, say, then introduce
          Code:
          timeBeginPeriod(1)
          Sleep 16
          to the application.

          If we apply that to a particular section as opposed to the application as a whole, in PBMain for example, then we should end the section with
          Code:
          timeEndPeriod(1)
          Sleep 16
          The Sleep 16 is necessary because it takes two clock cycles for the change to take effect. I haven't tested this but I should think that Sleep 2 will suffice after timeEndPeriod(1) but it may not be necessary anyway.

          We can test the introduction with TimerInterval - each time we enter the 'bracketed' section TimerInterval will display 1.0ms and its duration at that setting will depend upon the duration of the section.
          Last edited by David Roberts; 15 Sep 2014, 02:36 AM.

          Comment


          • #6
            Doesn't work in Windows 10 but a new version does; on my machine.

            The values got from NtQueryTimerResolution were not as expected. For example, the 2.5ms value used to be 25000 but with Win10 I am getting 25010. All the other values are 'wrong' as well. The 15.6ms used to be 156000 and is now 156260.

            The question is will you get 25010 for 2.5ms or might it be 25007 or whatever? I am looking at a way to force the issue so that if we get 25000 +- some delta then it is forced to be 25000.

            TimeGetDevCaps used to come back with a min/max of 1ms/15.6ms. With Win10 it comes back with 1ms/1000ms. 1000ms! No I will not be trying that.

            Comment


            • #7
              I got bogged down with some Win10 issues and came back to this.

              The solution was simple:

              Code:
              If CurrentResolution < 150000 Then
                CurrentResolution = Round(CurrentResolution/100, 0)*100 ' Gives an effective delta of plus/minus 49
              Else
                CurrentResolution = Round(CurrentResolution/1000, 0)*1000 ' Gives an effective delta of plus/minus 499
              End If
              This is used in %WM_InitDialog and %WM_Timer (querying every 33ms to catch another process changing the resolution).

              This allows me to use 5000, 10000, ..., 15600 as I did with the Win7 version.

              When it comes to setting the resolution via the radio buttons we don't have a problem as the OS will choose the nearest resolution to a request that it can find (noticed this when developing the Win7 version) - within reason but I don't know how far we can push it.

              I have renamed the app TimerRes as there is not enough room in the title area for TimerInterval because Win10 now has a ludicrous amount of space separating the minimise, restore and close buttons. How annoying is that? The product name is still TimerInterval.

              Needless to say TimerRes will also work with Win7.

              Attached is TimerRes.zip
              Attached Files

              Comment


              • #8
                I need to do some more work on this.

                I added a 'Case Else' to catch a resolution not recognised. I never expected to see it invoked but have just been advised of a value of 40000, corresponding to 4ms when running Microsoft Edge. 4ms is not available in Win7 and no problems with Google Chrome (yet).

                Comment


                • #9
                  Originally posted by David Roberts View Post
                  I need to do some more work on this.

                  I added a 'Case Else' to catch a resolution not recognised. I never expected to see it invoked but have just been advised of a value of 40000, corresponding to 4ms when running Microsoft Edge. 4ms is not available in Win7 and no problems with Google Chrome (yet).

                  Can you please send the sourcecode?

                  Thanks
                  Stephane

                  Comment


                  • #10
                    Can you please send the sourcecode?
                    No.

                    Have a nice day
                    David

                    Comment


                    • #11
                      We have a very, very different kettle of fish with Win10.

                      I have just thrown 93847 at NtSetTimerResolution and got a 'Current timer interval' of 9.3849ms.

                      4000/0.4ms and 200000/20ms gave 0.5004ms and 15.6261ms respectively so the lower and upper bounds are as with Win7.

                      Between those bounds it would appear that we can have anything we like so we need a different GUI.

                      I will come back to this at a later date - I am up to my neck in Win10 at the moment.

                      Comment


                      • #12
                        So, what we now have is a continuous version as opposed to a discrete version.

                        If the current resolution is 64Hz then this is what I get on opening.



                        When setting a timer interval we use units of 100 nanoseconds. This is not unusual and is in line with the FILETIME structure described in MSDN as:
                        Contains a 64-bit value representing the number of 100-nanosecond intervals since January 1, 1601 (UTC).
                        We could, as an unusual example, set 123456 and get an interval of 12.3468ms. It is not exact but we are talking about a PC here and a difference of 1.2 microseconds is pretty respectable.

                        By the way, the 'Set' button is a default button.

                        If we set with the set textbox empty I get 0.50004ms and if we set with a value of, say, 200000 I get 15.6261ms indicating the min/max range of 0.5ms/15.625ms as with Win7.

                        If you haven't read the opening post it is worth a read as it covers how the system works.

                        The golden rule is:
                        Windows employs the principle that the current timer interval is the smallest timer interval chosen by any open procecss.
                        For example, assuming the current interval is 15.6ms, then with an initial instance set at 10ms and then a second instance set at 12ms nothing seems to change but when the first instance is closed the second instance shows 12ms. If we closed that and opened again we find 15.6ms, assuming nothing else has set less. The behaviour then is exactly the same as with Win7.

                        Windows Media Player is now showing 10ms for mp4s. HD in YouTube sees 1ms.

                        Attached is a zip of TimerInterval (Win10).exe. So, back to the original name, nearly - the dialog is wider.
                        Attached Files
                        Last edited by David Roberts; 22 Aug 2015, 03:43 PM.

                        Comment


                        • #13
                          New version.



                          If we have an application and wonder if it would benefit from a decrease in the timer interval then we can quickly set the minimum with the lower of the new 'Set' buttons and quickly restore with the upper 'Set' button without altering the source code of our application. If a particular interval is beneficial we can then introduce it to our source code via TimeBeginPeriod.

                          Example:
                          Code:
                          Local Time As TIMECAPS
                           
                          TimeGetDevCaps( Time, SizeOf(Time) )
                          TimeBeginPeriod(2)
                          Sleep 16
                          The above will set a timer interval of 2ms.

                          TimeBeginPeriod uses integers so a float input will be converted. It is best then to stick with 1, 2, 3, ... , 16.

                          The new interval will not 'bite' until the old interval has elapsed so to make sure subsequent code runs at the new interval we need to Sleep for 16.

                          With Win7 we could only use 1, 5, 10 and 16.

                          As with most of the opening post the above has been gleaned from experimentation - there is absolutely nothing at MSDN.

                          Version 1.0.1 in previous post.

                          Comment


                          • #14
                            Now has an hour glass icon - just managed to squeeze it in.

                            Comment


                            • #15
                              New version: Continuous and discrete.

                              We can now set an interval between 1ms and 15ms from the System Menu.



                              Version 1.0.2 above.

                              Comment


                              • #16
                                Here is a simple way to add a resolution change to you applications.

                                Code:
                                #Compile Exe
                                #Dim All
                                #Register None
                                 
                                #Include "Win32API.inc"
                                 
                                Declare Function NtQueryTimerResolution Lib "ntdll.dll" Alias "NtQueryTimerResolution" _
                                 (LowestResolution As Long, HighestResolution As Long, CurrentResolution As Long) As Long
                                 
                                Global Resolution As Long
                                 
                                Function PBMain
                                 
                                  Resolution = 2
                                 
                                  SetResolution( Resolution ) ' {
                                 
                                    MsgBox "Wait1", %MB_Topmost ' Code To benefit From a higher resolution
                                 
                                  UnsetResolution( Resolution ) ' }
                                 
                                  MsgBox "Wait 2", %MB_Topmost
                                 
                                End Function
                                 
                                FastProc SetResolution( ByVal Resolution As Long )
                                Static Time As TIMECAPS
                                Static Dummy, CurrentResolution	As Long
                                 
                                  TimeGetDevCaps( Time, SizeOf(Time) )
                                  If Resolution < 1 Then Resolution = 1
                                  TimeBeginPeriod( Resolution )
                                  NtQueryTimerResolution( Dummy, Dummy, CurrentResolution )
                                  Sleep CurrentResolution\10000 + 1
                                  ' New resolution will now 'bite'
                                End FastProc
                                 
                                FastProc UnsetResolution( ByVal Resolution As Long )
                                Static Time As TIMECAPS
                                Static Dummy, CurrentResolution	 As Long
                                	
                                  TimeGetDevCaps( Time, SizeOf(Time) )
                                  If Resolution < 1 Then Resolution = 1
                                  TimeEndPeriod( Resolution )
                                  NtQueryTimerResolution( Dummy, Dummy, CurrentResolution )
                                  Sleep CurrentResolution\10000 + 1
                                  ' New resolution will now 'bite'
                                End FastProc
                                To see the above in action run 'TimerInterval (Win10)' and change the resolution to 5ms from a value greater than that, probably 15.625ms. Now move the window off centre.

                                Compile and run the above code.

                                At the message 'Wait1' the interval will now show 2ms ( 2.0006ms on my machine ). Click OK and at the message 'Wait2' the interval will now show 5ms ( 5.0008ms on my machine ).

                                Now comment these lines:
                                Code:
                                  UnsetResolution( Resolution ) ' }
                                 
                                  MsgBox "Wait 2", %MB_Topmost
                                and repeat the exercise.

                                In this case we have allowed 2ms to the end of the application session and neglected to implement a 'TimeBeginPeriod/TimeEndPeriod' combination. The OS invokes a TimeEndPeriod for us.

                                Comment


                                • #17
                                  Tinkering with Timer

                                  Try this:

                                  Code:
                                  Function PBMain
                                  Local t1, t2 As Double
                                  Local qFreq, qStart, qStop As Quad
                                   
                                    Resolution = 1
                                   
                                  '  SetResolution( Resolution ) ' {
                                   
                                    QueryPerformanceFrequency qFreq
                                    QueryPerformanceCounter qStart
                                    t1 = Timer
                                    QueryPerformanceCounter qStart
                                    Do
                                      QueryPerformanceCounter qStop
                                    Loop Until qStop - qStart >= qFreq/100 ' 10ms
                                    t2 = Timer
                                   
                                  '  UnsetResolution( Resolution ) ' }
                                   
                                    MsgBox Str$( (t2 - t1)*1000 )
                                   
                                  End Function
                                  When the interval is at the default of 15.625ms and the 10ms 'wait' is between two Timer updates then the message box will display zero. On the other hand when the 10ms wait straddles a Timer update then the message box will display something like 14.999999994179 or 15.9999999959837.

                                  If we remove the comments Timer will now use a multimedia timer as opposed to the system clock. We now get something like 8.99999999819556 or 9.99999999476131 showing that Timer now has a resolution if 1ms.

                                  So, if we want to time some code and are happy with a 1ms accuracy then this will do the job.

                                  Code:
                                  SetResolution( 1 )
                                  t1 = Timer
                                  ' Code to time
                                  t2 = Timer
                                  UnsetResolution( 1 )
                                  MsgBox Str$( (t2 - t1)*1000 )

                                  Comment


                                  • #18
                                    New version for Windows 10.

                                    The original version had only a text box for setting. It was not particularly user friendly. The next version allowed us to quickly set either the maximum or minimum resolution. The next version introduced discrete values via the System Menu.

                                    The text box entry allows, for example, 123456, for a resolution request of 12.3456ms; although after setting we get 12.3467ms. Windows 7, and earlier, has a limited number of discrete values to choose from.

                                    To my mind the text box entry became redundant as soon as the System Menu entry was introduced.

                                    In this new version the text box entry has been removed and so has the setting of maximum and minimum from the form.

                                    This is what we get on opening with the current resolution at the default. Click image for larger version

Name:	TI2.jpg
Views:	19
Size:	28.9 KB
ID:	752003



                                    The maximum and minimum are not from documentation but got from querying the system.

                                    Here is what the System Menu now looks like: Click image for larger version

Name:	TI2Menu.jpg
Views:	19
Size:	38.5 KB
ID:	752004



                                    We can set the maximum and minimum from the System Menu and these values are determined from querying the system before the menu is built. Chances are that you will have the same but I cannot know that for certain; although I doubt any future version of Windows will change the maximum timer interval.

                                    If we did not want to monitor the current resolution and only wanted to set a resolution then I recommended MTR.exe.

                                    I thought of adding an option to the main form of this new version to allow us to turn off the monitoring. It occurred to me that we would probably only use that just before minimising the form and start monitoring again after restoring. I cannot think of why we would want to stop monitoring and keep the form visible.

                                    This is begging to be done automatically, so monitoring will stop when we minimise the form and start when we restore. A message box briefly appears to remind us of the action taken. There should not be a need for that but some folk will download this application without reading all the notes. Yes, they will.

                                    It is possible that we may request a resolution lower than the current resolution and seem to get ignored. This will happen if another process set the current resolution. This has always been the case but I left it up to the user to figure out why. We now get a message box, for five seconds, as follows. Click image for larger version

Name:	TI2Message.jpg
Views:	19
Size:	24.6 KB
ID:	752005



                                    If the other process closes and no other process has requested a resolution higher then our request will now get processed.

                                    Needless to say if we request a resolution lower than the current resolution and we set the current resolution then we will not be ignored.

                                    To get a better feel of how the system works then run two instances of this application and play around setting resolutions with each.

                                    That is it!

                                    I have called this version 'TimerInterval2 (Win10)' - you may prefer the text box setting version.

                                    A zip of the exe is here.
                                    Last edited by David Roberts; 23 Aug 2016, 01:14 AM.

                                    Comment


                                    • #19
                                      I have just run some code by Gert Voland and learnt that when I request 0.5ms than I actually get that. I thought my best was 1ms according to the timers in my system. It gave me a boost of 33% compared with 1ms.

                                      Comment


                                      • #20
                                        A new item has been added to the System Menu: Revoke

                                        I am not seeing much of a benefit but this now exhausts all possibilities of NtSetTimerResolution. There are not many descriptions of NtSetTimerResolution on the internet and none of them fully explains the parameters, except one; which I have just found.

                                        Suppose we have two instances of TimerInterval2 (Win10) A and B, say.

                                        Assuming that the current timer interval is 15.625ms then set B to 10ms. A will now show 10ms. Set A to 5ms. B will now show 5ms.

                                        1) If we try to set A to 12ms, say, then we will be advised our request has been noted but another process has set a higher resolution so both will now show 10ms.

                                        If B is closed then A will show 12ms, the request that was noted.

                                        2) If we set A to Revoke the system will try to set A to its first value ie 15.625ms. It will fail but we will not get any message and both A and B will show 10ms.

                                        If B is closed then A will show 15.625ms, the value it tried to set on Revoke.

                                        Perhaps I am missing something but Revoke doesn't seem useful.

                                        Anyway, as mentioned, we have now exhasted all possibilities of NtSetTimerResolution.

                                        The link in post #18 will get you V1.03.

                                        I gave up on uploading to PB's server - it is broken and it looks like we have given up on trying to fix it. Tsk, tsk.

                                        Comment

                                        Working...
                                        X