Sleep() - Test

02/06/2013 22:49 Achat#1
Hi epvp!

Mir ist aufgefallen, dass die sleep() Funktion sehr ungenau ist.
Siehe dazu auch meinen Beitrag hier:
[Only registered and activated users can see links. Click Here To Register...]

Um eine Fehlfunktion meines Computers auszuschließen, möchte ich die Sleep Funktion mit euch testen:

Code:
[noparse]
#region ;**** Directives created by AutoIt3Wrapper_GUI ****
#AutoIt3Wrapper_UseX64=n
#AutoIt3Wrapper_Res_requestedExecutionLevel=asInvoker
#endregion ;**** Directives created by AutoIt3Wrapper_GUI ****
#include <Array.au3>
_SleepTest()
Func _SleepTest()
	Local $hTimer
	Local $aSleep[501][3], $sTable
	ProgressOn('epvpSleepTest', 'Fortschritt', '', -1, -1, 16)
	For $i = 0 To 500
		$hTimer = TimerInit()
		Sleep($i)
		$aSleep[$i][1] = TimerDiff($hTimer)
		$aSleep[$i][2] = Round(TimerDiff($hTimer) / $i * 100) & '%'
		$aSleep[$i][0] = $i
		ProgressSet($i / 501 * 100, 'Sleep(' & $i & ')')
	Next
	ProgressOff()
	$sTable = 'Ergebnisse des epvpSleepTests[spoiler][table="head"]' & 'Sleep | reale Sleepzeit in ms | Übereinstimmung %' & @CRLF
	For $i = 0 To UBound($aSleep) - 2
		$sTable &= $aSleep[$i][0] & '|' & $aSleep[$i][1] & '|' & $aSleep[$i][2] & @CRLF
	Next
	$sTable &= $aSleep[UBound($aSleep) - 1][0] & '|' & $aSleep[UBound($aSleep) - 1][1] & '|' & $aSleep[UBound($aSleep) - 1][2] & @CRLF & '[/Table][/Spoiler]'
	ClipPut($sTable)
	MsgBox(0x40000 + 64, 'epvpSleepTest', 'Die Ergebnisse des Sleep-Tests wurden als Tabelle in die Zwischenablage kopiert und stehen nun zum direkten Einfügen in epvp bereit.')
EndFunc   ;==>_SleepTest
[/noparse]
Script einfach ausführen und die Tabelle hier einfügen :).

Ergebnisse des epvpSleepTests

MfG

€:

Quote:
Originally Posted by butter123 View Post
[Only registered and activated users can see links. Click Here To Register...]

wie wärs damit? :)
[Only registered and activated users can see links. Click Here To Register...]

Code:
[noparse]
#region ;**** Directives created by AutoIt3Wrapper_GUI ****
#AutoIt3Wrapper_UseX64=n
#AutoIt3Wrapper_Res_requestedExecutionLevel=asInvoker
#endregion ;**** Directives created by AutoIt3Wrapper_GUI ****
#include <Array.au3>

Global $hDll = DllOpen('ntdll.dll')

_SleepTest()
Func _SleepTest()
	Local $hTimer
	Local $aSleep[501][3], $sTable
	Local $iAccuracy = 5
	ProgressOn('epvpSleepTest', 'Fortschritt', '', -1, -1, 16)
	For $i = 0 To 500
		$hTimer = TimerInit()
		For $ia = 1 To $iAccuracy
			_HighPrecisionSleep($i * 1000, $hDll)
		Next
		$aSleep[$i][1] = TimerDiff($hTimer)
		$aSleep[$i][1] = $aSleep[$i][1] / $iAccuracy
		$aSleep[$i][2] = Round($aSleep[$i][1] / $i * 100) & '%'
		$aSleep[$i][0] = $i
		ProgressSet($i / 501 * 100, '_HighPrecisionSleep(' & $i & ')')
	Next
	ProgressOff()
	$sTable = 'Ergebnisse des epvpHighPrecisionSleepTests[spoiler][table="head"]' & '_HighPrecisionSleep | reale Sleepzeit in ms | Übereinstimmung %' & @CRLF
	For $i = 0 To UBound($aSleep) - 2
		$sTable &= $aSleep[$i][0] & '|' & $aSleep[$i][1] & '|' & $aSleep[$i][2] & @CRLF
	Next
	$sTable &= $aSleep[UBound($aSleep) - 1][0] & '|' & $aSleep[UBound($aSleep) - 1][1] & '|' & $aSleep[UBound($aSleep) - 1][2] & @CRLF & '[/Table][/Spoiler]'
	ClipPut($sTable)
	MsgBox(0x40000 + 64, 'epvpHighPrecisionSleepTest', 'Die Ergebnisse des HighPrecisionSleep-Tests wurden als Tabelle in die Zwischenablage kopiert und stehen nun zum direkten Einfügen in epvp bereit.')
