几种序列化协议(protobuf,xstream,jackjson,jdk,hessian)相关数据对比

9 篇文章 0 订阅
6 篇文章 0 订阅

最近研究了下google protobuf协议,顺便对比了一下json,xml,java序列化相关的数据对比,从几个纬度进行对比。

 

别人的相关测试数据: http://code.google.com/p/thrift-protobuf-compare/wiki/Benchmarking

 

测试纬度

  • 序列化时间
  • 反序列化时间
  • bytes大小

测试代码

准备protobuf文件

 

Message.proto文件代码 复制代码  收藏代码
  1. import "InnerMessage.proto";   
  2. package demo;    
  3. option java_package = "com.agapple.protobuf.data";   
  4. option java_outer_classname = "MessageProtos";   
  5. option optimize_for = SPEED ;  //CODE_SIZE,LITE_RUNTIME   
  6. option java_generic_services = false;   
  7. message Message {   
  8.        
  9.     required string strObj = 1 [default="hello"];   
  10.     optional int32 int32Obj = 2;   
  11.     optional int64 int64Obj = 3;   
  12.     optional uint32 uint32Obj = 4;   
  13.     optional uint64 uint64Obj = 5;   
  14.     optional sint32 sint32Obj = 6;   
  15.     optional sint64 sint64Obj = 7;   
  16.     optional fixed32 fixed32Obj = 8;   
  17.     optional fixed64 fixed64Obj = 9;   
  18.     optional sfixed32 sfixed32Obj = 10;   
  19.     optional sfixed64 sfixed64Obj = 11;   
  20.     optional bool   boolObj = 12;   
  21.     optional bytes  bytesObj = 13;   
  22.     optional float folatObj = 14 [deprecated=true];   
  23.     repeated double doubleObj = 15 [packed=true]; //   
  24.     optional InnerMessage innerMessage = 16;   
  25. }  

 

 

Innermessage.proto代码 复制代码  收藏代码
  1. import "EnumType.proto";   
  2.   
  3. package demo;    
  4. option java_package = "com.agapple.protobuf.data";   
  5. option java_outer_classname = "InnerMessageProtos";   
  6.   
  7. message InnerMessage {    
  8.     optional string name = 1 [default = "name"];   
  9.     optional int32 id = 2;   
  10.     optional EnumType type = 3 [default = UNIVERSAL];   
  11. }  

 

 

Enumtype.proto代码 复制代码  收藏代码
  1. package demo;    
  2. option java_package = "com.agapple.protobuf.data";   
  3. option java_outer_classname = "EnumTypeProtos";   
  4.   
  5. enum EnumType {   
  6.     UNIVERSAL = 0;    
  7.     WEB = 1;    
  8.     IMAGES = 2;    
  9.     LOCAL = 3;    
  10.     NEWS = 4;    
  11.     PRODUCTS = 5;    
  12.     VIDEO = 6;    
  13. }  

 

 

基本上把protobuf支持的类型都囊括了,包括嵌套类型,枚举类型,以及各种int,uint,bool,bytes。  

 

依赖关系是Message.proto依赖了InnerMessage对象,而InnerMessage对象里包含了一个自定义枚举类型EnumType。

 

关于类型的使用可参见: 
      http://code.google.com/intl/zh/apis/protocolbuffers/docs/reference/java-generated.html
      http://code.google.com/intl/zh/apis/protocolbuffers/docs/proto.html

 

 

 

生成protobuf javabean

 

 

C代码 复制代码  收藏代码
  1. cd /home/ljh/work/code/src/main/java   
  2.   
  3. /home/ljh/work/protobuf/bin/protoc --proto_path=com/agapple/protobuf/ --java_out=. com/agapple/protobuf/EnumType.proto   
  4. /home/ljh/work/protobuf/bin/protoc --proto_path=com/agapple/protobuf/ --java_out=. com/agapple/protobuf/InnerMessage.proto   
  5. /home/ljh/work/protobuf/bin/protoc --proto_path=com/agapple/protobuf/ --java_out=. com/agapple/protobuf/Message.proto  

 

 通过protobuf自带的protoc进行编译,指定了protobuf文件的路径, 具体的文档: http://code.google.com/intl/zh/apis/protocolbuffers/docs/proto.html#generating

 

 

