Faster built-in variable

Propose new features and changes
Zelio
Posts: 278
Joined: 30 Sep 2013, 00:45
Location: France

Faster built-in variable

22 Oct 2013, 16:03

Code: Select all

#NoEnv
SetBatchlines -1

msgbox start

t0 := a_tickcount
loop 1000000
	var := DllCall("GetTickCount")
msgbox % a_tickcount-t0 "*" var

t0 := a_tickcount
loop 1000000
	var := a_tickcount
msgbox % a_tickcount-t0 "*" var

msgbox finish

Code: Select all

#NoEnv
SetBatchlines -1

msgbox start

t0 := a_tickcount
loop 1000000
{
	i++
	var := i
}
msgbox % a_tickcount-t0 " ms " var "?=" i

t0 := a_tickcount
loop 1000000
{
	i++
	var := a_index
}
msgbox % a_tickcount-t0 "ms " var "?=" i

msgbox end
HotKeyIt
Posts: 2364
Joined: 29 Sep 2013, 18:35
Contact:

Re: Faster built-in variable

22 Oct 2013, 16:16

For AutoHotkey built-in variables, internal function has to be called twice because we first need to know how much memory we need to reserve for returned value (similar like some WinApi functions do it), otherwise AHK memory usage would be not efficient and always to high.

Probably built-in variables could be split into Integers and Strings and we would allocate MAX_INTEGER_SIZE for Integers like A_TickCount and use tradidtional method for Strings like A_AhkPath.

This would give us more speed and not too much memory garbage.
lexikos
Posts: 9553
Joined: 30 Sep 2013, 04:07
Contact:

Re: Faster built-in variable

22 Oct 2013, 16:29

Is there some reason that it needs to be faster?

We already allocate MAX_INTEGER_SIZE for A_TickCount.
HotKeyIt
Posts: 2364
Joined: 29 Sep 2013, 18:35
Contact:

Re: Faster built-in variable

22 Oct 2013, 16:33

lexikos wrote:Is there some reason that it needs to be faster?
We really don't need a reason for that, faster = better :D
lexikos wrote:We already allocate MAX_INTEGER_SIZE for A_TickCount.
Yes and internal function is still called twice, that is why I suggested to split them, so we don't need to call them twice.
Zelio
Posts: 278
Joined: 30 Sep 2013, 00:45
Location: France

Re: Faster built-in variable

22 Oct 2013, 16:33

For me the most important reason is about a_index, a lot of algo use intensive loop with this variable, a_tickcount too for time check, all in-built variable potentialy too. And a shortcut have to be faster by definition...
Maybe split is a good solution as HotKeyIt said ? do as you wish :)
lexikos
Posts: 9553
Joined: 30 Sep 2013, 04:07
Contact:

Re: Faster built-in variable

22 Oct 2013, 17:09

HotKeyIt wrote:We really don't need a reason for that, faster = better :D
You're not the one asking; I am. I like to spend my time on worthwhile things (even if I rarely do), not spend hours speeding up something which is already fast and will likely have little or no real-world benefit.
Zelio wrote:For me the most important reason is about a_index
A_Index and A_EventInfo are already optimized for expressions.

Actually, I already had a tentative plan to redesign the way built-in variables work for v2, primarily to allow them to return different types of values (such as objects).
Zelio
Posts: 278
Joined: 30 Sep 2013, 00:45
Location: France

Re: Faster built-in variable

22 Oct 2013, 18:19

Hmm ok, I will trust you, I investigated with iteration, Run it for to have your own conclusion, a_index << 0 is the winner and I guess it is because of a pure integer return, V2 run 10% better on my computer but i+=1 is two time slower. Also I imagine that a_index have a cache system. It will not be a waste time to work on built-in variable but it just my opinion, and as you said maybe good to have an object (equal performance ?). If someone want to try with real algo case...

Code: Select all

;SetBatchLines -1

msgbox start

t0 := a_tickcount
loop 2000000
{
	var := a_index
}
t1 := a_tickcount-t0

t0 := a_tickcount
loop 2000000
{
	var := a_index+a_index-a_index
}
t2 := a_tickcount-t0


t0 := a_tickcount
loop 2000000
{
	var := a_index << 0
}
t3 := a_tickcount-t0

t0 := a_tickcount
i := 0
loop 2000000
{
	i++
	var := i
}
t4 := a_tickcount-t0

t0 := a_tickcount
i := 0
loop 2000000
{
	i++
	var := i+i-i
}
t5 := a_tickcount-t0

t0 := a_tickcount
i := 0
loop 2000000
{
	i += 1
	var := i
}
t6 := a_tickcount-t0


msgbox % t1 " ms : a_index`n" t2 " ms : a_index+a_index-a_index`n" t3 " ms : a_index << 0`n" t4 " ms : i (i++)`n" t5 " ms : i+i-i (i++)`n" t6 " ms : i i+=1"
However we can't have a fast trick here, and V2 is 10% slower

Code: Select all

;SetBatchLines -1

msgbox start

t0 := a_tickcount
loop 200000
{
	var%a_index% := true
}
t1 := a_tickcount-t0

t0 := a_tickcount
i := 0
loop 200000
{
	i++
	var%i% := true
}
t2 := a_tickcount-t0