EndFunc   ;==>_SleepTest

; #FUNCTION#;===============================================================================
;
; Name...........: _HighPrecisionSleep()
; Description ...: Sleeps down to 0.1 microseconds
; Syntax.........: _HighPrecisionSleep( $iMicroSeconds, $hDll=False)
; Parameters ....:  $iMicroSeconds		- Amount of microseconds to sleep
;				   $hDll  - Can be supplied so the UDF doesn't have to re-open the dll all the time.
; Return values .: None
; Author ........: Andreas Karlsson (monoceres)
; Modified.......:
; Remarks .......: Even though this has high precision you need to take into consideration that it will take some time for autoit to call the function.
; Related .......:
; Link ..........;
; Example .......; No
;
;;==========================================================================================
Func _HighPrecisionSleep($iMicroSeconds, $hDll = False)
	Local $hStruct, $bLoaded
	If Not $hDll Then
		$hDll = DllOpen("ntdll.dll")
		$bLoaded = True
	EndIf
	$hStruct = DllStructCreate("int64 time;")
	DllStructSetData($hStruct, "time", -1 * ($iMicroSeconds * 10))
	DllCall($hDll, "dword", "ZwDelayExecution", "int", 0, "ptr", DllStructGetPtr($hStruct))
	If $bLoaded Then DllClose($hDll)
EndFunc   ;==>_HighPrecisionSleep
[/noparse]
Ergebnisse des epvpHighPrecisionSleepTests
02/06/2013 22:59 MegaCoolblood#2
Ergebnisse des epvpSleepTests
02/06/2013 23:02 omer36#3
das sind millisec. ....glaub kaum, dass daraus irgendwas schief laufen würde..

Ergebnisse des epvpSleepTests

€ sieht aber seltsamm aus bei mir..
bis sleep(10) hat alles etwa 9ms
von 11-20 alles 19ms
von 21-30 alles 29ms
usw..
02/06/2013 23:04 Njahs#4
02/06/2013 23:29 Achat#5
Quote:
Originally Posted by omer36 View Post
das sind millisec. ....glaub kaum, dass daraus irgendwas schief laufen würde..
Besonders die Ungenauigkeit bei <10 von bis zu 1000(!)% :mad: ist ärgerlich

Ich habe in einer While Schleife eine Function, die immer aufgerufen wird, die Function benötigt zur Ausführung zwischen 0.01ms und 0.007 ms.
Code:
sleep(1) ;1 Millisekunde
wäre für diese Schleife natürlich perfekt, um eine Überlastung der CPU zu verhindern.

Es handelt sich hier um einen Aimbot.
Das Spiel läuft mit 62.5 fps, also kommt ca. alle 16 ms ein neues Bild.
Und wenn AutoIt dann 10ms pausiert anstatt 1, dann verzögert sich alles und die Effizienz (AutoIt o.O) des Programms sinkt.

Ich habe das in meiner Schleife so gelöst:
Code:
func _Func()
;...
local $i=0
;....
while 1
;.....
If Mod($i, 500) = 0 Then Sleep(1)
$i+=1
wend
endfunc
So optimal ist das zwar nicht, aber "Not macht erfinderisch"

Quote:
Originally Posted by http://web.slzm.de/blog/wp-content/uploads/AutoIt_leicht_gemacht_2009-07-11.pdf
[Only registered and activated users can see links. Click Here To Register...]
Es würde also irgendwann zum Crash führen?