运行脚本后就会生成对应的3个javabean文件: MessageProtos , InnerMessageProtos , EnumTypeProtos。

 

最后构造测试的protobuf bean代码

 

Java代码 复制代码  收藏代码
  1. private static MessageProtos.Message getProtobufBean() {   
  2.         com.agapple.protobuf.data.MessageProtos.Message.Builder messageBuilder = MessageProtos.Message.newBuilder();   
  3.   
  4.         messageBuilder.setStrObj("message");   
  5.         messageBuilder.setFolatObj(1f);   
  6.         messageBuilder.addDoubleObj(1d);   
  7.         messageBuilder.addDoubleObj(2d);   
  8.         messageBuilder.setBoolObj(true);   
  9.   
  10.         messageBuilder.setBytesObj(ByteString.copyFrom(new byte[] { 123 }));   
  11.         messageBuilder.setInt32Obj(32);   
  12.         messageBuilder.setInt64Obj(64l);   
  13.         messageBuilder.setSint32Obj(232);   
  14.         messageBuilder.setSint64Obj(264);   
  15.         messageBuilder.setFixed32Obj(532);   
  16.         messageBuilder.setFixed64Obj(564);   
  17.         messageBuilder.setSfixed32Obj(2532);   
  18.         messageBuilder.setSfixed64Obj(2564);   
  19.         messageBuilder.setUint32Obj(632);   
  20.         messageBuilder.setUint64Obj(664);   
  21.   
  22.         com.agapple.protobuf.data.InnerMessageProtos.InnerMessage.Builder innerMessageBuilder = InnerMessageProtos.InnerMessage.newBuilder();   
  23.         innerMessageBuilder.setId(1);   
  24.         innerMessageBuilder.setName("inner");   
  25.         innerMessageBuilder.setType(EnumType.PRODUCTS);   
  26.   
  27.         messageBuilder.setInnerMessage(innerMessageBuilder);   
  28.   
  29.         return messageBuilder.build();   
  30.     }  
private static MessageProtos.Message getProtobufBean() {
        com.agapple.protobuf.data.MessageProtos.Message.Builder messageBuilder = MessageProtos.Message.newBuilder();

        messageBuilder.setStrObj("message");
        messageBuilder.setFolatObj(1f);
        messageBuilder.addDoubleObj(1d);
        messageBuilder.addDoubleObj(2d);
        messageBuilder.setBoolObj(true);

        messageBuilder.setBytesObj(ByteString.copyFrom(new byte[] { 1, 2, 3 }));
        messageBuilder.setInt32Obj(32);
        messageBuilder.setInt64Obj(64l);
        messageBuilder.setSint32Obj(232);
        messageBuilder.setSint64Obj(264);
        messageBuilder.setFixed32Obj(532);
        messageBuilder.setFixed64Obj(564);
        messageBuilder.setSfixed32Obj(2532);
        messageBuilder.setSfixed64Obj(2564);
        messageBuilder.setUint32Obj(632);
        messageBuilder.setUint64Obj(664);

        com.agapple.protobuf.data.InnerMessageProtos.InnerMessage.Builder innerMessageBuilder = InnerMessageProtos.InnerMessage.newBuilder();
        innerMessageBuilder.setId(1);
        innerMessageBuilder.setName("inner");
        innerMessageBuilder.setType(EnumType.PRODUCTS);

        messageBuilder.setInnerMessage(innerMessageBuilder);

        return messageBuilder.build();
    }

 

 

 

准备纯Pojo Bean 

同样的,为了和json , xml以及java序列化有个很好的对比,新建了3个纯的pojo bean:  MessagePojo , InnerMessagePojo , EnumTypePojo。

属性和proto的bean保持一致。

 

构建bean对象

 

