olety / cjass

Preserving cjass code from code.google.com/p/cjass
0 stars 0 forks source link

In optimizer, can you also optimizer var names at some point please like vex's? : ) #15

Open GoogleCodeExporter opened 9 years ago

GoogleCodeExporter commented 9 years ago
This is so that it is way easier to bench. From here, a person can use vex's 
optimizer to optimizer rest of map (widgetize etc) and avoid the bug in vex's 
(how it can't handle declared AI natives).

Tx ^^

This would be ofc after you fix the current bugs = ).

Original issue reported on code.google.com by mrasolo...@gmail.com on 11 Aug 2011 at 8:29

GoogleCodeExporter commented 9 years ago
I do not want to copy VX optimizator functional theoretically.

And why? Obfuscation?

> This would be ofc after you fix the current bugs = )
Agree. We return to this issue later.

Original comment by adi...@gmail.com on 12 Aug 2011 at 4:43

GoogleCodeExporter commented 9 years ago
Oh, the reason is for optimization.

Variables/Functions/Etc with smaller names run faster. Reading/Setting a var 
named xxxxxxxxxxxxxx is much slower than reading/setting a var named x.

Original comment by mrasolo...@gmail.com on 12 Aug 2011 at 4:57

GoogleCodeExporter commented 9 years ago
> Reading/Setting a var named xxxxxxxxxxxxxx is much slower than 
reading/setting a var named x.

What?! It's "delirium"!

Ok, I know one russian hacker. Remember 1.23 version and expolit with code 
executing? This is his handiwork. And he give to me some tool - wc3 jass code 
disassembler. So, when map selected in game menu all code parsed into jass 
pseudocode. It is disassembled listing:

{{{
086F87F0 BJDebugMsg+0000 00 01 06 08  000009c0    CREATE_LOCAL_FROM_STACK msg 
[1] {string (6)}
086F87F8 BJDebugMsg+0008 00 00 04 05  0000005c    CREATE_LOCAL i {integer (4)}
086F8800 BJDebugMsg+0010 00 04 ba 0c  00000000    MOV_VAL_REG 0 => #ba {integer 
(4)}
086F8808 BJDebugMsg+0018 00 00 ba 11  0000005c    MOV_REG_VAR #ba => i
086F8810 BJDebugMsg+0020 00 00 00 28  00000001    STUB_LOOP main
086F8818 BJDebugMsg+0028 00 04 bb 0e  0000005c    MOV_VAR_REG i => #bb {integer 
(4)}
086F8820 BJDebugMsg+0030 00 00 bb 13  00000000    PUSH #bb
086F8828 BJDebugMsg+0038 00 00 00 15  00000530    CALL_NATIVE Player
086F8830 BJDebugMsg+0040 00 00 00 13  00000000    PUSH #00
086F8838 BJDebugMsg+0048 00 04 bc 0c  00000000    MOV_VAL_REG 0 => #bc {integer 
(4)}
086F8840 BJDebugMsg+0050 00 00 bc 17  00000000    #bc = (float)#bc
086F8848 BJDebugMsg+0058 00 00 bc 13  00000000    PUSH #bc
086F8850 BJDebugMsg+0060 00 04 bd 0c  00000000    MOV_VAL_REG 0 => #bd {integer 
(4)}
086F8858 BJDebugMsg+0068 00 00 bd 17  00000000    #bd = (float)#bd
086F8860 BJDebugMsg+0070 00 00 bd 13  00000000    PUSH #bd
086F8868 BJDebugMsg+0078 00 04 be 0c  0000003c    MOV_VAL_REG 60 => #be 
{integer (4)}
086F8870 BJDebugMsg+0080 00 00 be 17  00000000    #be = (float)#be
086F8878 BJDebugMsg+0088 00 00 be 13  00000000    PUSH #be
086F8880 BJDebugMsg+0090 00 06 bf 0e  000009c0    MOV_VAR_REG msg => #bf 
{string (6)}
086F8888 BJDebugMsg+0098 00 00 bf 13  00000000    PUSH #bf
086F8890 BJDebugMsg+00A0 00 00 00 15  000005fe    CALL_NATIVE 
DisplayTimedTextToPlayer
086F8898 BJDebugMsg+00A8 00 04 c0 0e  0000005c    MOV_VAR_REG i => #c0 {integer 
(4)}
086F88A0 BJDebugMsg+00B0 00 00 c0 13  00000000    PUSH #c0
086F88A8 BJDebugMsg+00B8 00 04 c1 0c  00000001    MOV_VAL_REG 1 => #c1 {integer 
(4)}
086F88B0 BJDebugMsg+00C0 00 00 c2 14  00000000    POP #c2
086F88B8 BJDebugMsg+00C8 c1 c2 c2 20  00000000    #c2 = #c2 + #c1
086F88C0 BJDebugMsg+00D0 00 00 c2 11  0000005c    MOV_REG_VAR #c2 => i
086F88C8 BJDebugMsg+00D8 00 04 c3 0e  0000005c    MOV_VAR_REG i => #c3 {integer 
(4)}
086F88D0 BJDebugMsg+00E0 00 00 c3 13  00000000    PUSH #c3
086F88D8 BJDebugMsg+00E8 00 04 c4 0e  0000080a    MOV_VAR_REG bj_MAX_PLAYERS => 
#c4 {integer (4)}
086F88E0 BJDebugMsg+00F0 00 00 c5 14  00000000    POP #c5
086F88E8 BJDebugMsg+00F8 c4 c5 c5 1a  00000000    #c5 = (#c5 == #c4)
086F88F0 BJDebugMsg+0100 00 00 c5 29  00000002    IF (#c5) THEN JUMP 
BJDebugMsg+0x0118
086F88F8 BJDebugMsg+0108 00 00 00 2b  00000001    JUMP BJDebugMsg+0x0028
086F8900 BJDebugMsg+0110 00 00 00 28  00000002    STUB_LOOP event
086F8908 BJDebugMsg+0118 00 00 00 27  00000000    RETURN
086F8910 BJDebugMsg+0120 00 00 00 04  00000000    STUB_FUNC_END
}}}

