AS3 > 性能 > if (myBooleanField) *VS* if (myObjectField != null) *VS* if (myIntField != 0)
AS3 > performance > if (myBooleanField) *VS* if (myObjectField != null) *VS* if (myIntField != 0)
假设我有一个名为 drawGraphics
的函数,它 运行 在某些预定义的配置下非常紧张 3 秒。
在该函数中我可以调用 myDecorator.decorate()
,前提是该字段不为空。
我可以 运行 此代码使用两个选项:
if (myDecorator != null)
myDecorator.decorate();
-或-
// during init:
isUsingDecorator = myDecorator != null; // boolean field
// ...
// during 'drawGraphics'
if (isUsingDecorator)
myDecorator.decorate();
哪个更有效:将字段与 null 进行比较或询问布尔字段是否为 'true'(或将 int 字段与 0 进行比较)?
我是不是对这里的表现过于夸张了?
提前致谢
埃亚尔
很可能 解析名称比实际比较花费的时间要长得多。但这在很大程度上取决于您的代码结构、作用域的嵌套以及编译器对其进行的优化。 我怀疑这个问题对整体性能是否真的很重要。我猜你在这里进行了微优化。
无论如何,您可以通过查看生成的字节码来评估问题。去除不相关部分的代码,保留作用域的结构并反编译结果。
即假设您在空 bytecode.swf
电影的单帧中有此代码:
var test:Function = function(){};
var check:Boolean = test != null;
var action:Function = function()
{
if (test != null) {
trace(1);
}
if (check) {
trace(2);
}
};
action();
使用flex_sdk_4.6\bin\swfdump.exe
:
swfdump.exe -abc -showbytecode bytecode.swf > bytecode.txt
检查 bytecode.txt
并找到以下内容:
02 02 01 0B 0B 1C var null::no name():
maxStack:2 localCount:1 initScopeDepth:11 maxScopeDepth:11
60 03 getlex :test
20 pushnull
13 07 00 00 ifeq L0
5D 09 findpropstrict :trace
24 01 pushbyte 1
4F 09 01 callpropvoid :trace (1)
60 05 L0: getlex :check
12 07 00 00 iffalse L1
5D 09 findpropstrict :trace
24 02 pushbyte 2
4F 09 01 callpropvoid :trace (1)
47 L1: returnvoid
现在我们可以看到比较test和null需要三个指令:getlex
、pushnull
、ifeq
;并在两条指令中检查布尔结果:getlex
、iffalse
。在性能方面唯一重要的是使用 getlex
.
解析标识符
因此,要回答您的问题,您需要弄清楚在您的特定上下文中解决 myDecorator
问题真正需要多长时间。例如,如果 isUsingDecorator
是方法变量的局部变量而 myDecorator
不是,那么使用前者肯定会获得更好的性能。再一次,我怀疑这才是真正重要的。
P.S。您也可以使用下面的原始测试,但当性能差异如此之小或根本不存在时,它就非常不准确。不管怎样,它至少可以给你一个提示:这不是需要优化的地方。
import flash.utils.setInterval;
var test:Function = function(){};
var check:Boolean = test != null;
var action:Function = function()
{
var a:Date;
var s:int, i:int;
s = getTimer();
for(i = 0;i<100000;i++) {
if (test != null) {
a = new Date(); // just chewing the fat
}
}
trace("a:"+(getTimer()-s));
s = getTimer();
for(i = 0;i<100000;i++) {
if (check) {
a = new Date(); // just chewing the fat
}
}
trace("b:"+(getTimer()-s));
};
setInterval(action, 1000);
这几乎不是一个相关的问题,因为你的第二个案例是第一个案例 + 作业。出于这个原因,第二种情况简直不能再快了。
为什么还要限制为 2 个选项?直接评估实例也是完全有效的:
if(myDecorator)
{ etc ....
假设我有一个名为 drawGraphics
的函数,它 运行 在某些预定义的配置下非常紧张 3 秒。
在该函数中我可以调用 myDecorator.decorate()
,前提是该字段不为空。
我可以 运行 此代码使用两个选项:
if (myDecorator != null)
myDecorator.decorate();
-或-
// during init:
isUsingDecorator = myDecorator != null; // boolean field
// ...
// during 'drawGraphics'
if (isUsingDecorator)
myDecorator.decorate();
哪个更有效:将字段与 null 进行比较或询问布尔字段是否为 'true'(或将 int 字段与 0 进行比较)?
我是不是对这里的表现过于夸张了?
提前致谢
埃亚尔
很可能 解析名称比实际比较花费的时间要长得多。但这在很大程度上取决于您的代码结构、作用域的嵌套以及编译器对其进行的优化。 我怀疑这个问题对整体性能是否真的很重要。我猜你在这里进行了微优化。
无论如何,您可以通过查看生成的字节码来评估问题。去除不相关部分的代码,保留作用域的结构并反编译结果。
即假设您在空 bytecode.swf
电影的单帧中有此代码:
var test:Function = function(){};
var check:Boolean = test != null;
var action:Function = function()
{
if (test != null) {
trace(1);
}
if (check) {
trace(2);
}
};
action();
使用flex_sdk_4.6\bin\swfdump.exe
:
swfdump.exe -abc -showbytecode bytecode.swf > bytecode.txt
检查 bytecode.txt
并找到以下内容:
02 02 01 0B 0B 1C var null::no name():
maxStack:2 localCount:1 initScopeDepth:11 maxScopeDepth:11
60 03 getlex :test
20 pushnull
13 07 00 00 ifeq L0
5D 09 findpropstrict :trace
24 01 pushbyte 1
4F 09 01 callpropvoid :trace (1)
60 05 L0: getlex :check
12 07 00 00 iffalse L1
5D 09 findpropstrict :trace
24 02 pushbyte 2
4F 09 01 callpropvoid :trace (1)
47 L1: returnvoid
现在我们可以看到比较test和null需要三个指令:getlex
、pushnull
、ifeq
;并在两条指令中检查布尔结果:getlex
、iffalse
。在性能方面唯一重要的是使用 getlex
.
因此,要回答您的问题,您需要弄清楚在您的特定上下文中解决 myDecorator
问题真正需要多长时间。例如,如果 isUsingDecorator
是方法变量的局部变量而 myDecorator
不是,那么使用前者肯定会获得更好的性能。再一次,我怀疑这才是真正重要的。
P.S。您也可以使用下面的原始测试,但当性能差异如此之小或根本不存在时,它就非常不准确。不管怎样,它至少可以给你一个提示:这不是需要优化的地方。
import flash.utils.setInterval;
var test:Function = function(){};
var check:Boolean = test != null;
var action:Function = function()
{
var a:Date;
var s:int, i:int;
s = getTimer();
for(i = 0;i<100000;i++) {
if (test != null) {
a = new Date(); // just chewing the fat
}
}
trace("a:"+(getTimer()-s));
s = getTimer();
for(i = 0;i<100000;i++) {
if (check) {
a = new Date(); // just chewing the fat
}
}
trace("b:"+(getTimer()-s));
};
setInterval(action, 1000);
这几乎不是一个相关的问题,因为你的第二个案例是第一个案例 + 作业。出于这个原因,第二种情况简直不能再快了。
为什么还要限制为 2 个选项?直接评估实例也是完全有效的:
if(myDecorator)
{ etc ....