`

探讨一下是什么原因导致for each语句效率减低

阅读更多
http://bbs.9ria.com/thread-74620-1-1.html

资讯类型: 原创
来源页面: http://riaoo.com/?p=2071
资讯原标题: 探讨一下是什么原因导致for each语句效率减低
资讯原作者: Y.Boy
我的评论:关于 for 、for in、for each 的效率,这是一个有趣的话题,一家一起来讨论。
对这篇文你有啥看法,跟贴说说吧!欢迎口水和板砖,哈哈。欢迎大家和我们一同分享更多资讯。



众所周知,在使用 for(var i:int=0; i<array.length; i++) 语句时,为提高效率,都把 array.length 拿在循环体外部,形如:

var length:uint = array.length;
for(var i:int = 0; i <  length; i++)
{
}


把 array.length 拿到外面去会提高效率,是因为减少了 array.length 语句的执行。而 Array 的 length 属性是一个 getter ,其实它相当于是一个函数,像:




public function get length():uint
{
// 可能包含复杂的逻辑
}


减少了这个函数的执行次数,所以提高了效率。在用flash builder编写代码时,在代码提示上看到有“=”号的属性,你就要小心了,因为它是一个可能包含复杂逻辑的 getter 属性:

其实,类似的,在 for in 或 for each 语句,也应该理所当然地存在这种情况。刚看到腾讯flash开发博客上这篇文章:《另一个很容易让人忽视并影响效率的for循环写法》。我的兴致就来了,心情再次滂湃起来。文章中说道,在使用 for each 语句时,也应该把属性放在外面,就像:

var prop:Object = obj.prop;
for each (var o:* in prop)
{
}



假如我们把 obj.prop 写进 for each 里:for each (var o:* in obj.prop) ,给人的感觉就是:每执行一次循环,obj.prop 都被访问一次(这就是降低效率的原因了)。但,实际上,它是不是这样子的呢?现在,你开始怀疑了,其实我也在怀疑,我也很好奇。我以前看到旧同事在写代码时,就喜欢把 obj.prop 放在 for each 里,我劝告他不要这么写,obj.prop 会被多次访问的。他说无所谓的,不影响效率。最终,我认为他是正确(其实他也不知道为什么不会影响效率,-_-!!)。经过我的试验,结论是:放在 for each 里的 obj.prop 不会被多次访问,它有且只有一次被访问。在随后的多次循环时,obj.prop 都不再被访问。这种情况跟第一种情况不同。
大家不妨写个 getter 属性来测试一下:

var a:A = new A();
var obj:Object = a.obj; // 在这里 a.obj 属性被访问一次
obj.a = “a”;
obj.b = “b”;
obj.c = “c”;
obj.d = “d”;
obj.e = “e”;
obj.f = “f”;for each (var o:* in a.obj) // a.obj 属性只在第一次被访问,前后总共被访问两次
{
trace(“for each”);



这是类 A :

package
{
public class A
{
private var _obj:Object;public function A()
{
_obj = {};
}public function get obj():Object
{
trace(“get obj”); // 每当被访问此属性时,都会输出”get obj”
return _obj;
}}
}



最终输出的结果是:

get obj
get obj
for each
for each
for each
for each
for each
for each
复制代码
“get obj” 只输出了两次,说明了 for each 语句里,a.obj 属性只被访问了一次。之后的循环里,都没有被访问了。我在猜想:是不是 flash player 对 a.obj 这个属性进行了缓存,效果就像把 array.length 放在循环语句外面一样!?
总结一下关于我的看法:我不知道这样分析是否正确,是否有充分的理由来说明把 a.obj 属性放在 for each 语句里不会影响效率。为了安全起见,还是统一把所有 getter 形式的属性放在最外面。

RIAMeeting如是说:
对于循环优化是子表达式消除问题(CSE),将循环引用表达式放在循环内部,据说在Java中并不会引起性能问题(即时编译优化),但AVM2的CSE实现还不是太好,所以我们需要手工优化代码。具体请参阅AVM2的核心机制说明。


标签:flash效率, for, for each, for in, getter
  • 大小: 1.4 KB
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics