转自:http://www.360doc.com/content/06/1217/00/15643_296709.shtml
通常人们认识的序列化类实现java.io.Serializable 像这样:
import java.io.*;
public class Pojo implements Serializable {
private static final long serialVersionUID = L;
....
}
这种做法被广大程序员广泛应用,然而这种序列化的性能很低。它使用反射机制寻找序列化类的类变量和这些类变量的类型。大家都知道反射是一个非常消耗时间的处理过程。
我们如何能尽可能的在程序中减轻这种负载呢?有下面三种方法:
1.使用ObjectStreamField类
2.使用readObject / writeObject 方法
3.使用Externalizable 接口
在上面的方法中,性能最好的是使用Externalizable 接口。为了便于理解,将为不同的方法例举一个例子。
ObjectStreamField 类为序列化机制提供序列化对象的成员变量以及成员变量的类型。这样做的好是可以节约一部分时间,他不必通过反射机制去查询成员变量以及类型。关键字transient 仍然可以在这种方式下正常使用,不过在创建ObjectStreamField对象添加序列话成员变量的时候,剔除transient 标识的成员变量。
public class Pojo implements Serializable {
private static final long serialVersionUID = 1L;
private String valueA = "SomeTextA";
private int valueB = 10;
private float valueC = 100f;
private double valueD = 100.100d;
private short valueE = 10;
// Getters and setters go here.
private static final ObjectStreamField[] serialPersistFields = {
new ObjectStreamField("valueA", String.class),
new ObjectStreamField("valueB", Integer.class),
new ObjectStreamField("valueC", Float.class),
new ObjectStreamField("valueD", Double.class),
new ObjectStreamField("valueE", Short.class)
};
}
就像你所看到的,为了提升性能得必须指明你所序列化的成员变量,当然除了transient 的成员变量。
第二种方法是使用readObject / writeObject 方法。
public class Pojo implements Serializable {
private static final long serialVersionUID = 1L;
private String valueA = "SomeTextA";
private int valueB = 10;
private float valueC = 100f;
private double valueD = 100.100d;
private short valueE = 10;
// Getters and setters go here.
private void writeObject(ObjectOutputStream oos) throws IOException {
oos.writeUTF(valueA);
oos.writeInt(valueB);
oos.writeFloat(valueC);
oos.writeDouble(valueD);
oos.writeShort(valueE);
}
private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {
this.valueA = ois.readUTF();
this.valueB = ois.readInt();
this.valueC = ois.readFloat();
this.valueD= ois.readDouble();
this.valueE= ois.readShort();
}
}
这种方式包括了序列化的序列化和反序列化过程。就像上面所展示的,仍然需要声明Serializable 接口。
第三种方式使用Externalizable 接口。
public class Pojo implements Externalizable {
private static final long serialVersionUID = 1L;
private String valueA = "SomeTextA";
private int valueB = 10;
private float valueC = 100f;
private double valueD = 100.100d;
private short valueE = 10;
// Getters and setters go here.
public void writeExternal(ObjectOutput out) throws IOException {
out.writeUTF(valueA);
out.writeInt(valueB);
out.writeFloat(valueC);
out.writeDouble(valueD);
out.writeShort(valueE);
}
public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
this.valueA = in.readUTF();
this.valueB = in.readInt();
this.valueC = in.readFloat();
this.valueD= in.readDouble();
this.valueE= in.readShort();
}
}
这种方式与readObject / writeObject 方式不同的是不再需要声明Serializable 接口, readObject / writeObject 方法使用ObjectOutput/ObjectInput 接口作为参数代理输入流输出流实现类,并且serialVersionUID 仍然可以使用。
下面将测试各种序列化方法所消耗的时间:
public class Run {
private static int TIMES = 500000;
public static void main(String[] args) {
Pojo sp = new Pojo();
long start = System.currentTimeMillis();
for (int i = 0; i<TIMES;i++){
serialize(sp);
}
long duration = System.currentTimeMillis() - start;
System.out.println("Externalizable: " + duration + "ms.");
}
public static void serialize(Pojo o) {
try {
ByteArrayOutputStream bout = new ByteArrayOutputStream();
ObjectOutputStream out = new ObjectOutputStream(bout);
out.writeObject(o);
out.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
为了获得正确的测试结果,我们制定以下规则 。首先,不能测试一小部分对象,应该取较大的均值。第二,减小不必要的负载。如果测试程序快速产生大量的对象,会产生大量的垃圾收集。
在上面的代码中,我们仅序列化了50000个对象。并且没有将序列化的内容写入磁盘或者网络,因为会产生我们不希望的负载。
还有一点值得注意的是,如果有多个String类型的成员变量,他们之应该是不同的值。如果他们的值相同,那么他们引用的是同一个对象。
下面是不同jdk版本间的测试结果:
JDK 1.4.2_12
Serializable: 9766ms.
Streamfield: 9656ms.
Read/Write object: 7781ms.
Externalizable: 5875ms.
JDK 1.5.0_19
Serializable: 9016ms.
Streamfield: 8859ms.
Read/Write object: 7141ms.
Externalizable: 5610ms.
JDK 1.6.0 (B103)
Serializable: 7484ms.
Streamfield: 7312ms.
Read/Write object: 5610ms.
Externalizable: 4828ms.
有趣的是你可以发现使用Externalizable 接口提升了55%的性能。同时也可以看出jdk不同版本的垃圾收集器&Hotpot引擎性能也在提升!
分享到:
相关推荐
本Dll提供了二进制序列化和Xml序列化,序列化之后,可以对序列化数据,进行压缩。本dll提供了两种压缩方式,GZipStream和DeflateStream,在使用Webservice作为服务端的系统中,提高传输性能是比较关键的,而提高传输...
Bboss和xstream序列化反序列化性能对比1
高性能的java序列化框架,无论是生成的二进制字节数或者是序列化的速度都要优于kryo
序列化性能测试JAVA
.NET对象序列化与数据持久化.NET对象序列化与数据持久化.NET对象序列化与数据持久化.NET对象序列化与数据持久化.NET对象序列化与数据持久化.NET对象序列化与数据持久化(Q群号:152088818 本群只为有经验的.NET开发者...
和好友一起总结了C#的四种对象序列化方法(DataContractSerializer、XmlSerializer、BinaryFormatter、SoapFormatter),其中有DataContractSerializer和XmlSerializer不需要在对象上标注[Serializable],...
Wire - 用于.NET框架的高性能POCO对象的二进制序列化器
高性能java序列化框架,比kryo的性能还要强上三分之一。目前还不支持多维数组以及Map类。框架正在持续开发演进中。
Python-srsly用于Python的现代高性能序列化工具
在.Net阵营中,Json.Net是由官方推荐的高性能开源序列化/反序列化工具,其官方网站:https://www.newtonsoft.com/json; 一、将对象序列化为Json格式字符串 首先是正常的序列化操作,对于给定的类: private class ...
主要介绍了java原生序列化和Kryo序列化性能实例对比分析,涉及Java和kryo序列化和反序列化相关实例,小编觉得很不错,这里分享给大家,希望给大家一个参考。
针对大量数据网络传输设计的序列化方案,用于储存多维数组
具体请看http://blog.csdn.net/luq885/archive/2007/05/10/1603330.aspx<br>其中JSonConvert.cs中xml-2-json.xsl文件的路径是固定的,请自行修改
Java中的序列化机制有两种实现方式: 一种是实现Serializable接口 另一种是实现Externalizable接口 区别: 实现Serializable接口 1 系统自动储存必要的信息 2 Java内建支持,易于实现,只需实现该接口即可,无须任何...
本工程源码,基于rapidjson实现二次封装,使C++序列化一个类的变得代码非常小,耦合性非常低,且不损失原有序列化性能。详细使用可关联本人博客:http://blog.csdn.net/lightspear/article/details/54836656
主流java语言实现的序列化框架的测试性能测试报告.......................................................................
metajson 非侵入性,高性能的C 17轻量级JSON序列化工具,专为易于使用和性能而设计。
(1): 支持深度复杂的对象结构且易于使用。...(2): 用 $ref 表示重复和循环引用的序列化和反序列化。 (3): 目前唯一支持 ref 属性的 JSON 库。 (4): 支持几乎所有您常用的类型!并允许您自定义类型的行为。
node-msgpack, 面向NodeJS的空间高效对象序列化库 node-msgpack 是 NodeJS插件的插件,提供使用 MessagePack插件库序列化和序列化JavaScript对象的API 。 原生 JSON 对象相比,这里插件的性能并不太差,序列化数据所...
KryoCocoa 是 Kryo 高性能 Java 序列化框架的 Objective-C 移植版本,兼容 Java 版本的序列化格式。示例代码:Kryo *kryo = [Kryo new]; // ... NSOutputStream *outputStream = [NSOutputStream ...