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

Helpful script writing tricks and HowTo's
User avatar
WAZAAAAA
Posts: 88
Joined: 13 Jan 2015, 19:48

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

23 Jun 2015, 19:23

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.
YOU'RE NOT ALEXANDER
lexikos
Posts: 9494
Joined: 30 Sep 2013, 04:07
Contact:

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

23 Jun 2015, 19:51

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.
User avatar
Joe Glines
Posts: 770
Joined: 30 Sep 2013, 20:49
Location: Dallas
Contact:

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

23 Jun 2015, 20:43

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 )
Sign-up for the 🅰️HK Newsletter

ImageImageImageImage:clap:
AHK Tutorials:Web Scraping | | Webservice APIs | AHK and Excel | Chrome | RegEx | Functions
Training: AHK Webinars Courses on AutoHotkey :ugeek:
YouTube

:thumbup: Quick Access Popup, the powerful Windows folders, apps and documents launcher!
User avatar
WAZAAAAA
Posts: 88
Joined: 13 Jan 2015, 19:48

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

24 Jun 2015, 09:41

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
YOU'RE NOT ALEXANDER
Sam_
Posts: 146
Joined: 20 Mar 2014, 20:24

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

24 Jun 2015, 10:50

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%
    ...
}
User avatar
WAZAAAAA
Posts: 88
Joined: 13 Jan 2015, 19:48

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

24 Jun 2015, 12:09

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
YOU'RE NOT ALEXANDER
User avatar
KuroiLight
Posts: 327
Joined: 12 Apr 2015, 20:24
Contact:

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

24 Jun 2015, 23:31

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:
Windows 10, Ryzen 1600, 16GB G.Skill DDR4, 8GB RX 480 | [MyScripts][MySublimeSettings] [Unlicense][MIT License]
01/24/18
[/color]
User avatar
jNizM
Posts: 3183
Joined: 30 Sep 2013, 01:33
Contact:

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

26 Jun 2015, 09:02

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. ;)
Last edited by jNizM on 06 Jul 2015, 01:46, edited 1 time in total.
[AHK] v2.0.5 | [WIN] 11 Pro (Version 22H2) | [GitHub] Profile
User avatar
WAZAAAAA
Posts: 88
Joined: 13 Jan 2015, 19:48

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

29 Jun 2015, 12:05

Posts by Sam_ and jNizM added to the top
YOU'RE NOT ALEXANDER
User avatar
KuroiLight
Posts: 327
Joined: 12 Apr 2015, 20:24
Contact:

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

05 Jul 2015, 00:45

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
Windows 10, Ryzen 1600, 16GB G.Skill DDR4, 8GB RX 480 | [MyScripts][MySublimeSettings] [Unlicense][MIT License]
01/24/18
[/color]
User avatar
dd900
Posts: 121
Joined: 27 Oct 2013, 16:03

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

08 Jul 2015, 10:06

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.
User avatar
jNizM
Posts: 3183
Joined: 30 Sep 2013, 01:33
Contact:

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

09 Jul 2015, 00:59

@dd900
Thats what I posted here => Speed Test (Benchmark): Define Variables
[AHK] v2.0.5 | [WIN] 11 Pro (Version 22H2) | [GitHub] Profile
RHCP
Posts: 202
Joined: 30 Sep 2013, 10:59

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

09 Jul 2015, 21:14

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.....
User avatar
jNizM
Posts: 3183
Joined: 30 Sep 2013, 01:33
Contact:

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

10 Jul 2015, 00:39

@RHCP
Can you show me your testscript?
[AHK] v2.0.5 | [WIN] 11 Pro (Version 22H2) | [GitHub] Profile
User avatar
WAZAAAAA
Posts: 88
Joined: 13 Jan 2015, 19:48

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

09 Sep 2015, 17:03

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
YOU'RE NOT ALEXANDER
dsewq1LYJ
Posts: 116
Joined: 26 Aug 2014, 23:21

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

16 Sep 2015, 04:01

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
User avatar
WAZAAAAA
Posts: 88
Joined: 13 Jan 2015, 19:48

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

17 Sep 2015, 21:19

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.
YOU'RE NOT ALEXANDER
dsewq1LYJ
Posts: 116
Joined: 26 Aug 2014, 23:21

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

22 Sep 2015, 04:06

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
;....
ozzii
Posts: 481
Joined: 30 Oct 2013, 06:04

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

23 Sep 2015, 01:59

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()
dsewq1LYJ
Posts: 116
Joined: 26 Aug 2014, 23:21

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

24 Sep 2015, 08:10

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 !?

Return to “Tutorials (v1)”

Who is online

Users browsing this forum: No registered users and 31 guests