天天看點

編解碼技術- 序列化工具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)運作結果

編解碼技術- 序列化工具Serializable

從上可以看出,二進制明細優于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");
    }
}      

,統計下測試時間:

編解碼技術- 序列化工具Serializable

以上結果證明:無論序列化後的碼流大小還是序列化的性能,jdk預設的序列化都很差,