Jump to content
Sign in to follow this  
ABANDONEDACC

Which one of these two AutoIt functions is faster?

Recommended Posts

ABANDONEDACC

===================================================

EDIT: Benchmark results and followup optimization question.

===================================================

Have any of you wondered about the speed difference of SEVEN calls to PixelGetColor() vs. ONE call to PixelChecksum()?

Have any of you got any insight into this?

PixelGetColor() is fast and uses the WinAPI call to get the color for a single pixel very quickly.

PixelChecksum() is (or used to be, according to the helpfile) slow but will allow you to read all those 7 pixels at once and get a condensed checksum for them, but the AutoIt helpfile has this to say about it:

Returns the checksum value of the region.

Previous versions were extremely slow, however the function is now significantly faster. Using the step parameter is no longer recommended. The performance gain from using a larger step is not nearly as noticeable since the function is faster all around. Also, the larger the step, the less reliable the checksum becomes when used to detect small changes in the region.

So my question is which of the following is faster?

PixelGetColor():

If Hex( PixelGetColor( $coords[0]+1, $coords[1] ), 6 ) == Hex($hColor,6) AND _ ; 1 pixel to the right
        Hex( PixelGetColor( $coords[0]+2, $coords[1] ), 6 ) == Hex($hColor,6) AND _ ; 2 pixels to the right
        Hex( PixelGetColor( $coords[0]+3, $coords[1] ), 6 ) == Hex($hColor,6) AND _ ; 3 pixels to the right
        Hex( PixelGetColor( $coords[0], $coords[1]+1 ), 6 ) == Hex($hColor,6) AND _ ; 1 pixel down
        Hex( PixelGetColor( $coords[0]+1, $coords[1]+1 ), 6 ) == Hex($hColor,6) AND _ ; 1 pixel down and 1 to the right
        Hex( PixelGetColor( $coords[0]+2, $coords[1]+1 ), 6 ) == Hex($hColor,6) AND _ ; 1 pixel down and 2 to the right
        Hex( PixelGetColor( $coords[0]+3, $coords[1]+1 ), 6 ) == Hex($hColor,6) Then ; 1 pixel down and 3 to the right
    ; DO SOMETHING
EndIf

Either of these methods will run at about 15 times per second for different areas of the screen and I'm wondering if multiple calls to PixelGetColor() is faster due to the simplicity of the function, or if one PixelChecksum() call will be faster despite it having to calculate a checksum for the region it's looking at. It's a question of which is faster; either a natively compiled function which checks all the pixels at once but does a complex job with them to calculate a checksum (PixelChecksum) or the rapid, but manual use of a tiny and very optimized function (PixelGetColor).

The goal is to look for a 2 pixels tall, 3 pixels wide grid of pixels in the most optimized way possible, and I am currently using the PixelGetColor() x7 method. If I simply made the switch to PixelChecksum() I wouldn't be sure if I saw a difference or if I imagined it.

Edited by darkthorn

Share this post


Link to post
Share on other sites
ABANDONEDACC

It probably matters that I am doing this check very rapidly so does anyone know how to write a small benchmark program that tries both methods repeatedly and sees which is faster?

Share this post


Link to post
Share on other sites
MadBoy

It probably matters that I am doing this check very rapidly so does anyone know how to write a small benchmark program that tries both methods repeatedly and sees which is faster?

From help file:

$begin = TimerInit()
sleep(3000)
$dif = TimerDiff($begin)
MsgBox(0,"Time Difference",$dif)

So just replace sleep(3000) with your functions and check it out.

Edited by MadBoy

My little company: Evotec (PL version: Evotec)

Share this post


Link to post
Share on other sites
ABANDONEDACC

Wow, both functions execute about 4000x faster than I expected them to be (not an exaggeration, I actually thought these functions could only get at most 30 runs each per second due to speed issues with the scripting language), but they were A LOT faster than I expected them to be.

I used a 2x4 pixel grid to test with, as such:

....