Java代码 复制代码  收藏代码
  1. private static MessagePojo getPojoBean() {   
  2.         MessagePojo bean = new MessagePojo();   
  3.   
  4.         bean.setStrObj("message");   
  5.         bean.setFolatObj(1f);   
  6.         List<Double> doubleObj = new ArrayList<Double>();   
  7.         doubleObj.add(1d);   
  8.         doubleObj.add(2d);   
  9.         bean.setDoubleObj(doubleObj);   
  10.         bean.setBoolObj(true);   
  11.   
  12.         bean.setBytesObj(new byte[] { 123 });   
  13.         bean.setInt32Obj(32);   
  14.         bean.setInt64Obj(64l);   
  15.         bean.setSint32Obj(232);   
  16.         bean.setSint64Obj(264);   
  17.         bean.setFixed32Obj(532);   
  18.         bean.setFixed64Obj(564);   
  19.         bean.setSfixed32Obj(2532);   
  20.         bean.setSfixed64Obj(2564);   
  21.         bean.setUint32Obj(632);   
  22.         bean.setUint64Obj(664);   
  23.   
  24.         InnerMessagePojo innerMessagePojo = new InnerMessagePojo();   
  25.         innerMessagePojo.setId(1);   
  26.         innerMessagePojo.setName("inner");   
  27.         innerMessagePojo.setType(EnumTypePojo.PRODUCTS);   
  28.   
  29.         bean.setInnerMessage(innerMessagePojo);   
  30.   
  31.         return bean;   
  32.     }  
private static MessagePojo getPojoBean() {
        MessagePojo bean = new MessagePojo();

        bean.setStrObj("message");
        bean.setFolatObj(1f);
        List<Double> doubleObj = new ArrayList<Double>();
        doubleObj.add(1d);
        doubleObj.add(2d);
        bean.setDoubleObj(doubleObj);
        bean.setBoolObj(true);

        bean.setBytesObj(new byte[] { 1, 2, 3 });
        bean.setInt32Obj(32);
        bean.setInt64Obj(64l);
        bean.setSint32Obj(232);
        bean.setSint64Obj(264);
        bean.setFixed32Obj(532);
        bean.setFixed64Obj(564);
        bean.setSfixed32Obj(2532);
        bean.setSfixed64Obj(2564);
        bean.setUint32Obj(632);
        bean.setUint64Obj(664);

        InnerMessagePojo innerMessagePojo = new InnerMessagePojo();
        innerMessagePojo.setId(1);
        innerMessagePojo.setName("inner");
        innerMessagePojo.setType(EnumTypePojo.PRODUCTS);

        bean.setInnerMessage(innerMessagePojo);

        return bean;
    }

 

 

 

具体的测试代码

定义测试Template接口

 

Java代码 复制代码  收藏代码
  1. interface TestCallback {   
  2.   
  3.     String getName();   
  4.   
  5.     byte[] writeObject(Object source);   
  6.   
  7.     Object readObject(byte[] bytes);   
  8. }  
interface TestCallback {

    String getName();

    byte[] writeObject(Object source);

    Object readObject(byte[] bytes);
}

 

 

统一的测试模板

 

Java代码 复制代码  收藏代码
  1. private static void testTemplate(TestCallback callback, Object source, int count) {   
  2.         int warmup = 10;   
  3.         // 先进行预热,加载一些类,避免影响测试   
  4.         for (int i = 0; i < warmup; i++) {   
  5.             byte[] bytes = callback.writeObject(source);   
  6.             callback.readObject(bytes);   
  7.         }   
  8.         restoreJvm(); // 进行GC回收   
  9.         // 进行测试   
  10.         long start = System.nanoTime();   
  11.         long size = 0l;   
  12.         for (int i = 0; i < count; i++) {   
  13.             byte[] bytes = callback.writeObject(source);   
  14.             size = size + bytes.length;   
  15.             callback.readObject(bytes);   
  16.             // System.out.println(callback.readObject(bytes));   
  17.             bytes = null;   
  18.         }   
  19.         long nscost = (System.nanoTime() - start);   
  20.         System.out.println(callback.getName() + " total cost=" + integerFormat.format(nscost) + "ns , each cost="  
  21.                            + integerFormat.format(nscost / count) + "ns , and byte sizes = " + size / count);   
  22.         restoreJvm();// 进行GC回收   
  23.   
  24.     }  
