Author Topic: An odd thing regarding timers (not counters)  (Read 890 times)

zedd151

  • Member
  • **
  • Posts: 241
An odd thing regarding timers (not counters)
« on: September 11, 2015, 09:21:51 AM »
I have been continuing my experiments with the timers, and I found something
that just doesn't make sense to me. I have two testbeds, they are exactly the
same except one uses ecx as a loop counter, and the other uses a variable.

I cannot understand why using the variable for the loop counter would make
the timing results DECREASE by ~ 320 - 340 ms! The loop counting part of the
equation is not even part of the timing cycle. I have checked the code and
even looked at the disassembled code with ollydbg, which confirmed that the
code is 15 bytes longer using the variable (outer loop size comparison), than
using ecx as loop counter.

edit ==
Nevermind the size, just checked after using align 4, same size inside the loop.

The 'algo' under test simply counts the lines in "windows.inc".

The typical results on my computer are this:


using ecx       using variable
-------------------------------
2835 ms         2522 ms
2759 ms         2430 ms
2761 ms         2428 ms
2762 ms         2429 ms
2760 ms         2435 ms
2764 ms         2432 ms
2763 ms         2428 ms
2760 ms         2430 ms
2763 ms         2431 ms
2764 ms         2432 ms

both testbeds posted here:
Code: [Select]
; ------------------------------------------------------
; Testbed using ecx as loop counter
; ------------------------------------------------------

        include \masm32\include\masm32rt.inc
        .686
        include \masm32\macros\timers.asm

        LoadFilex   proto :dword


    .data
        testtext    dd 0

    .code
    main:
        fn LoadFilex, "C:\masm32\include\windows.inc"
        mov testtext, esi
        invoke GetCurrentProcess
        invoke SetProcessAffinityMask, eax, 1
        mov ecx, 10 ; initialize ecx for use as counter

; outer loop -------------------------------------------------------
            align 4
            top:
            push ecx ; save the loop count
            invoke Sleep, 500

        ; - timer begin --------------------------------------------
                align 4
                timer_begin 1000, HIGH_PRIORITY_CLASS
                    pushad
                    call testy ; savage algorithm - lol
                    popad
                timer_end
               
        ; - timer end ----------------------------------------------
       
                print str$(eax), 20h, "ms", 10, 13
               
            pop ecx ; pop the loop count back into ecx
            dec ecx ; - the difference is here uses ecx versus variable
            jnz top
           
; end outer loop ---------------------------------------------------
   
        inkey
        invoke GlobalFree, testtext
        invoke ExitProcess, 0
       

    testy proc
        xor eax, eax
        mov ecx, testtext
        dec ecx
    @@:
        inc ecx
        cmp byte ptr [ecx], 0
        je @f
        .if byte ptr [ecx] == 13
        inc eax
        .endif
        jmp @b
    @@:
        ret
    testy endp

    LoadFilex proc lpName:dword
    local hFile :dword, fl :dword, bRead :dword, hMem$ :dword
        invoke CreateFile, lpName, 80000000h, 0, 0, 3, 80h, 0
        mov hFile, eax
        invoke GetFileSize, hFile, 0
        inc eax
        mov fl, eax
        invoke GlobalAlloc, GPTR, fl
        mov hMem$, eax
        invoke ReadFile, hFile, hMem$, fl, addr bRead, 0
        invoke CloseHandle, hFile
        mov esi, hMem$
        mov ecx, fl
        ret
    LoadFilex endp
 
    end main
; ------------------------------------------------------
; Testbed using variable as loop counter
; ------------------------------------------------------
        include \masm32\include\masm32rt.inc
        .686
        include \masm32\macros\timers.asm

        LoadFilex   proto :dword

    .data
        loopctr     dd 10 ; initialized to 10
        testtext    dd 0
       
    .code
    start:
        fn LoadFilex, "C:\masm32\include\windows.inc"
        mov testtext, esi
        invoke GetCurrentProcess
        invoke SetProcessAffinityMask, eax, 1
       
; outer loop -------------------------------------------------------
            align 4
            top:
                invoke Sleep, 500
               
        ; - timer begin --------------------------------------------
                align 4
                timer_begin 1000, HIGH_PRIORITY_CLASS
                    pushad
                    call testy ; savage algorithm - lol
                    popad
                timer_end
               
        ; - timer end ----------------------------------------------
       
                print str$(eax), 20h, "ms", 10, 13
               
            dec loopctr ; - the difference is here uses variable versus ecx
            jnz top
           
; end outer loop ---------------------------------------------------

        inkey
        invoke GlobalFree, testtext
        invoke  ExitProcess, 0

    testy proc
        xor eax, eax
        mov ecx, testtext
        dec ecx
    @@:
        inc ecx
        cmp byte ptr [ecx], 0
        je @f
        .if byte ptr [ecx] == 13
        inc eax
        .endif
        jmp @b
    @@:
        ret
    testy endp

    LoadFilex proc lpName:dword
    local hFile :dword, fl :dword, bRead :dword, hMem$ :dword
        invoke CreateFile, lpName, 80000000h, 0, 0, 3, 80h, 0
        mov hFile, eax
        invoke GetFileSize, hFile, 0
        inc eax
        mov fl, eax
        invoke GlobalAlloc, GPTR, fl
        mov hMem$, eax
        invoke ReadFile, hFile, hMem$, fl, addr bRead, 0
        invoke CloseHandle, hFile
        mov esi, hMem$
        mov ecx, fl
        ret
    LoadFilex endp

    end start



Links broken - to be remedied soon
----------------------------------------------
hutch: "MASM does not have bugs, it just has features you need to understand." 8)

jj2007

  • Member
  • *****
  • Posts: 7558
  • Assembler is fun ;-)
    • MasmBasic
Re: An odd thing regarding timers (not counters)
« Reply #1 on: September 11, 2015, 09:53:58 AM »
See Code location sensitivity of timings
Try inserting
Code: [Select]
nops 20   ; or any other number
 align 8
before one or both the loops. Or google for instruction cache boundary.

zedd151

  • Member
  • **
  • Posts: 241
Re: An odd thing regarding timers (not counters)
« Reply #2 on: September 11, 2015, 10:19:34 AM »
Okay thanks Agner Jochen, - lol

I tried first with the nops and used align 16 in the timer loops.

No change.

Next, I did the same for the external proc that is called from inside the loop, that did the trick:

Code: [Select]
using ecx

2464 ms ; first always seems to be longer - same as electronic timer circuits
2423 ms
2424 ms
2423 ms
2425 ms
2423 ms
2424 ms
2423 ms
2422 ms
2424 ms
Press any key to continue ...

using variable

2501 ms
2425 ms
2423 ms
2423 ms
2423 ms
2424 ms
2419 ms
2423 ms
2425 ms
2422 ms
Press any key to continue ...


Now since this appears to work ok, I will next experiment with making a
plugin out of one or the other timer testbeds. Should work like this:

It will be very similar to my plugin builder where code will be assembled on the fly
You select an algorithm you wish to test, then open the testbed plugin.

The code will be generated automatically, compiled, then a batch file
will also be created then run to test the algo!  :biggrin:  8)  :greenclp:
Links broken - to be remedied soon
----------------------------------------------
hutch: "MASM does not have bugs, it just has features you need to understand." 8)

zedd151

  • Member
  • **
  • Posts: 241
Re: An odd thing regarding timers (not counters)
« Reply #3 on: September 14, 2015, 08:16:45 PM »
Ooops!

I posted in the wrong thread.
Links broken - to be remedied soon
----------------------------------------------
hutch: "MASM does not have bugs, it just has features you need to understand." 8)