Sign in to follow this  
Followers 0
lgodfrey

Here's an alternet to Sleep

2 posts in this topic

#1 ·  Posted (edited)

Here is an altenate function for Sleep() that meets my goals of good accuracy at low CPU usage for all times 1 to 1000 msec.. It returns 0 if there was a bad parameter in the call, and returns the actual sleep time if the sleep was executed properly. It typically is accurate to better than +/-1 milliseconds from 1 to 1000 msec. Occasionally it will "oversleep" up to about 2-3 msec past the target because of the kernel32 sleep(0) call. (my understanding is that if a program needs cpu time exactly on the last loop, then control will not return in time to finish right on target.) AutoIT sleep can easily be 15 msec off target, depending on the time called. (On some machines it seems to be more accurate, but still up to 9-10 msec off) . It will undersleep by no more than 50 microseconds, for sure, but I have not seen an undersleep larger than 25 microseconds. You can use decimal places in the sleep parameter, but it is not accurate enough to bother doing this (this means you do not have to round your parameter to the nearest msec).

The only way I see right now to get a more accurate sleep is to use a call to MsgWaitForMultipleObjects method of user32 to dummy up a sleep function for the first sleep in the function I am posting. Epson claims that MsgWaitForMultipleObjects gets checked more frequently than kernel32 sleep, so it could be used for the first sleep in this function, and there would be almost 10 times fewer loops of kernel32.sleep(0), so the chances of oversleeping are reduced. However, I do not know anything about the hex constants, and the function call is very complex, so is I am stopping here. Here is the url for the Epson comments on sleep: http://www.robots.epson.com/support/T1090.htm (this MsgWait trick may even be good as +/-1 msec all by itselft, with no sleep(0) calls) It would be neat if someone could check this out...VB code is given, "just" have to know enough to translate it into AutoIT form.

Func _ModifiedSLeep($T)
    Local $dll, $T0 = TimerInit() ;EDIT  NEEDS BETA VERSION OF AUTOIT TO RUN
    If not (IsNumber($T)) Then Return 0
    $dll = DllOpen("kernel32.dll")
    If $T - TimerDiff($T0) > 16 Then DllCall($dll, "none", "Sleep", "long", $T - 16);guarantees will not sleep longer than the target, even for smaller $T
    While TimerDiff($T0) < $T - .05;you might have to modify the .3 offset for your PC  run the sample use codes to see if you like the .3 value
        DllCall($dll, "none", "Sleep", "long", 0)
    WEnd
    DllClose($dll)
    Return TimerDiff($T0)
EndFunc ;==>_ModifiedSLeep
Here are two test scripts that compares Sleep to ModfiedSleep. The first writes measured sleep times to a splash window so you can see values at 1, 10, 100, 1000 msec. You can toggle between autoit and this sleep function in the code to compare the two. This is the most user freindly of the two examples.

The second writes the average of 10 sleep times to a file, for 1, 2, 4..1024 msec, you choose to look at kernel32, autoit, or this sleep function. It appends the information to the Times.csv file, so you can run the different sleeps and look at them in a spreadsheet (you have to keep track of which ones you run).

SplashTextOn("Sleep Testing", "initialize")
While 1
    $stop1 = 0
    $sleep1 = 0
;comment out these next four lines if you want the smaller target sleeps to update faster   
    $start1 = TimerInit()
;~   $stop1 = Sleep(1000);toggle commented out, this and the following line, if you want to look at AutoIT's sleep function
    $sleep1 = _ModifiedSLeep(1000)
    $stop1 = TimerDiff($start1)

    $start2 = TimerInit()
    For $i = 1 To 1
;~       $sleep2 = Sleep(100);toggle commented out, this and the following line, if you want to look at AutoIT's sleep function
        $sleep2 = _ModifiedSLeep(100)
    Next
    $stop2 = TimerDiff($start2)
    
    $start3 = TimerInit()
    For $i = 1 To 10
;~       $sleep3 = Sleep(10);toggle commented out, this and the following line, if you want to look at AutoIT's sleep function
        $sleep3 = _ModifiedSLeep(10)
    Next
    $stop3 = TimerDiff($start3)
    
    $start4 = TimerInit()
    For $i = 1 To 100
;~       $sleep4 = Sleep(1);toggle commented out, this and the following line, if you want to look at AutoIT's sleep function
        $sleep4 = _ModifiedSLeep(1)
    Next
    $stop4 = TimerDiff($start4)
    ControlSetText("Sleep Testing", "", "Static1", _
            "Sleep Target             Average Actual Sleep   Last Sleep Func Return" & @CRLF & _
            "$stop1 (1000)=                       " & Round($stop1, 1) & "                      " & Round($sleep1, 1) & @CR & _
            "$stop2 (100) =                      " & Round($stop2, 1) & "                          " & Round($sleep2, 1) & @CR & _
            "$stop3 (10)=                     " & Round($stop3 / 10, 2) & "                        " & Round($sleep3, 2) & @CR & _
            "$stop4 (1) =                      " & Round($stop4 / 100,2) & "                           " & Round($sleep4, 2)) 
WEnd
        splashoff()
Exit
;comparing kernel32 and AutoIT sleep functions for times less than 100 msec
Dim $dll, $T = 1 / 2, $Sleep, $SavedTimesFile = "C:\Times.csv", $TimesFileH, $KK, $JJ, $KLOOPS, $TimeData[1000], $Line = 0
$dll = DllOpen("kernel32.dll")
$T0 = TimerInit()
$KLOOPS = 10
For $KK = 0 To 10
    $T = $T * 2
    For $JJ = 1 To $KLOOPS;uncomment the sleep function you want to store into the file
;~       DllCall($dll, "none", "Sleep", "long", $T)
;~       sleep($T)
        $dummy= _ModifiedSLeep($T)
    Next
    $Sleep = TimerDiff($T0)
    $T0 = TimerInit()
    $TimesFileH = FileOpen($SavedTimesFile, 1)
    FileWrite($TimesFileH, $t & ",   " & $Sleep / $KLOOPS & @CR)
    FileClose($TimesFileH)
Next
Exit

Regards

Larry

\

edit, added note in function that it needs beta version to run ###############

Edited by lgodfrey

I'm, Lovin' IT, X

Share this post


Link to post
Share on other sites



Impressive, even though I don't understand all the code. :)

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now
Sign in to follow this  
Followers 0