Search code examples
performanceactionscript-3post-incrementpre-increment

Why is i=i+1 faster than i++?


Test this code in Flash:

var i:int = 0;
for (var j:int = 0; j < 5000000; j++)
{
    i=i+1;
}// use about 300ms.

i = 0;
for (var j:int = 0; j < 5000000; j++)
{
    i++;
}// use about 400ms

i = 0;
for (var j:int = 0; j < 5000000; j++)
{
    ++i;
}// use about 400ms too

Why is i=i+1 faster in ActionScript 3 when it's slower in others?

Sorry,I make some mistake.The code above use the same time. but if put it into function,and the result will be different.

var i:int;
var j:int;
var startTime:Number;

function func1():void
{
    i = i + 1;
}

function func2():void
{
    i++;
}

startTime = getTimer();
i = 0;
for (j = 0; j < 10000000; j++)
{
    func1();
}
trace(getTimer() - startTime);//5 times:631,628,641,628,632

startTime = getTimer();
i = 0;
for (j = 0; j < 10000000; j++)
{
    func2();
}
trace(getTimer() - startTime);//5 times:800,814,791,832,777

Solution

  • Where your loop is situated can have a large impact on performance. If your loop is inside a function, Flash will perform calculations using local registers. The loop containing i++ produces thus the following opcodes:

    000013 inclocal_i (REG_2)  ; increment i 
    000015 inclocal_i (REG_3)  ; increment j
    000017 getlocal (REG_3)    ; push j onto stack
    000018 pushint 5000000     ; push 5000000 onto stack
    000020 iflt -12            ; jump backward if less than
    

    The loop containing i = i + 1 produces the following:

    000013 getlocal (REG_2)    ; push i onto stack
    000014 pushbyte 1          ; push 1 onto stack
    000016 add                 ; add the two
    000017 convert_i           ; coerce to integer
    000018 setlocal (REG_2)    ; save i back to register 2
    000019 inclocal_i (REG_3)  
    000021 getlocal (REG_3)
    000022 pushint 5000000
    000024 iflt -16
    

    i++ is faster than i = i + 1 here since inclocal_i modifies the register directly, without having to load the register onto the stack and saving it back.

    The loop becomes be far less efficient when you put it inside a frame script. Flash will store declared variables as class variables. Accessing those requires more work. The i++ loop results in the following:

    000017 getlocal (REG_0, this)   ; push this onto stack
    000018 dup                      ; duplicate it
    000019 setlocal (REG_2)         ; save this to register 2
    000020 getproperty i            ; get property "i"
    000022 increment_i              ; add one to it
    000023 setlocal (REG_3)         ; save result to register 3
    000024 getlocal (REG_2)         ; get this from register 2
    000025 getlocal (REG_3)         ; get value from register 3
    000026 setproperty i            ; set property "i"
    000028 kill (REG_3)             ; kill register 2
    000030 kill (REG_2)             ; kill register 3
    000032 getlocal (REG_0, this)   ; do the same thing with j...
    000033 dup
    000034 setlocal (REG_2)
    000035 getproperty j
    000037 increment_i
    000038 setlocal (REG_3)
    000039 getlocal (REG_2)
    000040 getlocal (REG_3)
    000041 setproperty j
    000043 kill (REG_3)
    000045 kill (REG_2)
    000047 getlocal (REG_0, this)
    000048 getproperty j
    000050 pushint 5000000
    000052 iflt -40
    

    The i = i + 1 version is somewhat shorter:

    000017 getlocal (REG_0, this)   ; push this onto stack
    000018 getlocal (REG_0, this)   ; push this onto stack
    000019 getproperty i            ; get property "i"
    000021 pushbyte 1               ; push 1 onto stack
    000023 add                      ; add the two
    000024 initproperty i           ; save result to property "i"
    000026 getlocal (REG_0, this)   ; increment j...
    000027 dup
    000028 setlocal (REG_2)
    000029 getproperty j
    000031 increment_i
    000032 setlocal (REG_3)
    000033 getlocal (REG_2)
    000034 getlocal (REG_3)
    000035 setproperty j
    000037 kill (REG_3)
    000039 kill (REG_2)
    000041 getlocal (REG_0, this)
    000042 getproperty j
    000044 pushint 5000000
    000046 iflt -34