• Diese Funktion zeigt wie man den Zeitunterschied ausrechnen kann.
    Ansonsten bitte die TimerDiff (EN) / TimerDiff (DE) Funktion verwenden.

    - MSDN System Information Functions: Kernel32.dll QueryPerformanceCounter
    - MSDN System Information Functions: Kernel32.dll QueryPerformanceFrequency

    [autoit]

    Func QueryPerformance($N = 0)
    Static $F, $A, $Q, $P, $X
    Local $R
    If $N And Not $P Then
    $F = DllCall("Kernel32.dll", "Int", "QueryPerformanceFrequency", "Int64*", "")
    $F = $F[1]
    $P = DllCall("Kernel32.dll", "Int", "QueryPerformanceCounter", "Int64*", "")
    $P = $P[1]
    Return $F + $P + ($X = 0) + ($A = 0)
    EndIf
    $Q = DllCall("Kernel32.dll", "Int", "QueryPerformanceCounter", "Int64*", "")
    $A = $A + $Q[1] - $P
    $P = $Q[1]
    $X = $X + 1
    $R = $A / $X / $F
    Return ($N And $X = $N) ? BitShift($X = $X - 1, -64) : ($N = 0 And $R) ? ($R + ($A = 0) + ($P = 0) + ($X = 0)) : 1
    EndFunc ;==> QueryPerformance() AutoIt v3.3.12.0

    [/autoit]

    Kürzere Funktion:

    [autoit]

    Func QueryPerformance($R = 0)
    Static $P, $F, $C
    If Not $F Then
    $F = DllCall("Kernel32.dll", "Int", "QueryPerformanceFrequency", "Int64*", "")
    $F = $F[1]
    EndIf
    $C = DllCall("Kernel32.dll", "Int", "QueryPerformanceCounter", "Int64*", "")
    $C = $C[1]
    If $R Then
    $P = $C
    Return $C / $F
    Else
    Return ($C - $P) / $F
    EndIf
    EndFunc

    [/autoit]


    Anwendungsbeispiele:

    [autoit]

    QueryPerformance(1) ; Zähler initialisieren
    Sleep(2500)
    $End = QueryPerformance(0) ; Gebrauchte Zeit auslesen (+ Zurücksetzten für nächsten Lauf)
    MsgBox(0, "QueryPerformance()", $End)

    [/autoit][autoit][/autoit][autoit][/autoit][autoit]

    $i = 0
    QueryPerformance(1) ; Zähler initialisieren
    While $i <> 10000000
    $i += 1
    WEnd
    $End = QueryPerformance(0) ; Gebrauchte Zeit auslesen (+ Zurücksetzten für nächsten Lauf)
    MsgBox(0, "QueryPerformance()", $End)

    [/autoit]


    PS: Schade um die Interessante Diskussion vor dem Platten-Crash

    7 Mal editiert, zuletzt von kaesereibe (2. September 2014 um 12:41)

  • Interessante Implementierung.

    Allerdings finde ich die Variante, wie sie in AutoIt (und vielen anderen Sprachen gehandhabt wird) etwas einfacher und verständlicher:

    [autoit]

    Func _Timer_Init()
    Return __Timer_QueryPerformanceCounter()
    EndFunc ;==>_Timer_Init

    [/autoit][autoit][/autoit][autoit]

    Func _Timer_Diff($iTimeStamp)
    Return 1000 * (__Timer_QueryPerformanceCounter() - $iTimeStamp) / __Timer_QueryPerformanceFrequency()
    EndFunc ;==>_Timer_Diff

    [/autoit]

    bzw. FreeBasic:

  • - Anwendungsbeispiele hinzugefügt

    Hier funktioniert das ganze über eine Funktion
    - QueryPerformance(1) ==> Zähler initialisieren
    - $End = QueryPerformance(0) ==> Gebrauchte Zeit auslesen (+ Zurücksetzten für nächsten Lauf)

    Es zeigt halt einfach eine andere Art der Implementierung von QueryPervormanceCounter an =)

  • 2te kürzere und schnellere Funktion hinzugefügt
    Aufruf ist gleich geblieben:

    Code
    QueryPerformance(1) ==> Zähler initialisieren
    $End = QueryPerformance(0) ==> Gebrauchte Zeit auslesen (+ Zurücksetzten für nächsten Lauf)

    siehe Anwendungsbeispiel oben

  • AutoIt nutzt intern durchaus die API-Dlls, greift aber für DLLCall nicht darauf zurück.
    Kannst du selbst testen:

    Spoiler anzeigen
    [autoit]

    Global Const $s_Dll = "kernel32.dll"
    Global Const $s_Proc = "QueryPerformanceCounter"
    Global Const $N = 1e5

    [/autoit] [autoit][/autoit] [autoit]

    ; Ohne DllOpen
    $iT = TimerInit()
    For $i = 1 To $N
    DllCall($s_Dll, "BOOL", $s_Proc, "Int64*", "")
    Next
    $iT = TimerDiff($iT)
    ConsoleWrite(StringFormat("% 25s: \t%7.4f ms\n", "ohne DLLOpen()", $iT / $N))

    [/autoit] [autoit][/autoit] [autoit]

    ; Ohne DllOpen + Ordinal number
    $iT = TimerInit()
    $ord = DllGetProcOrdinal($s_Dll, $s_Proc)
    For $i = 1 To $N
    DllCall($s_Dll, "BOOL", $ord, "Int64*", "")
    Next
    $iT = TimerDiff($iT)
    ConsoleWrite(StringFormat("% 25s: \t%7.4f ms\n", "ohne DLLOpen() + Ord", $iT / $N))

    [/autoit] [autoit][/autoit] [autoit]

    ; Mit DllOpen
    $iT = TimerInit()
    $h_DLL = DllOpen($s_Dll)
    For $i = 1 To $N
    DllCall($h_DLL, "BOOL", $s_Proc, "Int64*", "")
    Next
    DllClose($h_DLL)
    $iT = TimerDiff($iT)
    ConsoleWrite(StringFormat("% 25s: \t%7.4f ms\n", "mit DLLOpen()", $iT / $N))

    [/autoit] [autoit][/autoit] [autoit]

    ; Mit DllOpen + OrdinalNumber
    $iT = TimerInit()
    $ord = DllGetProcOrdinal($s_Dll, $s_Proc)
    $h_DLL = DllOpen($s_Dll)
    For $i = 1 To $N
    DllCall($h_DLL, "BOOL", $ord, "Int64*", "")
    Next
    DllClose($h_DLL)
    $iT = TimerDiff($iT)
    ConsoleWrite(StringFormat("% 25s: \t%7.4f ms\n", "mit DLLOpen() + Ord", $iT / $N))

    [/autoit] [autoit][/autoit] [autoit]

    ; Mit DllCallAddress
    $iT = TimerInit()
    $h_KRNL32 = DllOpen("kernel32.dll")
    $h_Dll = DllCall($h_KRNL32, "handle", "GetModuleHandleW", "wstr", $s_Dll)[0] ; die Startadresse der Dll im Speicher (falls bereits geladen - ansonsten LoadLibraryW)
    If $h_Dll = 0 Then $h_Dll = DllCall($h_KRNL32, "handle", "LoadLibraryW", "wstr", $s_Dll)[0] ; falls GetModuleHandle nix findet (eigentlich nur bei externen dlls welche noch extra geladen werden müssen)
    $p_Proc = DllCall($h_KRNL32, "ptr", "GetProcAddress", "handle", $h_Dll, "str", $s_Proc)[0] ; Die Adresse des Beginns der Prozedur im Speicher
    For $i = 1 To $N
    DllCallAddress("BOOL", $p_Proc, "Int64*", "")
    Next
    DllCall($h_KRNL32, "BOOL", "FreeLibrary", "HANDLE", $h_Dll) ; Handle zur dll wieder schließen
    DllClose($h_KRNL32)
    $iT = TimerDiff($iT)
    ConsoleWrite(StringFormat("% 25s: \t%7.4f ms\n", "mit DllCallAddress()", $iT / $N))

    [/autoit] [autoit][/autoit] [autoit]

    ; #FUNCTION# ======================================================================================
    ; Name ..........: DllGetProcOrdinal()
    ; Description ...: returns the procedure's ordinal number in it's dll-file
    ; Syntax ........: DllGetProcOrdinal(Const $s_Module, Const $s_Procedure)
    ; Parameters ....: $s_Module - the dll filename
    ; $s_Procedure - the name of the procedure
    ; Return values .: Success: the ordinal value of $s_Procedure
    ; Failure: -1
    ; @error = 1: procedure not found inside the dll
    ; 2: couldn't open the dll-file
    ; 3: couldn't find the procedure in the dll by it's procedure name
    ; Author ........: AspirinJunkie
    ; =================================================================================================
    Func DllGetProcOrdinal(Const $s_Module, Const $s_Procedure)
    Local Const $h_KRNL32 = DllOpen("kernel32.dll")

    [/autoit] [autoit][/autoit] [autoit]

    ; Open the dll:
    Local $h_Module = DllCall($h_KRNL32, "handle", "GetModuleHandleW", "wstr", $s_Module)[0]
    If $h_Module = 0 Then
    $h_Module = DllCall($h_KRNL32, "handle", "LoadLibraryW", "wstr", $s_Module)[0]
    If $h_Module = 0 Then Return SetError(2, 0, -1)
    EndIf

    [/autoit] [autoit][/autoit] [autoit]

    ; Get address of the procedure
    Local $p_Procedure = DllCall($h_KRNL32, "ptr", "GetProcAddress", "handle", $h_Module, "str", $s_Procedure)[0]
    If $p_Procedure = 0 Then Return SetError(3, 0, -1)

    [/autoit] [autoit][/autoit] [autoit]

    ; Iterate over the ordinal values and compare with the procedure address
    Local $ord = 1, $p_Proc
    Do
    $p_Proc = DllCall($h_KRNL32, "ptr", "GetProcAddress", "handle", $h_Module, "INT", $ord)[0]
    If $p_Proc = $p_Procedure Then
    DllCall($h_KRNL32, "BOOL", "FreeLibrary", "HANDLE", $h_Module)
    DllClose($h_KRNL32)
    Return $ord
    EndIf
    $ord += 1
    Until $p_Proc = 0
    DllCall($h_KRNL32, "BOOL", "FreeLibrary", "HANDLE", $h_Module)
    DllClose($h_KRNL32)
    Return SetError(1, 0, -1)
    EndFunc ;==>DllGetProcOrdinal

    [/autoit]

    3 Mal editiert, zuletzt von AspirinJunkie (8. Januar 2015 um 11:27)