So, as you see all jass instructions is 8 bytes opcodes. Name of variables is't 
used at all.

Original comment by adi...@gmail.com on 12 Aug 2011 at 5:13

GoogleCodeExporter commented 9 years ago
It was benched at wc3c and proven. The benchmark showed a few ms in difference.

Also, it was proven in my initial version of TimerQueue. The variable names 
were almost 3 lines long and the system lagged terribly relative to native 
timers. When the variable names were shortened to a minimal amount, the 
performance drastically increased.

It has been benched and documented and encountered ; P. The wc3 community now 
accepts the fact that longer names means slower code.

Original comment by mrasolo...@gmail.com on 12 Aug 2011 at 5:25

GoogleCodeExporter commented 9 years ago
Ok, for the bench, function calls weren't tested, only variables. It could be 
that function names don't matter but variable names do ;\.

Dr Super Good thinks that they might be doing character by character for look 
ups on variables.

Original comment by mrasolo...@gmail.com on 13 Aug 2011 at 7:17

GoogleCodeExporter commented 9 years ago
> but variable names do ;\.
086F88D8 BJDebugMsg+00E8 00 04 c4 0e  0000080a    MOV_VAR_REG bj_MAX_PLAYERS => 
#c4 {integer (4)}
It use only dword - pointer to variable.

Give me your bench map, I look it.

Length of the variable name can only affect to the speed of parsing maps code, 
and very little.

Original comment by adi...@gmail.com on 13 Aug 2011 at 7:54

GoogleCodeExporter commented 9 years ago
I can't link you the thread with the benchmark on it since wc3c is down.

When wc3c comes back up (who knows when), go to resources section and 
submissions and go to the old Timer Queue thread. Scroll down and you'll 
eventually find a reply that has benches on it.

And yes, in Timer Queue, it originally ran slower than natives timers and the 
variable names were like 3 lines long. When I made the variable names very 
short (a few characters), it's speed drastically increased and it became much 
faster than natives ;p.

Considering the only thing I changed between the two things was the variable 
names, it stands to reason that longer variable names are slower for JASS to 
process.

People complained about the short variable names in TimerQueue when I submitted 
it. I told them the above, and like you, nobody believed me. Nobody on any site 
believed me actually, and most people still don't believe it and regard it as 
bs.

The first proper benchmark of it was conducted at wc3c on the TimerQueue thread 
using RtC natives. The benchmark showed that my assertions were in fact correct 
and people stopped arguing with me about speeds based on variable name length.

If you look around thw, some people are following the practice of variable 
names that are as short as possible (1-2 characters) in order to keep their 
script running as fast as possible (I was first person to start that trend). 
This practice is now becoming a problem as scripts are becoming largely 
unreadable.

If cjass had slimmed labels down to minimal sizes, people would stop this 
practice and depend on cjass optimizer instead and we wouldn't have our current 
issues of unreadable code.

You're our only hope ; P. It looks like vex's renaming in his map optimizer 
will never be fixed, meaning that the short var name practice will likely 
continue on until someone comes up with a solution.

I didn't suggest this all willy nilly. I suggested it as a solution to a 
current and very serious problem that is current resulting in piles of 
completely unreadable code.

Here is just one example
            loop
                exitwhen not lb[n]
                loop
                    exitwhen not lb[n] or (0==rl[n] and 0==rh[n]) or 0==n
                    set y=dm[this].depthPointer
                    loop
                        exitwhen not lb[y.depthNode]
                        set y=y.depthPointer
                    endloop
                    exitwhen (y.id>=rl[n] and y.id<=rh[n])
                    set n=dm[this].skip
                endloop
                if (lb[n]) then
                    if (0!=li[n]) then
                        set l=n
                    endif
                    set n=dm[this].get
                endif
            endloop

Original comment by mrasolo...@gmail.com on 13 Aug 2011 at 9:02

GoogleCodeExporter commented 9 years ago
Oh, and another good optimizer practice is to fix all comparisons to 0 so that 
the 0 is in front

For example
if (this==0) then

should turn into
if (0==this) then

