Sign in to follow this  
Followers 0
ludocus

sleep is not to accurate...

19 posts in this topic

#1 ·  Posted (edited)

I did a test..

First I TimerDiff't sleep(1000) 2 times

result:

1: 1003.58872426523

2: 1008.31055343626

thats 3 millie seconds wrong..

Now I made my own sleep :)

I did 2 tests with _Sleep(1000) and got the following results:

1: 1000.01117460459

2: 1000.01340952551

Very accurate!

just to let people now that sleep is not so accurate... because when someone is making something wich needs very accurate sleeping my code could be better :P

here are the tests:

$11 = _Example1()
$12 = _Example1()
$21 = _Example2()
$22 = _Example2()
msgbox ( 32, 'sleeping results', 'the results for normal sleep are:'&@CRLF&'1) '&$11&@CRLF&'2) '&$12&@CRLF&@CRLF&'The results for my _Sleep are:'&@CRLF&'1) '&$21&@CRLF&'2) '&$22)
ClipPut($11&@CRLF&$12&@CRLF&$21&@CRLF&$22)
Func _Example1() ;normal sleep
$Timer = TimerInit()
sleep(1000)
$tmp = TimerDiff($timer)
return $tmp
EndFunc

Func _Example2() ;my _Sleep
$Timer = TimerInit()
_Sleep(1000)
$tmp = TimerDiff($timer)
return $tmp
EndFunc

Func _Sleep($sTime)
    $timer=TimerInit()
    Do
        $tmp = TimerDiff($timer)
    Until $tmp >= $sTime
EndFunc
Edited by ludocus

Share this post


Link to post
Share on other sites



WOW, when I tested with sleep "5000"

Posted Image

The concerning thing is the CPU usage of your script... 100%

8)


NEWHeader1.png

Share this post


Link to post
Share on other sites

I know, is there a way to make the cpu usage a little lower..?

Share this post


Link to post
Share on other sites

#4 ·  Posted (edited)

yeh thats true...

The standard Sleep function isn't as accurate because it just rests with a very low CPU priority/usage... so there is a timelaps between the moment it says "time is over" and the moment where the cpu gets available for this info...

I guess that if you start CPU Burn at the same time as the standard Sleep the standard one will be much more accurate.

Edited by JavaCupiX

Share this post


Link to post
Share on other sites

#5 ·  Posted (edited)

I found that directly calling the Sleep function in kernel32.dll was more accurate than the built in sleep:

$timer=TimerInit()
Sleep(2500)
ConsoleWrite(TimerDiff($timer)&" milliseconds"&@CRLF)

$dll=DllOpen("kernel32.dll")
$timer=TimerInit()
DllCall($dll,"none","Sleep","dword",2500)
ConsoleWrite(TimerDiff($timer)&" milliseconds"&@CRLF)

:)

Edited by monoceres

Broken link? PM me and I'll send you the file!

Share this post


Link to post
Share on other sites

The standard Sleep function isn't as accurate because it just rests with a very low CPU priority/usage... so there is a timelaps between the moment it says "time is over" and the moment where the cpu gets available for this info...

I guess that if you start CPU Burn at the same time as the standard Sleep the standard one will be much more accurate.

Using that theory, some tests:

AdlibEnable("burn", 1)

$timer = TimerInit()
Sleep (1000)
$diff = TimerDiff($timer)
MsgBox(0, "with burn - autoit "&@AutoItVersion, $diff)
ClipPut($diff)

Func burn()
    $blah = TimerDiff($timer)
EndFuncoÝ÷ Û}µÛY¨²ÖÚrH+¢éݦº ­©¬rZ,yß|ï½¼×Nºß5ãß

1000.01080577208

1000.0109460981

1000.00941788088

1000.01248233396

1000.01149270138

Average: ~1000.011 (+0.011 difference)

So the least accurate is the built-in sleep function with cpu burning, at a difference of -11.644.

The most accurate is Ludocus' sleep function at a difference of only +0.011.


The cake is a lie.www.theguy0000.com is currentlyUP images.theguy0000.com is currentlyUP all other *.theguy0000.com sites are DOWN

Share this post


Link to post
Share on other sites

hey, good test! thnx

Share this post


Link to post
Share on other sites

Having said that ... and if accuracy is very important, I'd simply adjust my sleep milliseconds accordingly to get as accurate as I could, versus sacrificing cpu usage.


[center]Common sense plays a role in the basics of understanding AutoIt... If you're lacking in that, do us all a favor, and step away from the computer.[/center]

Share this post


Link to post
Share on other sites

That doesn't really work either:

$xTra = 9.708;thats what came out Theguy000's post...
ClipPut('')
For $k=1 to 2
For $i = 1 to 10
$timer = TimerInit()
Call('_Sleep'&$k, 1000)
$diff = TimerDiff($timer)
ClipPut(ClipGet()&@CRLF&';'&$diff)
Next
Next

;and the following turned out;
;#1:
;1008.4600137727
;1015.39832576487
;1018.59677696467
;1009.74397584051
;1008.8365979475
;1014.93234475331
;1031.15982617903
;1031.04528648194
;1019.196015136
;1017.63324668359
;#2:
;998.316545817974
;996.804342451345
;989.328811343341
;996.950171041292
;998.00002514286
;1015.03738603649
;1015.21897336114
;990.587351185695
;997.588240963586
;999.04820305374