....

On my computer, 10000 (TEN THOUSAND!) runs of PixelGetColor() x8 (to cover the 2x4 grid) took less time than 10000 runs of PixelChecksum() to cover the same 2x4 area on the screen.

The results were as follows:

PixelGetColor():

255.132984778792 milliseconds

PixelChecksum():

376.265139843192 milliseconds

So as I suspected, despite PixelChecksum() being a compiled function that does all the work natively, it is still slower than manual checking, since it also has to calculate a checksum for the grid.

I also learnt that it isn't taxing for the computer to run repeated PixelGetColor()'s every second and that I am way within safe limits. This example managed to do 40000 PixelGetColor() calls per second if left without speed restriction which is WAY less than what I am using currently (about 15 per second).

AutoIt amazes me. Here is the benchmark program:

Global $coords[2], $hColor = 0xFCAB9C, $iChecksum = 458954407 ; neither pixel color is correct, since I want them to be on even testing grounds
$coords[0] = 178
$coords[1] = 199

$begin1 = TimerInit()
For $i = 1 to 10000 Step 1
    If Hex( PixelGetColor( $coords[0], $coords[1] ), 6 ) == Hex($hColor,6) AND _ ; spot-on (base, pixel 1)
            Hex( PixelGetColor( $coords[0]+1, $coords[1] ), 6 ) == Hex($hColor,6) AND _ ; 1 pixel to the right
            Hex( PixelGetColor( $coords[0]+2, $coords[1] ), 6 ) == Hex($hColor,6) AND _ ; 2 pixels to the right
            Hex( PixelGetColor( $coords[0]+3, $coords[1] ), 6 ) == Hex($hColor,6) AND _ ; 3 pixels to the right
            Hex( PixelGetColor( $coords[0], $coords[1]+1 ), 6 ) == Hex($hColor,6) AND _ ; 1 pixel down
            Hex( PixelGetColor( $coords[0]+1, $coords[1]+1 ), 6 ) == Hex($hColor,6) AND _ ; 1 pixel down and 1 to the right
            Hex( PixelGetColor( $coords[0]+2, $coords[1]+1 ), 6 ) == Hex($hColor,6) AND _ ; 1 pixel down and 2 to the right
            Hex( PixelGetColor( $coords[0]+3, $coords[1]+1 ), 6 ) == Hex($hColor,6) Then ; 1 pixel down and 3 to the right
        ; DO NOTHING
    EndIf
Next 
$dif1 = TimerDiff($begin1)

$begin2 = TimerInit()
For $i = 1 to 10000 Step 1
    If PixelChecksum($coords[0], $coords[1], $coords[0]+3, $coords[1]+1) == $iChecksum Then
        ; DO NOTHING
    EndIf
Next 
$dif2 = TimerDiff($begin2)

MsgBox(0,"Time Difference","PixelGetColor():" & @CRLF & $dif1 & " milliseconds" & @CRLF & @CRLF & "PixelChecksum():" & @CRLF & $dif2 & " milliseconds")

You have to run the test a few times since AutoIt sometimes stalls right after it begins parsing a script, and that will make the first timer go off and then just wait around before actually doing the testing. You can easily tell when it has happened since the first value can go as high as 1.5 seconds before the script comes to life again. No big deal, after a few test runs you will recognize their normal values.

Share this post


Link to post
Share on other sites
ABANDONEDACC

Unfortunately, this alerted me to something else.

It's not my PixelGetColor() calls that are slowing down the program, it's the PixelSearch(). The problem is how PixelSearch() only looks for a specific pixel color and can therefore match incorrect places on the screen, which then forces me to use PixelGetColor() to look at surrounding pixels and manually validate that we have matched the right area and not just hit a single pixel that happens to have the same color as the area we are looking for.

I have employed every trick in the book... I use a large step size (6, it scans every 6th pixel for the matching color!) - AND - I've restricted the area that it scans to a small 400x300 section of the screen. I can't think of anything else to improve the PixelSearch() speed!

