Page 2 of 6

Re: How to optimize the speed of a script as much as possible.

Posted: 23 Jun 2015, 19:23
by WAZAAAAA
Polished the first post quite a bit according to the replies.

-Added details to each command for the skeptic and some corrections.
-SendEvent replaced by SendInput as it seems that I was somehow wrong about Event's higher speed, I benchmarked these again recently and Input was faster like the documentation suggests. Testable benchmark script included into the first post.
-Removed #MaxThreads 255, #MaxMem 4095, #MaxThreadsBuffer On, since lexikos in person clarified that they don't provide any performance benefit. My bad for blindly including them into the code.
-Removed SetTitleMatchMode 2 and SetTitleMatchMode fast because it defaults to fast already and the MatchMode setting was arbitrary.

Re: How to optimize the speed of a script as much as possible.

Posted: 23 Jun 2015, 19:51
by lexikos
WAZAAAAA, your top post still contains the SetKeyDelay error.
Sam_ wrote:
lexikos wrote:
SetKeyDelay, -1, -1, -1
The third parameter should be the word "Play" or nothing at all. -1 has no meaning.
Thanks for the catch! I updated my last post.
"Nothing at all" (for the third parameter) is the more correct option in this case. If you use the word Play it will only affect SendPlay, which defaults to -1/-1 anyway.

Re: How to optimize the speed of a script as much as possible.

Posted: 23 Jun 2015, 20:43
by Joe Glines
Thanks for y'all working on this. I put something similar to the above in my library and then I call it at the beginning of all my scripts:

#Include <default_Settings>

This allows me to keep my script small yet have a lot of preferences selected. (I just like having less in my actual file )

Re: How to optimize the speed of a script as much as possible.

Posted: 24 Jun 2015, 09:41
by WAZAAAAA
lexikos wrote:WAZAAAAA, your top post still contains the SetKeyDelay error.
Sam_ wrote:
lexikos wrote:
SetKeyDelay, -1, -1, -1
The third parameter should be the word "Play" or nothing at all. -1 has no meaning.
Thanks for the catch! I updated my last post.
"Nothing at all" (for the third parameter) is the more correct option in this case. If you use the word Play it will only affect SendPlay, which defaults to -1/-1 anyway.
corrected, thanks for pointing it out again, and thanks for EXISTING

Re: How to optimize the speed of a script as much as possible.

Posted: 24 Jun 2015, 10:50
by Sam_
Is it okay to discuss programming techniques that will help "optimize the speed of a script as much as possible" in this topic? For instance, in my experience (and according to the documentation), using VarSetCapacity() improves performance when building a string by means of gradual concatenation. From the documentation:
In addition to its uses described at DllCall, this function can also be used to enhance performance when building a string by means of gradual concatenation. This is because multiple automatic resizings can be avoided when you have some idea of what the string's final length will be.
From the example in the documentation (although not a working example...):

Code: Select all

; Optimize by ensuring MyVar has plenty of space to work with.
VarSetCapacity(MyVar, 10240000)  ; ~10 MB
Loop
{
    ...
    MyVar = %MyVar%%StringToConcatenate%
    ...
}

Re: How to optimize the speed of a script as much as possible.

Posted: 24 Jun 2015, 12:09
by WAZAAAAA
Sam_ wrote:Is it okay to discuss programming techniques that will help "optimize the speed of a script as much as possible" in this topic
Yes, as the first post mentions:
WAZAAAAA wrote:GOTTA GO FAST

Re: How to optimize the speed of a script as much as possible.

Posted: 24 Jun 2015, 23:31
by KuroiLight
Sam_ wrote:So, taking the above into account, following the recommendations in the documentation (generally a wise move), and rearranging a bit, we now have:

Code: Select all

#NoEnv
Process, Priority, , H
SetBatchLines, -1
ListLines Off
#KeyHistory 0
SendMode Input
SetTitleMatchMode 2
SetTitleMatchMode Fast
SetKeyDelay, -1, -1, Play
SetMouseDelay, -1
SetWinDelay, 0		; Changed to 0 upon recommendation of documentation
SetControlDelay, 0	; Changed to 0 upon recommendation of documentation
SetDefaultMouseSpeed, 0

