Vector数据类型

自FlashPlayer10伴随着FlashCS4发布时,AS3中就多了一种新的数据类型:Vector

这里先给不大熟悉Vector的同学们做一下简介(节选并改编自官方文档):

Vector是一种特殊的数组

  • 首先,Vector的定义和C语言中“数组”更为接近,即数组的每一个元素都有相同的数据类型。(这就意味着对Vector中元素的访问要经过类型检查)
  • 其次,Vector是一种密集数组,即每一个索引中必须包含一个值。(可以是null)
  • 最后,Vector可以随时指定为固定长度的数组。

由于这些特殊性,Vector便拥有以下几点优势:

  • 性能:使用 Vector 实例时的组元素的访问和迭代速度比使用 Array 时的要快很多。
  • 类型安全性:在严格模式下,编译器可以识别数据类型错误。(但当使用 push() 方法或 unshift() 方法向 Vector 添加值时,编译器不会检查参数的数据类型,而是在运行时检查)
  • 可靠性:相对于 Array,运行时范围检查(或定长检查)极大地提高了可靠性。

今天我们主要关注的是使用Vector数据类型来优化程序效率。

对于追求效率的RIA应用,使用Vector来提升效率是一种简单却行之有效的办法,

然而很多开发者对Vector的了解不够深入,以致未能充分发挥Vector在速度的优势。

接下来我们便来剖析一下Vector的最佳使用方法。

注:下文中所有代码的运行环境:FlashPlayer 10.1 & Mac OS X 10.6.4,所有耗时均经过多次统计平均并取整。

一、Vector数组的长度应当固定

Vector类型在AVM中的实现使用的是定长数组,虽然在AS3中其fixed属性默认为false,但仍不建议对Vector数组进行能够更改长度的操作。

请看以下测试:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
var a:Vector.< uint >= new Vector.< uint >( 1000000 );
var b:Vector.< uint >= new Vector.< uint >( 10000000 );
var t: Number =getTimer();
for ( var k: uint = 0 ;k< 9 ;k+= 1 ){
a.concat( new Vector.< uint >( 1000000 ));
}
for ( var i: uint = 0 ;i< 10000000 ;i+= 1 ){
a[i]=i;
i=a[i];
}
trace (getTimer()-t);
//
t=getTimer();
for ( var j: uint = 0 ;j< 10000000 ;j+= 1 ){
b[j]=j;
j=b[j];
}
trace (getTimer()-t);

同样是对长度为1千万的数组进行操作,前者的耗时在850ms,后者则保持在350ms。

如果将上述代码中的Vector a使用1千万次push操作来达到1千万的长度,则耗时变为1800ms。

(事实上,用上述代码对Array进行测试,有同样的耗时比率,所以无论使用哪种数组,都不建议频繁改变其长度)

至于splice操作的耗时,请参见gskinner的

Quick As A Flash: Optimization Strategies for AS3 and Flash
可以看到,Vector的splice操作要比Array慢出10倍。

二、正向/逆向遍历的速度无差异

对于Array类型,正向/逆向遍历其元素的速度大约是3:2,即逆向遍历要慢一些,比如以下代码:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
var a: Array = new Array ( 10000000 );
var b: Array = new Array ( 10000000 );
var t: Number =getTimer();
for ( var i: uint = 0 ;i< 10000000 ;i+= 1 ){
  a[i]=i;
  i=a[i];
}
trace (getTimer()-t);
//
t=getTimer();
for ( var j: uint = 9999999 ;j> 0 ;j-= 1 ){
  b[j]=j;
  j=b[j];
}
trace (getTimer()-t);

前者的耗时约是1000ms,后者则是1500ms。

而对于Vector,这种正向/逆向间的速度差异不存在。(有兴趣可以自行修改上面代码进行测试,此处作为结论给出)

三、使用Vector储存基元类型的数据时,才能充分发挥Vector的效率优势

AS3内的数据类型分为基元类型和引用类型两种,对于这两种不同类型的数据,使用Vector的效率也是不同的。(需要指出的是,这两种类型在AS3中本质都是引用类型,只不过前者是不变对象,后者是可变对象)

首先是储存基元类型数据时,Vector与Array的读写效率对比:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
var a:Vector.< uint >= new Vector.< uint >( 10000000 );
var b: Array = new Array ( 10000000 );
var t: Number =getTimer();
for ( var i: uint = 0 ;i< 10000000 ;i+= 1 ){
a[i]=i;
i=a[i];
}
trace (getTimer()-t);
//
t=getTimer();
for ( var j: uint = 0 ;j< 10000000 ;j+= 1 ){
b[j]=j;
j=b[j];
}
trace (getTimer()-t);

使用Vector耗时在400ms左右,而使用Array则是1200ms。

可见在使用基元类型时,Vector的访问速度相比Array有三倍(以上)的优势。

接下来看看储存引用类型数据时的效率对比:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
var a:Vector.< Object >= new Vector.< Object >( 1000000 );
var b: Array = new Array ( 1000000 );
var t: Number =getTimer();
for ( var i: uint = 0 ;i< 1000000 ;i+= 1 ){
a[i]={data:i, label :i};
i=a[i].data;
}
trace (getTimer()-t);
//
t=getTimer();
for ( var j: uint = 0 ;j< 1000000 ;j+= 1 ){
b[j]={data:j, label :j};
j=b[j].data;
}
trace (getTimer()-t);

二者的耗时基本一样,经过多次平均,Array耗时要比Vector多3%~8%,速度上仍然不及Vector,如非对效率要求极高,基本可以忽略。

最后对使用String类型的情况进行了单独测试,与引用类型下的表现结果一致。

四、注意索引的数据类型

很多开发者会忽略一个细节,那就是在AS3中“看起来是整数的”不一定就是整数类型。

请看以下的代码段:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
var a:Vector.< uint >= new Vector.< uint >( 10000000 );
var t: Number =getTimer();
for ( var i: uint = 0 ;i< 10000000 ;i+= 1 ){
a[i* 2 / 2 ]=i;
i=a[i* 2 / 2 ];
}
trace (getTimer()-t);
//
t=getTimer();
for ( var j: uint = 0 ;j< 10000000 ;j+= 1 ){
a[ uint (j* 2 / 2 )]=j;
j=a[ uint (j* 2 / 2 )];
}
trace (getTimer()-t);
//
t=getTimer();
for ( var k: uint = 0 ;k< 10000000 ;k+= 1 ){
a[(k* 2 / 2 )>> 0 ]=k;
k=a[(k* 2 / 2 )>> 0 ];
}
trace (getTimer()-t);
//
t=getTimer();
var n: uint ;
for ( var q: uint = 0 ;q< 10000000 ;q+= 1 ){
n=(q* 2 / 2 );
a[n]=q;
q=a[n];
}
trace (getTimer()-t);

四种方式的耗时分别是1100ms,750ms,650ms,550ms,当然,最后一种由于只计算了一次,不具可比性。(如果同样计算两次,则是750ms)

这里测试用的是乘法和除法,另经测试,+1/-1的结果也是一样。

所以这里特地提一下,如果一定要把算式直接写在索引的位置,要使用位运算将其转化为整数。

关于AS3效率优化中Vector的使用,目前我能想到的就是这四点。(不排除以后想起来了再更新)

希望能对各位有所帮助。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值