Is it possible to improve the speed of PixelSearch even more? What the program does is to find a large, single-colored area (of a specific color) on the screen, and I can't come up with any better way to do it than to first PixelSearch() for the color of the area, and then look at 8 surrounding pixels to see if they are the same color as well, which would validate that we really hit a single-colored area.

Perhaps some of you have managed to improve the situation with PixelSearch? Perhaps through a DLL to do the job instead of PixelSearch()?

I'm still hopeful that there is a way. :)

Share this post


Link to post
Share on other sites
Fossil Rock

What I found interesting is how slow a For...Next loop is ... around 8.5 times slower.

Edit: I was going to try and make the area larger to compare the speeds, but realized I would have to create an enormous amount of code to get a region large enough for testing.

;;;; PixelCheckSum Speed Test

Global $coords[2], $hColor = 0xFCAB9C, $iChecksum = 458954407 ; neither pixel color is correct, since I want them to be on even testing grounds
$coords[0] = 178
$coords[1] = 199
$pcs = ""

$begin0 = TimerInit()
For $i = 1 to 10000 Step 1
    For $a = 0 To 1
        For $b = 0 To 3
            If Hex( PixelGetColor( $coords[0]+$a, $coords[1]+$b ) == Hex($hColor, 6)) Then
            ; DO NOTHING
        EndIf
        Next
    Next
Next
$dif0 = TimerDiff($begin0)

$begin1 = TimerInit()
For $i = 1 to 10000 Step 1
    If Hex( PixelGetColor( $coords[0], $coords[1] ), 6 ) == Hex($hColor,6) AND _ ; spot-on (base, pixel 1)
            Hex( PixelGetColor( $coords[0]+1, $coords[1] ), 6 ) == Hex($hColor,6) AND _ ; 1 pixel to the right
            Hex( PixelGetColor( $coords[0]+2, $coords[1] ), 6 ) == Hex($hColor,6) AND _ ; 2 pixels to the right
            Hex( PixelGetColor( $coords[0]+3, $coords[1] ), 6 ) == Hex($hColor,6) AND _ ; 3 pixels to the right
            Hex( PixelGetColor( $coords[0], $coords[1]+1 ), 6 ) == Hex($hColor,6) AND _ ; 1 pixel down
            Hex( PixelGetColor( $coords[0]+1, $coords[1]+1 ), 6 ) == Hex($hColor,6) AND _ ; 1 pixel down and 1 to the right
            Hex( PixelGetColor( $coords[0]+2, $coords[1]+1 ), 6 ) == Hex($hColor,6) AND _ ; 1 pixel down and 2 to the right
            Hex( PixelGetColor( $coords[0]+3, $coords[1]+1 ), 6 ) == Hex($hColor,6) Then ; 1 pixel down and 3 to the right
        ; DO NOTHING
    EndIf
Next
$dif1 = TimerDiff($begin1)

$begin2 = TimerInit()
For $i = 1 to 10000 Step 1
    If PixelChecksum($coords[0], $coords[1], $coords[0]+3, $coords[1]+1) == $iChecksum Then
        ; DO NOTHING
    EndIf
Next
$dif2 = TimerDiff($begin2)

MsgBox(0,"Time Difference","PixelGetColor() - For Next Loop:" & @CRLF & $dif0 & " milliseconds" & @CRLF & _ 
@CRLF & "PixelGetColor():" & @CRLF & $dif1 & " milliseconds" & @CRLF & @CRLF & "PixelChecksum():" & @CRLF & $dif2 & " milliseconds")
Edited by Fossil Rock

Agreement is not necessary - thinking for one's self is!

My-Colors.jpg

cuniform2.gif

Share this post


Link to post
Share on other sites
ABANDONEDACC

What I found interesting is how slow a For...Next loop is ... around 8.5 times slower.

Edit: I was going to try and make the area larger to compare the speeds, but realized I would have to create an enormous amount of code to get a region large enough for testing.

