News:

MASM32 SDK Description, downloads and other helpful links
MASM32.com New Forum Link
masmforum WebSite

Question on timing.

Started by Hjortur, March 27, 2009, 11:34:53 AM

Previous topic - Next topic

Hjortur

This is probably the wrong place to ask, but since i don't know any other I'll ask here.  ::)

I have just written a little .dll file containing, among other things, two procedures: Initf() and CleanUp().
Now what i want to do is initiate a timer when someone calls Init(), stop it temporarily when some other procedures are called, and finally display the results when CleanUp() is called. 
Now I need high precision timer, so what would be the best way to go about this ?

Hjörtur

Hjortur

I am thinking of something like QueryPerformanceCounter()  http://msdn.microsoft.com/en-us/library/ms644904(VS.85).aspx
or like GetTickCount()  http://msdn.microsoft.com/en-us/library/ms724408(VS.85).aspx

But I dont know how to use these functions, so if someone could post a short demo..... ::)   
It would be great. 

Hjörtur


MichaelW

This test code uses the high-resolution performance counter. I have never encountered a system that did not support a high-resolution performance counter, so I didn't bother to check the return value from QueryPerformanceFrequency. The code appears to work OK, but it's not well tested, and it does not protect against the procedures being called out of sequence. And I made it dependent on the FPU, because doing so made the 64-bit calculations somewhat easier.

; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
include \masm32\include\masm32rt.inc
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
.data
    hrtimer_pc_frequency  dq 0
    hrtimer_pc_count      dq 0
    hrtimer_pc_start      dq 0
    hrtimer_pc_elapsed    dq 0
.code
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
StartTimer proc

    ;----------------------------------------------
    ; This gets the pc frequency on the first call
    ; only, then captures a new starting pc count.
    ;----------------------------------------------

    test DWORD PTR hrtimer_pc_frequency, 0
    jnz @F
    invoke QueryPerformanceFrequency, ADDR hrtimer_pc_frequency
  @@:
    invoke QueryPerformanceCounter, ADDR hrtimer_pc_start
    ret
StartTimer endp
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««

SuspendTimer proc

    ;------------------------------------------------------------
    ; This calculates the elapsed pc count for the current timing
    ; period and adds it to the total elapsed pc count.
    ;------------------------------------------------------------

    invoke QueryPerformanceCounter, ADDR hrtimer_pc_count
    fild hrtimer_pc_elapsed   ; st(0)=elapsed
    fild hrtimer_pc_start     ; st(0)=start,st(1)=elapsed
    fild hrtimer_pc_count     ; st(0)=count,st(1)=start,st(2)=elapsed
    fsubr                     ; st(0)=count-start,st(1)=elapsed
    fadd                      ; st(0)=count-start+elapsed
    fistp hrtimer_pc_elapsed  ; st(0)-st(7) empty
    ret

SuspendTimer endp

; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««

ResumeTimer proc

    ;----------------------------------------
    ; This captures a new starting pc count.
    ;----------------------------------------

    invoke QueryPerformanceCounter, ADDR hrtimer_pc_start
    ret

ResumeTimer endp
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««

EndTimer proc

    ;-----------------------------------------------------------------
    ; This calculates the elapsed pc count for the last timing period,
    ; adds it to the total elapsed pc count, divides the total elapsed
    ; pc count by the pc counter frequency to get the total elapsed
    ; seconds, and displays the result.
    ;-----------------------------------------------------------------

    invoke QueryPerformanceCounter, ADDR hrtimer_pc_count
    fild hrtimer_pc_elapsed   ; st(0)=elapsed
    fild hrtimer_pc_start     ; st(0)=start,st(1)=elapsed
    fild hrtimer_pc_count     ; st(0)=count,st(1)=start,st(2)=elapsed
    fsubr                     ; st(0)=count-start,st(1)=elapsed
    fadd                      ; st(0)=count-start+elapsed
    fild hrtimer_pc_frequency ; st(0)=frequency,st(1)=count-start+elapsed
    fdiv                      ; st(0)=count-start+elapsed/frequency
    sub esp, 8                ; reserve room on stack for REAL8
    fstp QWORD PTR [esp]      ; st(0)-st(7) empty
    pop eax                   ; get low-order dword into eax
    pop edx                   ; get high-order dword into edx

    invoke crt_printf,chr$("%.4fs%c"),edx::eax,10

    ret

EndTimer endp

; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
start:
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««

    ;-----------------------------------------------------------
    ; This delay improves the timimg accuracy by allowing the
    ; system activities involved in launching an application to
    ; subside, so the timing code will see fewer interruptions.
    ;-----------------------------------------------------------

    invoke Sleep, 4000

    call StartTimer
    invoke Sleep, 500
    call EndTimer

    call StartTimer
    invoke Sleep, 500
    call SuspendTimer
    invoke Sleep, 2000
    call ResumeTimer
    invoke Sleep, 500
    call EndTimer

    inkey "Press any key to exit..."
    exit

; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
end start

eschew obfuscation

Hjortur

Thanks MichaelW, that is excactly what I was looking for.  :U
Thank you for taking the time to do this.

Hjörtur