; YOUR_SCRIPT_HERE
Edited SetKeyDelay. See next post.
Looks good. :thumbup:

Re: How to optimize the speed of a script as much as possible.

Posted: 26 Jun 2015, 09:02
by jNizM
Speedup DllCall's (excluded: "User32.dll", "Kernel32.dll", "ComCtl32.dll" & "Gdi32.dll")

Found in old Forum (Code by Bentschi)

Functions: LoadLibrary() & FreeLibrary()

Code: Select all

LoadLibrary(filename)
{
    static ref := {}
    if (!(ptr := p := DllCall("LoadLibrary", "str", filename, "ptr")))
        return 0
    ref[ptr,"count"] := (ref[ptr]) ? ref[ptr,"count"]+1 : 1
    p += NumGet(p+0, 0x3c, "int")+24
    o := {_ptr:ptr, __delete:func("FreeLibrary"), _ref:ref[ptr]}
    if (NumGet(p+0, (A_PtrSize=4) ? 92 : 108, "uint")<1 || (ts := NumGet(p+0, (A_PtrSize=4) ? 96 : 112, "uint")+ptr)=ptr || (te := NumGet(p+0, (A_PtrSize=4) ? 100 : 116, "uint")+ts)=ts)
        return o
    n := ptr+NumGet(ts+0, 32, "uint")
    loop % NumGet(ts+0, 24, "uint")
    {
        if (p := NumGet(n+0, (A_Index-1)*4, "uint"))
        {
            o[f := StrGet(ptr+p, "cp0")] := DllCall("GetProcAddress", "ptr", ptr, "astr", f, "ptr")
            if (Substr(f, 0)==((A_IsUnicode) ? "W" : "A"))
                o[Substr(f, 1, -1)] := o[f]
        }
    }
    return o
}

FreeLibrary(lib)
{
    if (lib._ref.count>=1)
        lib._ref.count -= 1
    if (lib._ref.count<1)
        DllCall("FreeLibrary", "ptr", lib._ptr)
}
Test Script:

Code: Select all

loops := 1000000
SetBatchLines, -1
global gdiplus := LoadLibrary("gdiplus")
VarSetCapacity(bin, 20, 0)
NumPut(1, bin, 0, "int")
DllCall(gdiplus.GdiplusStartup, "ptr*", token, "ptr", &bin, "ptr", 0)
DllCall(gdiplus.GdipCreateBitmapFromScan0, "int", 1, "int", 1, "int", 0, "int", 0x26200A, "ptr", 0, "ptr*", pBitmap)

start := A_TickCount
loop % loops
    DllCall("gdiplus\GdipBitmapGetPixel", "ptr", pBitmap, "int", 1, "int", 1, "uint*", col)
timeA := A_TickCount-start

start := A_TickCount
loop % loops
    DllCall(gdiplus.GdipBitmapGetPixel, "ptr", pBitmap, "int", 1, "int", 1, "uint*", col)
timeB := A_TickCount-start

DllCall(gdiplus.DisposeImage, "ptr", pBitmap)
DllCall(gdiplus.Cleanup, "ptr", token)
MsgBox % "Normal:`n" timeA "`n`nWith LoadLibrary:`n" timeB "`n`n" timeA/timeB
Result:

Code: Select all

---------------------------
LoadLibrary.ahk
---------------------------
Normal:
1828

With LoadLibrary:
781

2.340589
---------------------------
OK   
---------------------------
Export Table:

Code: Select all

global gdiplus := LoadLibrary("gdiplus")
for name, proc in gdiplus
{
    if (name!="_ptr" && name!="_ref" && name!="__delete")
        MsgBox % name
}

Maybe Lexikos can tell us more about it and his pro & contra. ;)

Re: How to optimize the speed of a script as much as possible.

Posted: 29 Jun 2015, 12:05
by WAZAAAAA
Posts by Sam_ and jNizM added to the top