The 0 in front is faster than the 0 behind. I don't know why, it's a weird JASS 
thing. It only works with 0 as well (it might actually work with 1 too, haven't 
tested 1).

This is faster
if (0==55) then

than this
if (55==0) then

So that should be semi simple.. find all ==0 and flip it. Also, for like if 
this > 0, you can flip to 0<this.

Also, get rid of as many <= and >= as you can. >= and <= are about half the 
speed of <, >, !=, and ==.

Original comment by mrasolo...@gmail.com on 13 Aug 2011 at 9:05

GoogleCodeExporter commented 9 years ago
And dude, I'm an optimizer freak. I know all of the ins and outs of JASS ; P 
(tricks etc for speed increases).

Original comment by mrasolo...@gmail.com on 13 Aug 2011 at 9:06

GoogleCodeExporter commented 9 years ago
I guess to shorten var names via an external program wouldnt be that hard, but 
I have to agree, that it would be nice to be included in the adic optimizer.

Original comment by erwgfifo...@gmail.com on 13 Aug 2011 at 9:31

GoogleCodeExporter commented 9 years ago
> And dude, I'm an optimizer freak.
I'm too. We must have two codes - first readable to users, and second fast to 
executing.

{{{
For example
if (this==0) then

should turn into
if (0==this) then
}}}

May be) Ok, I need 22 patch to launch my secret tool;) Also we're test 
variables name processing.

Original comment by adi...@gmail.com on 13 Aug 2011 at 11:45

GoogleCodeExporter commented 9 years ago
{{{
nothing fx () {
    boolean b
    b = 0 == 55
    b = 55 == 0
}
}}}

08B9D3F8 fx+0020 00 00 00 03  00000e9f    STUB_FUNC_BEGIN fx
08B9D400 fx+0000 00 00 08 05  000005f3    CREATE_LOCAL b {boolean (8)}
// 0 == 55
08B9D408 fx+0008 00 04 ca 0c  00000000    MOV_VAL_REG 0 => #ca {integer (4)}
08B9D410 fx+0010 00 00 ca 13  00000000    PUSH #ca
08B9D418 fx+0018 00 04 cb 0c  00000037    MOV_VAL_REG 55 => #cb {integer (4)}
08B9D420 fx+0020 00 00 cc 14  00000000    POP #cc
08B9D428 fx+0028 cb cc cc 1a  00000000    #cc = (#cc == #cb)
// result to b
08B9D430 fx+0030 00 00 cc 11  000005f3    MOV_REG_VAR #cc => b
// 55 ==0
08B9D438 fx+0038 00 04 cd 0c  00000037    MOV_VAL_REG 55 => #cd {integer (4)}
08B9D440 fx+0040 00 00 cd 13  00000000    PUSH #cd
08B9D448 fx+0048 00 04 ce 0c  00000000    MOV_VAL_REG 0 => #ce {integer (4)}
08B9D450 fx+0050 00 00 cf 14  00000000    POP #cf
08B9D458 fx+0058 ce cf cf 1a  00000000    #cf = (#cf == #ce)
// resule t b
08B9D460 fx+0060 00 00 cf 11  000005f3    MOV_REG_VAR #cf => b
// retn
08B9D468 fx+0068 00 00 00 27  00000000    RETURN
08B9D470 fx+0070 00 00 00 04  00000000    STUB_FUNC_END

Any difference.

adic3x 15:06:25 Тут типы утверждают, что чем 
короче имя переменной - тем быстрее к ней 
обращение.
cr*** 15:06:36 нахуй пусть идут
cr*** 15:08:28 даешь им ИДу
cr*** 15:08:32 даешь им гейм.длл
cr*** 15:08:35 и говоришь = докажите

Original comment by adi...@gmail.com on 13 Aug 2011 at 12:28

GoogleCodeExporter commented 9 years ago
Well, I've done some benchmarks (on 1.24.4.6387) with this code:

#include "lib\\cj_types.j"

#define VAR_NAME = a
#define COUNT = 24576

int VAR_NAME

callback onInit () {

   TimerStart (CreateTimer(), 3.0, true, lambda nothing () {
       int sw = StopWatchCreate()
       float mark = StopWatchMark(sw)

       #repeat COUNT
           VAR_NAME = 0
       #endrepeat

       mark = (StopWatchMark(sw) - mark) * 1000.0
       BJDebugMsg(R2S(mark))
   })
}

and got following results:

2,09..2,14 - "a" (1)
2,50..2,55 - "aaaaa" (5)
2,96..3,01 - "aaaaaaaaaa" (10)
4,25..4,30 - "aaaaaaaaaaaaaaa" (15)

Also, I've tried to test 20 char length variable name, but jasshelper failed at 
compilation.

Original comment by shadow.d...@gmail.com on 13 Aug 2011 at 12:49

GoogleCodeExporter commented 9 years ago
Can't be ... Blizz never cease to amaze me!) Ok, issue accapted.

Original comment by adi...@gmail.com on 13 Aug 2011 at 1:03

GoogleCodeExporter commented 9 years ago

Original comment by adi...@gmail.com on 24 Aug 2011 at 6:18