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

后端 未结 5 672
野性不改
野性不改 2021-01-13 09:04

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         


        
5条回答
  •  [愿得一人]
    2021-01-13 09:44

    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 
    

提交回复
热议问题