msgbox % t1 "`n" t2

return
For my noob eyes, when a_index is alone it doesn't return an integer
lexikos
Posts: 9553
Joined: 30 Sep 2013, 04:07
Contact:

Re: Faster built-in variable

23 Oct 2013, 05:19

v := A_Index isn't evaluated as an expression. According to my estimation, v := (A_Index) is about twice as fast as v := A_Index.
Also I imagine that a_index have a cache system.
What is there to cache? A_Index just returns g->mLoopIteration.
HotKeyIt
Posts: 2364
Joined: 29 Sep 2013, 18:35
Contact:

Re: Faster built-in variable

23 Oct 2013, 05:32

lexikos wrote:Actually, I already had a tentative plan to redesign the way built-in variables work for v2, primarily to allow them to return different types of values (such as objects).
That would be great :)
Coco
Posts: 771
Joined: 29 Sep 2013, 20:37
Contact:

Re: Faster built-in variable

23 Oct 2013, 07:16

v := A_Index isn't evaluated as an expression. According to my estimation, v := (A_Index) is about twice as fast as v := A_Index.
Hmm, interesting. True, as tested below:

Code: Select all

a := GTC()
Loop 1000000
	v  := A_Index
elapsedA := GTC()-a
b := GTC()
Loop 1000000
	v := (A_Index)
elapsedB := GTC()-b
MsgBox, % "Elapsed A: " . elapsedA . "`nElapsed B: " . elapsedB
return

GTC() {
	return DllCall("GetTickCount")/1000
}
Zelio
Posts: 278
Joined: 30 Sep 2013, 00:45
Location: France

Re: Faster built-in variable

23 Oct 2013, 10:34

Hmm, with my test that doesn't work with V2, but in V1 it is 3 times faster as you said : (sorry if I bother you with both version, and better to don't fix V1...)
V1 1061 ms a_index
V1 0327 ms (a_index)
V1 0562 ms a_index << 0
V2 0967 ms a_index
V2 0967 ms (a_index)
V2 0468 ms a_index << 0

About a cache system, sorry I don't know, it is that a_index+a_index-a_index+... have a better result than i+i-i+... so my noob conclusion was machine code prefer to always have the same address to call, or it is about tokenisation in expression who don't refere to the same block and address at each call (legitimate because variable can change many time itself in one large expression i:=(i+(i++))... ), nevermind, it is out of my knowledge...

Also with pseudo array we can't have this trick without extra line. But object[a_index] or array[a_index] are extremly fast :)
lexikos
Posts: 9553
Joined: 30 Sep 2013, 04:07
Contact:

Re: Faster built-in variable

23 Oct 2013, 16:44

Your benchmark should use SetBatchLines -1 on v1, otherwise the result will be inaccurate (it will vary considerably each time you run it).

IIRC, adding parentheses does not force it to be evaluated as an expression in v2.
Zelio
Posts: 278
Joined: 30 Sep 2013, 00:45
Location: France

Re: Faster built-in variable

23 Oct 2013, 18:43

Yes, of course, I use SetBatchLines -1, my result log is serious. Sorry if it was for Coco.
just me
Posts: 9424
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: Faster built-in variable

24 Oct 2013, 00:55

Looking at the execution time per iteration, I'd say it's fast enough for an interpreted scripting language:

Code: Select all

#NoEnv
SetBatchLines -1
SetFormat, Float, 0.8
iterations := 1000000
msgbox start

t0 := a_tickcount
loop %iterations%
    var := a_index
t1 := (a_tickcount - t0) / iterations

t0 := a_tickcount
loop %iterations%
    var := a_index+a_index-a_index
t2 := (a_tickcount - t0) / iterations

t0 := a_tickcount
loop %iterations%
    var := (a_index)
t3 := (a_tickcount - t0) / iterations

t0 := a_tickcount
i := 0
loop %iterations% {
    i++
    var := i
}
t4 := (a_tickcount - t0) / iterations

t0 := a_tickcount
i := 0
loop %iterations% {
    i++
    var := i+i-i
}
t5 := (a_tickcount - t0) / iterations

t0 := a_tickcount
i := 0
loop %iterations% {
    i += 1
    var := i
}
t6 := (a_tickcount - t0) / iterations

t0 := a_tickcount
i := 0
loop %iterations%
    var := i++
t7 := (a_tickcount - t0) / iterations

msgbox 0, %iterations% iterations
        , % t1 " ms : a_index`n" t2 " ms : a_index+a_index-a_index`n" t3 " ms : (a_index)`n" t4 " ms : i (i++)`n"
        . t5 " ms : i+i-i (i++)`n" t6 " ms : i i+=1`n" t7 " ms : i++"

Code: Select all

---------------------------
1000000 iterations
---------------------------
0.00018800 ms : a_index
0.00015600 ms : a_index+a_index-a_index
0.00009300 ms : (a_index)
0.00017200 ms : i (i++)
0.00026500 ms : i+i-i (i++)
0.00017200 ms : i i+=1
0.00010900 ms : i++
AMD A6-5400B @ 3.6 GHz - Win 7 Pro x64 - AHK 1.1.13.00 U64

Return to “Wish List”

Who is online

Users browsing this forum: TheDewd and 31 guests