Re: How to optimize the speed of a script as much as possible.

Posted: 05 Jul 2015, 00:45
by KuroiLight
jNizM wrote:
Spoiler
why not this?

Code: Select all

LUCall(lib, func, params*) {
    static LookupTable := {}
    
    if(!Lookuptable[lib][func]) {
        if(!LookupTable[lib])
            LookupTable[lib] := {}
        LookupTable[lib][func] := DllCall("GetProcAddress", Ptr, DllCall("LoadLibrary", Str, lib, Ptr), AStr, func, Ptr)
    }
    
    return DllCall(LookupTable[lib][func], params*)
}
example usage:

Code: Select all

LUCall("Kernel32", "Sleep", "Int", 1000)
LUCall("User32", "MessageBoxA", "UInt", 0, "AStr", "Hello World!", "AStr", "MSGBOX", "UInt", 0)
LUCall("Kernel32", "Sleep", "Int", 1000)
EDIT: according to a tickcount test this is actually slower; but it has the upside of not having to worry about whether the library is already loaded or not.
Spoiler
EDIT: well seems I made a mistake in not testing these properly before-hand: in that all other ways I've tried are still slower than the built-in dllcall, makes sense actually. (guess Ill be removing some code); I still think one form or another might help with function calls to libraries not yet loaded though, stay clear of lookuptables/dictionaries as those seem to be too slow for ahk though. (strangely enough dynamic variable version was the fastest of the 3)
Spoiler

Re: How to optimize the speed of a script as much as possible.

Posted: 08 Jul 2015, 10:06
by dd900
Documentation wrote:Performance: In v1.0.48+, the comma operator is usually faster than writing separate expressions, especially when assigning one variable to another (e.g. x:=y, a:=b). Performance continues to improve as more and more expressions are combined into a single expression; for example, it may be 35% faster to combine five or ten simple expressions into a single expression.
As suggested by the documentation I have changed

Code: Select all

a := 1
b := 2
c := 3
d := Function( param )
e := AnotherFunc( d )
return
to

Code: Select all

a := 1
, b := 2
, c := 3
, d := Function( param )
, e := AnotherFunc( d )
return
My project is rather large and doing this over my entire script has caused a noticeable increase in speed.

Re: How to optimize the speed of a script as much as possible.

Posted: 09 Jul 2015, 00:59
by jNizM
@dd900
Thats what I posted here => Speed Test (Benchmark): Define Variables

Re: How to optimize the speed of a script as much as possible.

Posted: 09 Jul 2015, 21:14
by RHCP
KuroiLight wrote: EDIT: well seems I made a mistake in not testing these properly before-hand: in that all other ways I've tried are still slower than the built-in dllcall, makes sense actually. (guess Ill be removing some code); I still think one form or another might help with function calls to libraries not yet loaded though, stay clear of lookuptables/dictionaries as those seem to be too slow for ahk though. (strangely enough dynamic variable version was the
It's not too surprising that those DLLCalls are slower. Those particular function names are automatically resolved to an address when AHK starts. Better results might be obtained when the function does not reside in User32.dll, Kernel32.dll, ComCtl32.dll, or Gdi32.dll.

However, I use the GDIP ahk library and decided to try jNizM's idea.
Test:
All the gdiPlus names were replaced with an object that stored the relevant function address.
A custom drawing function was then looped 1000 times.

Average Time Per Loop:
  • String Function Name: 14.9 ms
    Function Address: 15.5 ms
Considering the data which was being drawn, there were probably a few hundred gdiPlus calls per loop. I wasn't expecting much of a performance boost, but it actually ended up being slower.....

Re: How to optimize the speed of a script as much as possible.

Posted: 10 Jul 2015, 00:39
by jNizM
@RHCP
Can you show me your testscript?

Re: How to optimize the speed of a script as much as possible.

Posted: 09 Sep 2015, 17:03
by WAZAAAAA
Replaced the high CPU Sleep function with the "suspend" Sleep method which uses no considerable CPU and makes the code way shorter.