private static void testTemplate(TestCallback callback, Object source, int count) {
        int warmup = 10;
        // 先进行预热,加载一些类,避免影响测试
        for (int i = 0; i < warmup; i++) {
            byte[] bytes = callback.writeObject(source);
            callback.readObject(bytes);
        }
        restoreJvm(); // 进行GC回收
        // 进行测试
        long start = System.nanoTime();
        long size = 0l;
        for (int i = 0; i < count; i++) {
            byte[] bytes = callback.writeObject(source);
            size = size + bytes.length;
            callback.readObject(bytes);
            // System.out.println(callback.readObject(bytes));
            bytes = null;
        }
        long nscost = (System.nanoTime() - start);
        System.out.println(callback.getName() + " total cost=" + integerFormat.format(nscost) + "ns , each cost="
                           + integerFormat.format(nscost / count) + "ns , and byte sizes = " + size / count);
        restoreJvm();// 进行GC回收

    }

 

 

  在测试模板方法中,使用了warmup预热的概念,就是预先执行目标方法一定的次数,用于避免因为jit的优化影响系统测试。 同时包含了每次测试模板调用完成后system.gc保证下一轮的功能测试

 

  相应的restoreJvm方法: 

Java代码 复制代码  收藏代码
  1. private static void restoreJvm() {   
  2.         int maxRestoreJvmLoops = 10;   
  3.         long memUsedPrev = memoryUsed();   
  4.         for (int i = 0; i < maxRestoreJvmLoops; i++) {   
  5.             System.runFinalization();   
  6.             System.gc();   
  7.   
  8.             long memUsedNow = memoryUsed();   
  9.             // break early if have no more finalization and get constant mem used   
  10.             if ((ManagementFactory.getMemoryMXBean().getObjectPendingFinalizationCount() == 0)   
  11.                 && (memUsedNow >= memUsedPrev)) {   
  12.                 break;   
  13.             } else {   
  14.                 memUsedPrev = memUsedNow;   
  15.             }   
  16.         }   
  17.     }   
  18.   
  19.     private static long memoryUsed() {   
  20.         Runtime rt = Runtime.getRuntime();   
  21.         return rt.totalMemory() - rt.freeMemory();   
  22.     }  
private static void restoreJvm() {
        int maxRestoreJvmLoops = 10;
        long memUsedPrev = memoryUsed();
        for (int i = 0; i < maxRestoreJvmLoops; i++) {
            System.runFinalization();
            System.gc();

            long memUsedNow = memoryUsed();
            // break early if have no more finalization and get constant mem used
            if ((ManagementFactory.getMemoryMXBean().getObjectPendingFinalizationCount() == 0)
                && (memUsedNow >= memUsedPrev)) {
                break;
            } else {
                memUsedPrev = memUsedNow;
            }
        }
    }

    private static long memoryUsed() {
        Runtime rt = Runtime.getRuntime();
        return rt.totalMemory() - rt.freeMemory();
    }

 

最后相应的测试例子:

 