Vielleicht finden wir ja eine Alternative zu sleep()

MfG
02/07/2013 00:08 Requi#6
Ergebnisse des epvpSleepTests
02/07/2013 00:22 butter123#7
[Only registered and activated users can see links. Click Here To Register...]

wie wärs damit? :)
02/07/2013 01:38 lolkop#8
spielt man das spiel auf etwas höherer präzisionsebene weiter, so zeigt sich ein recht klares bild, über die sleep funktion:

Code:
$genauigkeit = 5
For $x=0 To 500
	$summe = 0
	For $i=0 To $genauigkeit
		$t = TimerInit()
		Sleep($x)
		$summe += TimerDiff($t)
	Next
	ConsoleWrite($x&'ms -> '&$summe/$genauigkeit&'ms'&@CRLF)
Next
je höher wir hier die genauigkeit setzen, umso realistischer werden die ergebnisse (umso länger dauert der test aber natürlich)... wenn man das ganze mal überblickt, ergibt sich ein recht genaues bild, in welchen stufen autoit's sleep funktion arbeitet.

hier mal eine auflistung meiner ergebnisse für sleeps von 0-50ms mit genauigkeit 100:

was man an meinem beispiel schön erkennt ist, das es keinen unterschied macht, ob ich bei mir sleep(1) oder sleep(11) ausführe, da beide exakt die selbe wartezeit verursachen.
02/07/2013 08:03 Lawliet#9
Eine Alternative wäre evl. Eine eige Sleep Funktion über nen Timer zu implementieren. Da ich gerade am Handy bin kann ich allerdings nicht testen, ob diese dann bessere Ergebnisse liefern würde.
02/07/2013 09:21 Der-Eddy#10
Soweit ich weiß geht Sleep irgendwelche Berechnungen am Prozessor durch sodass auf PCs mit einem besseren Prozessor die reale Sleep Zeit kürzer ist als auf anderen
Quote:
Originally Posted by Lawliet! View Post
Eine Alternative wäre evl. Eine eige Sleep Funktion über nen Timer zu implementieren. Da ich gerade am Handy bin kann ich allerdings nicht testen, ob diese dann bessere Ergebnisse liefern würde.
Dann muss man aber immernoch mit Verzögerungen rechnen da die Befehle selber auch noch mal Zeit verbrauchen
02/07/2013 16:46 .SkyneT.#11
Quote:
Originally Posted by Der-Eddy View Post
Soweit ich weiß geht Sleep irgendwelche Berechnungen am Prozessor durch sodass auf PCs mit einem besseren Prozessor die reale Sleep Zeit kürzer ist als auf anderen
Nein.
So sieht das vielleicht auf kleinen AVR Prozessoren aus aber sicher nicht
bei der CPU eines PC's.

Vereinfacht wird der CPU gesagt:
"Für foo.exe wird die nächsten x ms nichts berechnet"

Das die Zeit die hier gemessen wird von vielen anderen Faktoren als
Sleep() alleine abhängt sollte auch erwähnt werden..
02/12/2013 16:54 SeYz#12
epvpSleepTest
02/12/2013 17:03 YatoDev#13
Ergebnisse des epvpSleepTests
02/12/2013 17:09 Schlüsselbein#14
Sleep garantiert dir nur, für die angegebene Zeit _mindestens_ zu warten. Die Beispiele, wo Sleep() weniger lang als angefordert wartet, müssten Messfehler sein.

Du arbeitest mit keinem µC (bei dem man exakt sagen kann, wie viele ms/µs ein bestimmter Befehl brauch), sondern hast OS, Scheduler etc. mit an Board.
02/12/2013 18:59 Achat#15
Quote:
Originally Posted by butter123 View Post
[Only registered and activated users can see links. Click Here To Register...]

wie wärs damit? :)
Hab den 1. Post aktualisiert :)

Sieht leider auch nicht viel besser aus.

MfG

€:

Quote:
Originally Posted by Lawliet! View Post
Eine Alternative wäre evl. Eine eige Sleep Funktion über nen Timer zu implementieren.
Deine Func interessiert mich.

MfG