Here's the previous one, for historical reasons I guess:
Spoiler

Re: How to optimize the speed of a script as much as possible.

Posted: 16 Sep 2015, 04:01
by dsewq1LYJ
WAZAAAAA wrote:Replaced the high CPU Sleep function with the "suspend" Sleep method which uses no considerable CPU and makes the code way shorter.

Here's the previous one, for historical reasons I guess:
Spoiler
Higher precision but higher usage ?
And may I ask.
What's the lowest delay of the function

Re: How to optimize the speed of a script as much as possible.

Posted: 17 Sep 2015, 21:19
by WAZAAAAA
dsewq1LYJ wrote:Higher precision but higher usage ?
And may I ask.
What's the lowest delay of the function
According to my benchmarks:
Sleep default method = low CPU, low precision
Sleep suspend method = low CPU, high precision, issues with SetTimer
Sleep precise method = high CPU, higher precision
But sometimes when using the precise method, it eats so much CPU that it actually ends up slowing everything down, this has happened to a friend of mine too with a weaker PC, that's why I have replaced it with the suspend mode.
You can read more about precise sleeps at RHCP's thread: http://www.autohotkey.com/board/topic/9 ... -function/

I don't understand what do you mean with lowest delay.

Re: How to optimize the speed of a script as much as possible.

Posted: 22 Sep 2015, 04:06
by dsewq1LYJ
WAZAAAAA wrote:
dsewq1LYJ wrote:Higher precision but higher usage ?
And may I ask.
What's the lowest delay of the function
According to my benchmarks:
Sleep default method = low CPU, low precision
Sleep suspend method = low CPU, high precision, issues with SetTimer
Sleep precise method = high CPU, higher precision
But sometimes when using the precise method, it eats so much CPU that it actually ends up slowing everything down, this has happened to a friend of mine too with a weaker PC, that's why I have replaced it with the suspend mode.
You can read more about precise sleeps at RHCP's thread: http://www.autohotkey.com/board/topic/9 ... -function/

I don't understand what do you mean with lowest delay.
Hi
Waza

As you say in this thread.
http://ahkscript.org/boards/viewtopic.php?t=5920

The PixelSearch is faster than PixelGetColor.
but I got a Question about it.

The "PixelSearch" cant store the color right ?
What I mean...is follow code maybe the PixelSearch is pointless ?
<Sorry about my horrible English...I'll try my best...>
e.g.

Code: Select all

;PixelGetColor
PixelGetColor,A,1,1
PixelGetColor,B,2,2
PixelGetColor,C,3,3
if (A=0xFFFFFF)
	foo()
else if (B=0xEEEEEE)
	bar()
else if (C=0xDDDDDD)
	foo()
; Uh...How and .... what ?
PixelSearch,,,1,1,1,1,0xFFFFFF
PixelSearch,,,1,1,1,1,0xEEEEEE
PixelSearch,,,1,1,1,1,0xDDDDDD

;Gdi ? Faster
;....

Re: How to optimize the speed of a script as much as possible.

Posted: 23 Sep 2015, 01:59
by ozzii
If I understand well something like this:

Code: Select all

PixelSearch,,,1,1,1,1,0xFFFFFF
if !errorlevel
	foo()
PixelSearch,,,1,1,1,1,0xEEEEEE
if !errorlevel
	bar()
PixelSearch,,,1,1,1,1,0xDDDDDD
if !errorlevel
	foo()

Re: How to optimize the speed of a script as much as possible.

Posted: 24 Sep 2015, 08:10
by dsewq1LYJ
ozzii wrote:If I understand well something like this:

Code: Select all

PixelSearch,,,1,1,1,1,0xFFFFFF
if !errorlevel
	foo()
PixelSearch,,,1,1,1,1,0xEEEEEE
if !errorlevel
	bar()
PixelSearch,,,1,1,1,1,0xDDDDDD
if !errorlevel
	foo()

Nice..but I still confusing ... Why PixelSearch faster than PixelGetColor ???...

PixelSearch has 7 parameters ... why it faster !?