Java代码 复制代码  收藏代码
  1. final int testCount = 1000 * 500;           
  2. final MessageProtos.Message protoObj = getProtobufBean();   
  3. final MessagePojo pojoOBj = getPojoBean();   
  4.   
  5. // Serializable测试   
  6. testTemplate(new TestCallback() {   
  7.   
  8.     public String getName() {   
  9.         return "Serializable Test";   
  10.     }   
  11.   
  12.     @Override  
  13.     public byte[] writeObject(Object source) {   
  14.         try {   
  15.             ByteArrayOutputStream bout = new ByteArrayOutputStream();   
  16.             ObjectOutputStream output = new ObjectOutputStream(bout);   
  17.             output.writeObject(source);   
  18.             return bout.toByteArray();   
  19.         } catch (IOException e) {   
  20.             e.printStackTrace();   
  21.         }   
  22.         return null;   
  23.     }   
  24.   
  25.     @Override  
  26.     public Object readObject(byte[] bytes) {   
  27.         try {   
  28.             ByteArrayInputStream bin = new ByteArrayInputStream(bytes);   
  29.             ObjectInputStream input = new ObjectInputStream(bin);   
  30.             return input.readObject();   
  31.         } catch (Exception e) {   
  32.             e.printStackTrace();   
  33.         }   
  34.         return null;   
  35.     }   
  36. }, pojoOBj, testCount);   
  37.   
  38. // protobuf测试   
  39. testTemplate(new TestCallback() {   
  40.   
  41.     public String getName() {   
  42.         return "protobuf test";   
  43.     }   
  44.   
  45.     @Override  
  46.     public byte[] writeObject(Object source) {   
  47.         if (source instanceof MessageProtos.Message) {   
  48.             MessageProtos.Message message = (MessageProtos.Message) source;   
  49.             return message.toByteArray();   
  50.         }   
  51.   
  52.         return null;   
  53.     }   
  54.   
  55.     @Override  
  56.     public Object readObject(byte[] bytes) {   
  57.         try {   
  58.             return MessageProtos.Message.parseFrom(bytes);   
  59.         } catch (InvalidProtocolBufferException e) {   
  60.             e.printStackTrace();   
  61.         }   
  62.         return null;   
  63.     }   
  64. }, protoObj, testCount);   
  65.   
  66. // json测试   
  67. final ObjectMapper objectMapper = new ObjectMapper();   
  68. final JavaType javaType = TypeFactory.type(pojoOBj.getClass());   
  69.   
  70. // JSON configuration not to serialize null field   
  71. objectMapper.getSerializationConfig().setSerializationInclusion(JsonSerialize.Inclusion.NON_NULL);   
  72.   
  73. // JSON configuration not to throw exception on empty bean class   
  74. objectMapper.getSerializationConfig().disable(SerializationConfig.Feature.FAIL_ON_EMPTY_BEANS);   
  75.   
  76. // JSON configuration for compatibility   
  77. objectMapper.configure(Feature.ALLOW_UNQUOTED_FIELD_NAMES, true);   
  78. objectMapper.configure(Feature.ALLOW_UNQUOTED_CONTROL_CHARS, true);   
  79.   
  80. testTemplate(new TestCallback() {   
  81.   
  82.     public String getName() {   
  83.         return "Jackson Test";   
  84.     }   
  85.   
  86.     @Override  
  87.     public byte[] writeObject(Object source) {   
  88.         try {   
  89.             return objectMapper.writeValueAsBytes(source);   
  90.         } catch (JsonGenerationException e) {   
  91.             e.printStackTrace();   
  92.         } catch (JsonMappingException e) {   
  93.             e.printStackTrace();   
  94.         } catch (IOException e) {   
  95.             e.printStackTrace();   
  96.         }   
  97.   
  98.         return null;   
  99.     }   
  100.   
  101.     @Override  
  102.     public Object readObject(byte[] bytes) {   
  103.         try {   
  104.             return objectMapper.readValue(bytes, 0, bytes.length, javaType);   
  105.         } catch (JsonParseException e) {   
  106.             e.printStackTrace();   
  107.         } catch (JsonMappingException e) {   
  108.             e.printStackTrace();   
  109.         } catch (IOException e) {   
  110.             e.printStackTrace();   
  111.         }   
  112.         return null;   
  113.     }   
  114. }, pojoOBj, testCount);   
  115.   
  116. // Xstream测试   
  117. final XStream xstream = new XStream();   
  118. testTemplate(new TestCallback() {   
  119.   
  120.     public String getName() {   
  121.         return "Xstream test";   
  122.     }   
  123.   
  124.     @Override  
  125.     public byte[] writeObject(Object source) {   
  126.         return xstream.toXML(source).getBytes();   
  127.     }   
  128.   
  129.     @Override  
  130.     public Object readObject(byte[] bytes) {   
  131.         return xstream.fromXML(new ByteArrayInputStream(bytes));   
  132.     }   
  133. }, pojoOBj, testCount);  
        final int testCount = 1000 * 500;        
        final MessageProtos.Message protoObj = getProtobufBean();
        final MessagePojo pojoOBj = getPojoBean();

        // Serializable测试
        testTemplate(new TestCallback() {

            public String getName() {
                return "Serializable Test";
            }

            @Override
            public byte[] writeObject(Object source) {
                try {
                    ByteArrayOutputStream bout = new ByteArrayOutputStream();
                    ObjectOutputStream output = new ObjectOutputStream(bout);
                    output.writeObject(source);
                    return bout.toByteArray();
                } catch (IOException e) {
                    e.printStackTrace();
                }
                return null;
            }

            @Override
            public Object readObject(byte[] bytes) {
                try {
                    ByteArrayInputStream bin = new ByteArrayInputStream(bytes);
                    ObjectInputStream input = new ObjectInputStream(bin);
                    return input.readObject();
                } catch (Exception e) {
                    e.printStackTrace();
                }
                return null;
            }
        }, pojoOBj, testCount);

        // protobuf测试
        testTemplate(new TestCallback() {

            public String getName() {
                return "protobuf test";
            }

            @Override
            public byte[] writeObject(Object source) {
                if (source instanceof MessageProtos.Message) {
                    MessageProtos.Message message = (MessageProtos.Message) source;
                    return message.toByteArray();
                }

                return null;
            }

            @Override
            public Object readObject(byte[] bytes) {
                try {
                    return MessageProtos.Message.parseFrom(bytes);
                } catch (InvalidProtocolBufferException e) {
                    e.printStackTrace();
                }
                return null;
            }
        }, protoObj, testCount);

        // json测试
        final ObjectMapper objectMapper = new ObjectMapper();
        final JavaType javaType = TypeFactory.type(pojoOBj.getClass());

        // JSON configuration not to serialize null field
        objectMapper.getSerializationConfig().setSerializationInclusion(JsonSerialize.Inclusion.NON_NULL);

        // JSON configuration not to throw exception on empty bean class
        objectMapper.getSerializationConfig().disable(SerializationConfig.Feature.FAIL_ON_EMPTY_BEANS);

        // JSON configuration for compatibility
        objectMapper.configure(Feature.ALLOW_UNQUOTED_FIELD_NAMES, true);
        objectMapper.configure(Feature.ALLOW_UNQUOTED_CONTROL_CHARS, true);

        testTemplate(new TestCallback() {

            public String getName() {
                return "Jackson Test";
            }

            @Override
            public byte[] writeObject(Object source) {
                try {
                    return objectMapper.writeValueAsBytes(source);
                } catch (JsonGenerationException e) {
                    e.printStackTrace();
                } catch (JsonMappingException e) {
                    e.printStackTrace();
                } catch (IOException e) {
                    e.printStackTrace();
                }

                return null;
            }

            @Override
            public Object readObject(byte[] bytes) {
                try {
                    return objectMapper.readValue(bytes, 0, bytes.length, javaType);
                } catch (JsonParseException e) {
                    e.printStackTrace();
                } catch (JsonMappingException e) {
                    e.printStackTrace();
                } catch (IOException e) {
                    e.printStackTrace();
                }
                return null;
            }
        }, pojoOBj, testCount);

        // Xstream测试
        final XStream xstream = new XStream();
        testTemplate(new TestCallback() {

            public String getName() {
                return "Xstream test";
            }

            @Override
            public byte[] writeObject(Object source) {
                return xstream.toXML(source).getBytes();
            }

            @Override
            public Object readObject(byte[] bytes) {
                return xstream.fromXML(new ByteArrayInputStream(bytes));
            }
        }, pojoOBj, testCount);

 

 

