我刚刚从同事那里听说,在验证中直接使用length属性,其性能低于为变量赋值:
for(var i:int=0;i<array.length;i++)
trace(String(i));
for(var i:int=array.length-1;i>-1;i--)
trace(String(i));
他们实际上声称,第二个循环将迭代数组“快达90%”,这是真的吗?
这个问题适用于任何语言,但我只对AS3行为感兴趣,特别是在ArrayCollections上。
答案 0 :(得分:2)
这个问题的原因比你想象的要有趣得多。
检查以下代码,它包括七个测试:
结果如下:
为什么你认为最后一个与其他人相比非常慢? 这不是因为数组每次重新计算长度,这将是愚蠢的。
阅读本文:
length属性:一个非负整数,指定数组中元素的数量。将新元素添加到阵列时,此属性自动更新。为数组元素赋值(例如,my_array [index] = value)时,如果index是数字,并且index + 1大于length属性,则length属性将更新为index + 1。
原因在于实施
//Implementation
public function get length():uint
public function set length(value:uint):void
其他六个测试使用一个普通的公共成员。 数组使用getter和setter函数来检索长度值。 如果您继续详细说明测试,您将看到功能调用需要花费宝贵的时间。 当您需要更高的性能时,有时您必须依赖内联代码。 这几乎每次都是如此。那是因为处理器必须“跳跃”。到代码中的不同区域,创建一个新的范围和一些其他原因。
Why is inlining considered faster than a function call?
如果你检查vector的长度实现,你会发现它只是一个公共成员,不像array(getter和setter)函数。 Getters和Setter更适合于可扩展性,如果您决定从类继承,它们可以使您的生活更轻松,setters也可以通过检查值来防止某些错误。没有什么比公共财产更快的了。
package regression
{
import flash.display.Sprite;
import flash.utils.getTimer;
/**
* ...
* @author Arthur Wulf White
*/
public class Check_Loop_Speed_1 extends Sprite
{
//BIG_NUMBER == 100,000,000
public function Check_Loop_Speed_1()
{
var i : int = 0, j : int = 100000000, time : int = 0;
var vector: Vector.<Boolean> = new Vector.<Boolean>(100000000, true),
vect2 : Vector.<Boolean> = new Vector.<Boolean>(100000000),
obj : Object = new TestObject(),
arr : Array = new Array();
arr.length = 100000000;
//test 1
time = getTimer();
for (i = 0; i < 100000000; i++) { }
trace(getTimer() - time);
//test 2
time = getTimer();
for (i = 0; i < j; i++) { }
trace(getTimer() - time);
//test 3
time = getTimer();
for (i = 0; i < vector.length; i++) { }
trace(getTimer() - time);
//test 4
time = getTimer();
for (i = 0; i < vect2.length; i++) { }
trace(getTimer() - time);
//test 5
time = getTimer();
for (i = 0; i < obj.val; i++) { }
trace(getTimer() - time);
//test 6
time = getTimer();
for (i = 0; i < obj.val2; i++) { }
trace(getTimer() - time);
//test 7
time = getTimer();
for (i = 0; i < arr.length; i++) { }
trace(getTimer() - time);
}
}
}
class TestObject
{
public var val : uint = 100000000;
public const val2 : uint = 100000000;
}
答案 1 :(得分:1)
你的朋友是对的,但90%不一致。
一种测试方法:
import flash.utils.getTimer;
var btn:Sprite = new Sprite();
btn.graphics.beginFill(0);
btn.graphics.drawRect(0,0,100,50);
btn.addEventListener(MouseEvent.CLICK,test);
addChild(btn);
var array:Array = new Array();
var arraySize:int = 100000;
for(var i:int=0;i < arraySize;i++){
array.push(i);
}
function test(e:Event):void {
var i:int = 0; //initialize before getTimer so all things are equal
var curTime:Number = 0;
curTimer = getTimer();
for(i=0;i<array.length;i++){
doSomething(i);
}
trace("First Took: ", (getTimer() - curTime) + "ms");
curTime = getTimer();
for(i=array.length-1;i>-1;i--){
doSomething(i);
}
trace("Second Took: ", (getTimer() - curTime) + "ms");
};
function doSomething(index:int):void {
index = index * 2; //some arbitrary function - don't trace!!!
}