为什么用ByteArray序列化的对象如此小?
众所周知我们可以利用ByteArray自动序列化任何东西并且它比XML或者Json都要小和快。但是为什么会这样小呢?此文做了一些调查后揭露为什么此格式如此高效,并告诉如何在解序列化的时候减少工作量。
为方便探究,我们需要一个简单的Person类:
1 class Person
2
3 {
4
5 var first:String;
6
7 var last:String;
8
9 var mother:Person;
10
11 var father:Person;
12
13 }
当我们用Bytearray的wirteobject函数来序列化的时候,Bytearray最好的特性在于它会递归的将你自定义的对象序列化,并且不需要再次编码,以为它内在支持引用。因此你可以简单的这样做:
1 var mother:Person = new Person();
2
3 mother.first = "Susan";
4
5 mother.last = "Smith";
6
7
8
9 var father:Person = new Person();
10
11 father.first = "Bruce";
12
13 mother.last = "Smith";
14
15
16
17 var child:Person = new Person();
18
19 child.first = "Jimmy";
20
21 child.last = "Smith";
22
23 child.mother = mother;
24
25 child.father = father;
26
27
28
29 bytes.writeObject(new <Person>[child,father,mother]);
不需要担心子Person对象会保存父类对象的拷贝。至少这是AMF说明书定义的ByteArray.writeObject跟readObject的文件格式。
我们如何在实际中测试观察呢?我们进行一个小测试,测试里我们让Person的名字很长,然后用Bytearray序列化几次Person对象。
1 var reallyLongString:String = "";
2
3 for (var i:int = 0; i < 1024; ++i)
4
5 {
6
7 reallyLongString += i;
8
9 }
10
11
12
13 var person:Person = new Person();
14
15 person.first = reallyLongString;
16
17 person.last = reallyLongString;
18
19 person.mother = person;
20
21
22
23 var bytes:ByteArray = new ByteArray();
24
25 for (var i:int = 0; i < 1000000; ++i)
26
27 {
28
29 bytes.writeObject(person);
30
31 }
32
33
34
35 trace(bytes.length);
如果AMF不支持指针或引用,那Bytearray将完全拷贝reallyLongString,而这将造成Bytearray很大。而我们只得到3百万个字节。如果有1百万个Person对象,它们都有两个很大的字符串,AMF就可以很安全的做此项工作而不是拷贝对象。
最后一次测试我们将看下AMF的引用概念到底如何实现的。Bytearray.readObject会在AS3对象里回读的时候保留它们吗?下面这个最终的测试读取前两个Person对象,然后查看每个的父类是否指向相同的Person。
1 bytes.position = 0;
2
3 var obj1:Object = bytes.readObject();
4
5 var obj2:Object = bytes.readObject();
6
7 trace(obj1.mother == obj2.mother);
当然,打印的结果为true,这代表序列化跟解序列化过程中保留的是相同的引用。这也是AFM格式的Bytearray.readObject 和Bytearray.writeObject比XML和Json好的原因。它不仅快,小而且保存类型和引用。AMF绝对是你需要序列化东西的时候选择的。