2011年3月10号补充 =========================================================

增加了hessian 3.1.5版本基于二进制序列化的测试

 

Xml代码 复制代码  收藏代码
  1. <dependency>  
  2.     <groupId>com.caucho</groupId>  
  3.     <artifactId>hessian</artifactId>  
  4.     <version>3.1.5</version>  
  5. </dependency>  

 

 

测试了3种情况:

 

  1. hessian 2协议
  2. hessian 2协议 + deflat压缩
  3. hessian 1协议

 

 

测试代码:

 

Java代码 复制代码  收藏代码
  1. // hessian 2 with no deflat   
  2.         testTemplate(new TestCallback() {   
  3.   
  4.             public String getName() {   
  5.                 return "hessian 2 with no deflat";   
  6.             }   
  7.   
  8.             @Override  
  9.             public byte[] writeObject(Object source) {   
  10.                 try {   
  11.                     ByteArrayOutputStream bos = new ByteArrayOutputStream();   
  12.                     Hessian2Output out = new Hessian2Output(bos);   
  13.                     // out.startMessage();   
  14.                     out.writeObject(source);   
  15.                     // out.completeMessage();   
  16.                     out.flush();   
  17.                     return bos.toByteArray();   
  18.                 } catch (IOException e) {   
  19.                     e.printStackTrace();   
  20.                 }   
  21.                 return null;   
  22.             }   
  23.   
  24.             @Override  
  25.             public Object readObject(byte[] bytes) {   
  26.                 try {   
  27.                     ByteArrayInputStream bin = new ByteArrayInputStream(bytes);   
  28.                     Hessian2Input in = new Hessian2Input(bin);   
  29.                     // in.startMessage();   
  30.                     Object obj = in.readObject();   
  31.                     // in.completeMessage();   
  32.                     return obj;   
  33.                 } catch (IOException e) {   
  34.                     e.printStackTrace();   
  35.                 }   
  36.                 return null;   
  37.             }   
  38.         }, pojoOBj, testCount);   
  39.   
  40.         // hessian 2 with deflat   
  41.         final Deflation envelope = new Deflation();   
  42.         testTemplate(new TestCallback() {   
  43.   
  44.             public String getName() {   
  45.                 return "hessian 2 with deflat";   
  46.             }   
  47.   
  48.             @Override  
  49.             public byte[] writeObject(Object source) {   
  50.                 try {   
  51.                     ByteArrayOutputStream bos = new ByteArrayOutputStream();   
  52.                     Hessian2Output out = new Hessian2Output(bos);   
  53.                     out = envelope.wrap(out);   
  54.                     out.writeObject(source);   
  55.                     out.flush();   
  56.                     out.close(); // 记得关闭   
  57.                     return bos.toByteArray();   
  58.                 } catch (Exception e) {   
  59.                     e.printStackTrace();   
  60.                 }   
  61.                 return null;   
  62.             }   
  63.   
  64.             @Override  
  65.             public Object readObject(byte[] bytes) {   
  66.                 try {   
  67.                     ByteArrayInputStream bin = new ByteArrayInputStream(bytes);   
  68.                     Hessian2Input in = new Hessian2Input(bin);   
  69.                     in = envelope.unwrap(in);   
  70.                     Object obj = in.readObject();   
  71.                     in.close();   
  72.                     return obj;   
  73.                 } catch (IOException e) {   
  74.                     e.printStackTrace();   
  75.                 }   
  76.                 return null;   
  77.             }   
  78.         }, pojoOBj, testCount);   
  79.   
  80.         // hessian 1 with no deflat   
  81.         testTemplate(new TestCallback() {   
  82.   
  83.             public String getName() {   
  84.                 return "hessian 1 with no deflat";   
  85.             }   
  86.   
  87.             @Override  
  88.             public byte[] writeObject(Object source) {   
  89.                 try {   
  90.                     ByteArrayOutputStream bos = new ByteArrayOutputStream();   
  91.                     HessianOutput out = new HessianOutput(bos);   
  92.                     out.writeObject(source);   
  93.                     out.flush();   
  94.                     return bos.toByteArray();   
  95.                 } catch (Exception e) {   
  96.                     e.printStackTrace();   
  97.                 }   
  98.                 return null;   
  99.             }   
  100.   
  101.             @Override  
  102.             public Object readObject(byte[] bytes) {   
  103.                 try {   
  104.                     ByteArrayInputStream bin = new ByteArrayInputStream(bytes);   
  105.                     HessianInput in = new HessianInput(bin);   
  106.                     Object obj = in.readObject();   
  107.                     in.close();   
  108.                     return obj;   
  109.                 } catch (IOException e) {   
  110.                     e.printStackTrace();   
  111.                 }   
  112.                 return null;   
  113.             }   
  114.         }, pojoOBj, testCount);  
