编解码技术- 序列化工具Serializable
1、编解码名词含义:将java对象编码为字节数组或者bytebuffer对象,当远程服务读取到byterbuffer对象或者字节数组是,需要将其编解码为发送是的java对象。
2、我用过的序列化方式以下三种:1)对象实现Serializable接口 2)使用google的json或者阿里巴巴的FastJSon 3)使用google的protobuf 4)Facebook的Thrift 主要用于静态数据交换,已知的数据结构,负责搭建大型数据交换接存储的工具 5)Jboss的Marshalling 是一个java对象的序列化api包
本次主要查看第一种serializable 序列化后的编码性能,码流大小,api工具是否方便
1)pojo类
public class UserInfo implements Serializable { private static final long serialVersionUid=1L; private String userName; private int userID; public UserInfo buildUserName(String username) { this.userName = username; return this; } public UserInfo buildUserID(int userID) { this.userID = userID; return this; } public final String getUserName() { return userName; } public final void setUserName(String userName) { this.userName = userName; } public final int getUserID() { return userID; } public final void setUserID(int userID) { this.userID = userID; } public byte[] codeC(){ ByteBuffer buffer = ByteBuffer.allocate(1024); byte[] bytes = this.userName.getBytes(); buffer.putInt(bytes.length); buffer.put(bytes); buffer.putInt(this.userID); buffer.flip(); bytes=null; byte[] result = new byte[buffer.remaining()]; buffer.get(result); return result; }
usrinfo对象是一个普通pojo类,它实现了serializable接口,,通过jdk默认的序列化机制进行序列化和反序列化。
codec方法使用的是bytebuffer通用的二进制编码技术对userinfo对象进行编码,编码结果仍然是byte数组,
2)测试类
public class TestUserInfo { public static void main(String[] args) throws IOException { UserInfo userInfo = new UserInfo(); userInfo.buildUserID(100).buildUserName("welcome to netty"); ByteArrayOutputStream bos = new ByteArrayOutputStream(); ObjectOutputStream os = new ObjectOutputStream(bos); os.writeObject(userInfo); os.flush(); os.close(); byte[] bytes = bos.toByteArray(); System.out.println("the jdk serializable length is:"+bytes.length); bos.close(); System.out.println("====================================="); System.out.println("the byte array serializable length:"+userInfo.codeC().length); } }
3)运行结果
从上可以看出,二进制明细优于jdk序列化。因为编解码后的字节数组越大,存储的时候约占空间,硬件成本就越高,网络传送就越高,
4)编码100万次,新增一个重载方法
/** * 修改后的 * @return */ public byte[] codeC(ByteBuffer buffer){ buffer.clear(); byte[] bytes = this.userName.getBytes(); buffer.putInt(bytes.length); buffer.put(bytes); buffer.putInt(this.userID); buffer.flip(); bytes=null; byte[] result = new byte[buffer.remaining()]; buffer.get(result); return result; }
public class PerformTestUserInfo { public static void main(String[] args) throws IOException { UserInfo userInfo = new UserInfo(); userInfo.buildUserID(100).buildUserName("weclome to netty"); int loop=1000000; ByteArrayOutputStream bos=null; ObjectOutputStream os=null; long startTime = System.currentTimeMillis(); for(int i=0;i<loop;i++){ bos=new ByteArrayOutputStream(); os=new ObjectOutputStream(bos); os.writeObject(userInfo); os.flush(); os.close(); byte[] bytes = bos.toByteArray(); bos.close(); } long endTime = System.currentTimeMillis(); System.out.println("the jdk serializable cost time is:"+(endTime-startTime)+"ms"); System.out.println("====================================="); ByteBuffer byteBuffer = ByteBuffer.allocate(1024); startTime = System.currentTimeMillis(); for(int i=0;i<loop;i++){ byte[] bytes = userInfo.codeC(byteBuffer); } endTime = System.currentTimeMillis(); System.out.println("the byte array serializable cost time is:"+(endTime-startTime)+"ms"); } }
,统计下测试时间:
以上结果证明:无论序列化后的码流大小还是序列化的性能,jdk默认的序列化都很差,