;;;; PixelCheckSum Speed Test

Global $coords[2], $hColor = 0xFCAB9C, $iChecksum = 458954407 ; neither pixel color is correct, since I want them to be on even testing grounds
$coords[0] = 178
$coords[1] = 199
$pcs = ""

$begin0 = TimerInit()
For $i = 1 to 10000 Step 1
    For $a = 0 To 1
        For $b = 0 To 3
            If Hex( PixelGetColor( $coords[0]+$a, $coords[1]+$b ) == Hex($hColor, 6)) Then
            ; DO NOTHING
        EndIf
        Next
    Next
Next
$dif0 = TimerDiff($begin0)

$begin1 = TimerInit()
For $i = 1 to 10000 Step 1
    If Hex( PixelGetColor( $coords[0], $coords[1] ), 6 ) == Hex($hColor,6) AND _ ; spot-on (base, pixel 1)
            Hex( PixelGetColor( $coords[0]+1, $coords[1] ), 6 ) == Hex($hColor,6) AND _ ; 1 pixel to the right
            Hex( PixelGetColor( $coords[0]+2, $coords[1] ), 6 ) == Hex($hColor,6) AND _ ; 2 pixels to the right
            Hex( PixelGetColor( $coords[0]+3, $coords[1] ), 6 ) == Hex($hColor,6) AND _ ; 3 pixels to the right
            Hex( PixelGetColor( $coords[0], $coords[1]+1 ), 6 ) == Hex($hColor,6) AND _ ; 1 pixel down
            Hex( PixelGetColor( $coords[0]+1, $coords[1]+1 ), 6 ) == Hex($hColor,6) AND _ ; 1 pixel down and 1 to the right
            Hex( PixelGetColor( $coords[0]+2, $coords[1]+1 ), 6 ) == Hex($hColor,6) AND _ ; 1 pixel down and 2 to the right
            Hex( PixelGetColor( $coords[0]+3, $coords[1]+1 ), 6 ) == Hex($hColor,6) Then ; 1 pixel down and 3 to the right
        ; DO NOTHING
    EndIf
Next
$dif1 = TimerDiff($begin1)

$begin2 = TimerInit()
For $i = 1 to 10000 Step 1
    If PixelChecksum($coords[0], $coords[1], $coords[0]+3, $coords[1]+1) == $iChecksum Then
        ; DO NOTHING
    EndIf
Next
$dif2 = TimerDiff($begin2)

MsgBox(0,"Time Difference","PixelGetColor() - For Next Loop:" & @CRLF & $dif0 & " milliseconds" & @CRLF & _ 
@CRLF & "PixelGetColor():" & @CRLF & $dif1 & " milliseconds" & @CRLF & @CRLF & "PixelChecksum():" & @CRLF & $dif2 & " milliseconds")
I think that may be the reason why Jon is asking if we want a simple function:

Loop 10000

; Do Something

EndLoop

There is a thread about it somewhere, he said this fixed integer way was for speed since the current loops evaluate at every turn, and that we would be able to use an integer variable for the Loop value, but that it would be static after the first run and no longer evaluated. Sounds pretty good for benchmarks at least.

Anyone know how to improve PixelSearch() speed?

Share this post


Link to post
Share on other sites
SmOke_N

I Know that PixelGetColor used to use the GetPixel API as you may have stated above, which in itself is horribly slow. But I'm not sure if they have changed it to the method type they are using for PixelSearch and PixelGetColor, which is not the GetPixel method.

But comparing speeds of a region versus what PixelCheckSum does, isn't really a fair test.

What you would have to do to make it fair, is after receiving all the values is separate each of the values received by their RGB then use the adler method to check the sums of each of them.

If you're going to run a true test, test it specifically for what the functions do themselves... there's a lot more to PixelCheckSum then you might think.


Common sense plays a role in the basics of understanding AutoIt... If you're lacking in that, do us all a favor, and step away from the computer.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this  

×