// hessian 2 with no deflat
        testTemplate(new TestCallback() {

            public String getName() {
                return "hessian 2 with no deflat";
            }

            @Override
            public byte[] writeObject(Object source) {
                try {
                    ByteArrayOutputStream bos = new ByteArrayOutputStream();
                    Hessian2Output out = new Hessian2Output(bos);
                    // out.startMessage();
                    out.writeObject(source);
                    // out.completeMessage();
                    out.flush();
                    return bos.toByteArray();
                } catch (IOException e) {
                    e.printStackTrace();
                }
                return null;
            }

            @Override
            public Object readObject(byte[] bytes) {
                try {
                    ByteArrayInputStream bin = new ByteArrayInputStream(bytes);
                    Hessian2Input in = new Hessian2Input(bin);
                    // in.startMessage();
                    Object obj = in.readObject();
                    // in.completeMessage();
                    return obj;
                } catch (IOException e) {
                    e.printStackTrace();
                }
                return null;
            }
        }, pojoOBj, testCount);

        // hessian 2 with deflat
        final Deflation envelope = new Deflation();
        testTemplate(new TestCallback() {

            public String getName() {
                return "hessian 2 with deflat";
            }

            @Override
            public byte[] writeObject(Object source) {
                try {
                    ByteArrayOutputStream bos = new ByteArrayOutputStream();
                    Hessian2Output out = new Hessian2Output(bos);
                    out = envelope.wrap(out);
                    out.writeObject(source);
                    out.flush();
                    out.close(); // 记得关闭
                    return bos.toByteArray();
                } catch (Exception e) {
                    e.printStackTrace();
                }
                return null;
            }

            @Override
            public Object readObject(byte[] bytes) {
                try {
                    ByteArrayInputStream bin = new ByteArrayInputStream(bytes);
                    Hessian2Input in = new Hessian2Input(bin);
                    in = envelope.unwrap(in);
                    Object obj = in.readObject();
                    in.close();
                    return obj;
                } catch (IOException e) {
                    e.printStackTrace();
                }
                return null;
            }
        }, pojoOBj, testCount);

        // hessian 1 with no deflat
        testTemplate(new TestCallback() {

            public String getName() {
                return "hessian 1 with no deflat";
            }

            @Override
            public byte[] writeObject(Object source) {
                try {
                    ByteArrayOutputStream bos = new ByteArrayOutputStream();
                    HessianOutput out = new HessianOutput(bos);
                    out.writeObject(source);
                    out.flush();
                    return bos.toByteArray();
                } catch (Exception e) {
                    e.printStackTrace();
                }
                return null;
            }

            @Override
            public Object readObject(byte[] bytes) {
                try {
                    ByteArrayInputStream bin = new ByteArrayInputStream(bytes);
                    HessianInput in = new HessianInput(bin);
                    Object obj = in.readObject();
                    in.close();
                    return obj;
                } catch (IOException e) {
                    e.printStackTrace();
                }
                return null;
            }
        }, pojoOBj, testCount);
 

 