Func _Sleep1($sTime)
    Sleep($sTime+$xTra)
EndFunc

Func _Sleep2($sTime)
    Sleep($sTime-$xTra)
EndFunc

Share this post


Link to post
Share on other sites

What demands an accurate Sleep() time? :)

As far as I know, Sleep() is suppose to give your CPU a break, not use it as timing function.

Your _Sleep() UDF should be renamed to _Timing() because that's what it does. It doesn't make your CPU sleep.


[font="Georgia"]Chances are, I'm wrong.[/font]HotKey trouble?Stringregexp GuideAutoIT Current Version

Share this post


Link to post
Share on other sites

As far as using up CPU time, could one not use a hybrid method? Use the normal sleep to bring the delay within say 20ms then use the CPU intensive polling loop.

Func _Sleep($sTime)
    $timer=TimerInit()
    Sleep($sTime - 20)
    Do
        $tmp = TimerDiff($timer)
    Until $tmp >= $sTime
EndFunc

---------------------------

sleeping results

---------------------------

the results for normal sleep are:

1) 990.113547950927

2) 999.914793639974

The results for my _Sleep are:

1) 1000.02486349522

2) 1000.47743498126

---------------------------

OK

---------------------------

---------------------------

sleeping results

---------------------------

the results for normal sleep are:

1) 988.238728665235

2) 1000.61655880845

The results for hybrid _Sleep are:

1) 1000.03268571844

2) 1000.23801907784

---------------------------

OK

---------------------------

Share this post


Link to post
Share on other sites

I found this interesting topic in someone's signature. The following script tries to correction the difference from the fastest method. It does barely anything.

Dim $mTargetWait = 100
Dim $mResult[10]
Dim $mAvDiff = 0

;; Make some test results
For $i = 0 to UBound($mResult)-1
    $lTimer = TimerInit()
    _Sleep($mTargetWait)
    $mResult[$i] = TimerDiff($lTimer)
Next

;; Calculate average difference
$lTotal = 0
For $i = 0 to UBound($mResult)-1
    $lTotal += $mResult[$i]-$mTargetWait
Next
$mAvDiff = $lTotal/UBound($mResult)
_Print($mResult, "Average difference: " & $mAvDiff, "Sleep without correction")

;; Make some test results now with correction
For $i = 0 to UBound($mResult)-1
    $lTimer = TimerInit()
    _Sleep($mTargetWait)
    $mResult[$i] = TimerDiff($lTimer)
Next

;; Calculate average difference with correction
$lTotal = 0
For $i = 0 to UBound($mResult)-1
    $lTotal += $mResult[$i]-$mTargetWait
Next
$mAvDiff = $lTotal/UBound($mResult)
_Print($mResult, "Average difference: " & $mAvDiff, "Sleep WITH correction")


;; Trying to keep _Sleep as short as possible, to not stress the interpreter
Func _Sleep($B)
    $b -= $mAvDiff
    $a = TimerInit()
    Do
    Until TimerDiff($a) >= $b
EndFunc

;; Custom print function, that makes no sense at all lulz
Func _Print($pArray, $pText, $pTitle)
    $lReturn = ""
    For $i = 0 to UBound($pArray)-1
        $lReturn &= "[" & $i & "] = " & $pArray[$i] & @CRLF
    Next
    $lReturn &= @CRLF & @CRLF & $pText
    MsgBox(0, $pTitle, $lReturn)
EndFunc

Share this post


Link to post
Share on other sites

Just a thought but to address the CPU utilization issue just stack a sleep in there but subtract a small time then use the more intensive method.

Func _Sleep($sTime)
    $timer=TimerInit()
    If $sTime > 10 Then
        Sleep($sTime - 10)
    EndIf
    Do
        $tmp = TimerDiff($timer)
    Until $tmp >= $sTime
EndFunc

--- TTFN

Share this post


Link to post
Share on other sites

#15 ·  Posted (edited)

Func _Sleep($sTime)
    $timer = TimerInit()

    Do
        Sleep(1)
        $tmp = TimerDiff($timer)
    Until $tmp > ($sTime * .99); .99 works well for anything over 700ms, .95 works well for anything over 65ms
        
    While $tmp < $sTime
        $tmp = TimerDiff($timer)
    WEnd
EndFunc  ;==>_Sleep

Edited by Vakari

Share this post


Link to post
Share on other sites

Just a thought but to address the CPU utilization issue just stack a sleep in there but subtract a small time then use the more intensive method.

Or do what I did, and calculate the average correction required.

Share this post


Link to post
Share on other sites

mhmm..!, Interesting.. ;)

Share this post


Link to post
Share on other sites

TimerInit and TimerDiff also take some time to calculate.

Yes, and the interpreter also takes some time to do a loop. It is all based on how much your computer is being stressed. Your best bet if you want a super accurate sleep is to absolutely kill all process and services, and run your AutoIt script that uses a dynamically corrected Sleep. You could have it do 10 loops of trying just to get it almost right.

This could potentially lead to a sleep with a variation of 0.000001s and less.

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