为什么 i=i+1 比 i++ 快? [英] Why is i=i+1 faster than i++?

查看:36
本文介绍了为什么 i=i+1 比 i++ 快?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在 Flash 中测试此代码:

var i:int = 0;for (var j:int = 0; j <5000000; j++){i=i+1;}//使用大约 300 毫秒.我 = 0;for (var j:int = 0; j <5000000; j++){我++;}//使用大约400ms我 = 0;for (var j:int = 0; j <5000000; j++){++i;}//也使用大约 400 毫秒

为什么 i=i+1 在 ActionScript 3 中更快,而在其他中则较慢?

对不起,我弄错了.上面的代码使用了相同的时间.但是如果放到函数里,结果就不一样了.

var i:int;var j:int;var startTime:Number;函数 func1():void{i = i + 1;}函数 func2():void{我++;}startTime = getTimer();我 = 0;对于 (j = 0; j <10000000; j++){func1();}trace(getTimer() - startTime);//5次:631,628,641,628,632startTime = getTimer();我 = 0;对于 (j = 0; j <10000000; j++){func2();}trace(getTimer() - startTime);//5次:800,814,791,832,777

解决方案

循环所在的位置会对性能产生很大影响.如果您的循环在函数内部,Flash 将使用本地寄存器执行计算.包含 i++ 的循环因此产生以下操作码:

000013 inclocal_i (REG_2) ;增量 i000015 inclocal_i (REG_3);增量 j000017 获取本地(REG_3);将 j 压入堆栈000018 pushint 5000000 ;将 5000000 压入堆栈000020 iflt -12 ;如果小于,则向后跳

包含 i = i + 1 的循环产生以下结果:

000013 getlocal (REG_2) ;将 i 压入堆栈000014 推字节 1 ;将 1 压入堆栈000016 添加;添加两个000017 转换_i ;强制为整数000018 设置本地(REG_2);保存我回到注册2000019 inclocal_i (REG_3)000021 getlocal (REG_3)000022 pushint 5000000000024 iflt -16

i++ 在这里比 i = i + 1 快,因为 inclocal_i 直接修改寄存器,而无需将寄存器加载到堆栈上并将其保存回来.>

当您将循环放入框架脚本中时,它的效率会大大降低.Flash 将声明的变量存储为类变量.访问这些需要更多的工作.i++ 循环结果如下:

000017 getlocal (REG_0, this) ;将其推入堆栈000018 重复;复制它000019 设置本地(REG_2);将此保存到注册 2000020 getproperty i ;获得财产我"000022 增量_i;添加一个000023 设置本地(REG_3);将结果保存到寄存器 3000024 获取本地(REG_2);从寄存器 2 得到这个000025 获取本地(REG_3);从寄存器 3 获取值000026 setproperty i ;设置属性我"000028 杀死(REG_3);杀死寄存器 2000030 杀死(REG_2);杀死寄存器 3000032 getlocal (REG_0, this) ;对 j 做同样的事情...000033 重复000034 setlocal (REG_2)000035 获取属性 j000037 increment_i000038 setlocal (REG_3)000039 getlocal (REG_2)000040 getlocal (REG_3)000041 setproperty j000043 杀死 (REG_3)000045 杀死 (REG_2)000047 getlocal (REG_0, this)000048 获取属性 j000050 pushint 5000000000052 iflt -40

i = i + 1 版本有点短:

000017 getlocal (REG_0, this) ;将其推入堆栈000018 getlocal (REG_0, this) ;将其推入堆栈000019 getproperty i ;获得财产我"000021 推字节 1 ;将 1 压入堆栈000023 添加;添加两个000024 initproperty i ;将结果保存到属性i"000026 getlocal (REG_0, this) ;增加 j...000027 重复000028 setlocal (REG_2)000029 getproperty j000031 增量_i000032 设置本地 (REG_3)000033 getlocal (REG_2)000034 getlocal (REG_3)000035 setproperty j000037 杀死 (REG_3)000039 杀死 (REG_2)000041 getlocal (REG_0, this)000042 获取属性 j000044 pushint 5000000000046 iflt -34

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

解决方案

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 

这篇关于为什么 i=i+1 比 i++ 快?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