测试结果

序列化数据对比



 

bytes字节数对比

具体的数字: 

 protobufjacksonxstreamSerializablehessian2hessian2压缩hessian1
序列化(单位ns)11545421 92406 101892679410076629027
反序列化(单位ns)13348743 117329 640273787118843237596
bytes97311 664 824374283495

 

  1. protobuf 不管是处理时间上,还是空间占用上都优于现有的其他序列化方式。内存暂用是java 序列化的1/9,时间也是差了一个数量级,一次操作在1us左右。缺点:就是对象结构体有限制,只适合于内部系统使用。
  2. json格式在空间占用还是有一些优势,是java序列化的1/2.6。序列化和反序列化处理时间上差不多,也就在5us。当然这次使用的jackson,如果使用普通的jsonlib可能没有这样好的性能,jsonlib估计跟java序列化差不多。
  3. xml相比于java序列化来说,空间占用上有点优势,但不明显。处理时间上比java序列化多了一个数量级,在100us左右。
  4. 以前一种的java序列化,表现得有些失望
  5. hessian测试有点意外,具体序列化数据上还步入json。性能上也不如jackjson,输得比较彻底。
  6. hessian使用压缩,虽然在字节上有20%以上的空间提升,但性能上差了4,5倍,典型的以时间换空间。总的来说还是google protobuf比较给力

 

总结 

以后在内部系统,数据cache存储上可以考虑使用protobuf。跟外部系统交互上可以考虑使用json。

 

有兴趣的同学,可以研究一下google protobuf的marshall的方式: http://code.google.com/intl/zh/apis/protocolbuffers/docs/encoding.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值