News:

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

code loop

Started by ecube, November 26, 2008, 11:40:20 PM

Previous topic - Next topic

ecube

can someone please tell me which method is more optimal in keeping a program alive and why

@@:
invoke Sleep,10000 ;whatever number
jmp @B

or

invoke CreateEvent, 0, TRUE, FALSE, ctx("optional name")
mov ourevent,eax

invoke WaitForSingleObject,ourevent, INFINITE

MichaelW

I think it depends on what you are doing. For many applications there appears to be no provably significant reason to select one method over the other. One application that I have encountered where the event object method was the best choice, because it required less coding, was in a test app were I created multiple threads and needed to wait for all of them to finish.

I assume you intended to add some sort of conditional exit from your Sleep loop. For any Sleep value other than zero, I suspect the event object method would provide a faster response. This might be an interesting test to perform, if I can find time.
eschew obfuscation

MichaelW

I'm not really satisfied with this test because I cannot find any way to get consistent timings, but it looks like the event object method may provide a generally faster response than Sleep, 0.

; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
    include \masm32\include\masm32rt.inc

    T0 PROTO :DWORD
    T1 PROTO :DWORD
    T2 PROTO :DWORD

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

timer_start MACRO

    IFNDEF pc_freq
      .data
        pc_freq   dq 0
        pc_start  dq 0
        pc_stop   dq 0
        time      dq 0
      .code
      invoke QueryPerformanceFrequency, ADDR pc_freq
    ENDIF
    invoke QueryPerformanceCounter, ADDR pc_stop
  @@:
    ; Sync with the PC to minimize uncertainty.
    invoke QueryPerformanceCounter, ADDR pc_start
    mov eax, DWORD PTR pc_stop
    cmp eax, DWORD PTR pc_start
    je  @B

ENDM

timer_stop MACRO

    invoke QueryPerformanceCounter, ADDR pc_stop
    mov eax, DWORD PTR pc_stop
    mov edx, DWORD PTR pc_stop+4
    sub eax, DWORD PTR pc_start
    sbb edx, DWORD PTR pc_start+4
    push edx
    push eax
    fild QWORD PTR [esp]
    fild pc_freq
    fdiv
    fstp time

ENDM

; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
    .data
      hEvent dd 0
      flag   dd 0
    .code
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
start:
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««

    invoke GetCurrentProcess
    invoke SetPriorityClass, eax, HIGH_PRIORITY_CLASS

    invoke CreateEvent, 0, TRUE, FALSE, NULL
    mov hEvent, eax

    invoke Sleep, 3000

    REPEAT 4
      timer_start
      timer_stop
      invoke crt_printf, chr$("empty cycle: %.6fs%c"), time, 10
    ENDM

    invoke Sleep, 2000
    print chr$(13,10)

    REPEAT 4
      mov flag, 0
      invoke crt__beginthread, ADDR T0, 0, NULL
      invoke Sleep, 200
      timer_start
      inc flag
    ENDM

    invoke Sleep, 2000
    print chr$(13,10)

    REPEAT 4
      mov flag, 0
      invoke crt__beginthread, ADDR T1, 0, NULL
      invoke Sleep, 200
      timer_start
      inc flag
    ENDM

    invoke Sleep, 2000
    print chr$(13,10)

    REPEAT 4
      invoke ResetEvent, hEvent
      invoke crt__beginthread, ADDR T2, 0, NULL
      invoke Sleep, 200
      timer_start
      invoke SetEvent, hEvent
    ENDM

    invoke Sleep, 2000
    print chr$(13,10)

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

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

T0 proc junk:DWORD

  @@:
    invoke Sleep, 0
    cmp flag, 0
    je  @B
    timer_stop
    invoke crt_printf, chr$("sleep,0 loop: %.6fs%c"), time, 10
    ret

T0 endp

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

T1 proc junk:DWORD

  @@:
    invoke Sleep, 1
    cmp flag, 0
    je  @B
    timer_stop
    invoke crt_printf, chr$("sleep,1 loop: %.6fs%c"), time, 10
    ret

T1 endp

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

T2 proc junk:DWORD

    invoke WaitForSingleObject, hEvent, INFINITE
    timer_stop
    invoke crt_printf, chr$("wait object : %.6fs%c"), time, 10
    ret

T2 endp

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

end start


Typical results on my Windows 2000 P3 system:

empty cycle: 0.000002s
empty cycle: 0.000002s
empty cycle: 0.000002s
empty cycle: 0.000002s

sleep,0 loop: 0.000006s
sleep,0 loop: 0.000389s
sleep,0 loop: 0.000649s
sleep,0 loop: 0.000688s

sleep,1 loop: 0.010014s
sleep,1 loop: 0.010252s
sleep,1 loop: 0.010267s
sleep,1 loop: 0.010276s

wait object : 0.000137s
wait object : 0.000013s
wait object : 0.000175s
wait object : 0.000017s


eschew obfuscation

ecube

herm interesting MichaelW, thanks for the code.

empty cycle: 0.000002s
empty cycle: 0.000002s
empty cycle: 0.000002s
empty cycle: 0.000002s

sleep,0 loop: 0.000003s
sleep,0 loop: 0.000141s
sleep,0 loop: 0.000184s
sleep,0 loop: 0.000218s

sleep,1 loop: 0.000979s
sleep,1 loop: 0.001115s
sleep,1 loop: 0.001976s
sleep,1 loop: 0.001987s

wait object : 0.000005s
wait object : 0.000005s
wait object : 0.000005s
wait object : 0.000004s

Press any key to exit...