Protobuf与Avro的序列化性能测试

时间:2021-11-11 07:54:19

Avro与Protobuf性能对比

所用Schema

Avro所用Schema

{"namespace": "test.avro",
"type": "record",
"name": "User",
"fields": [
{"name": "i", "type": ["int","null"]},
{"name": "l", "type": ["long", "null"]},
{"name": "s", "type": ["string", "null"]},
{"name":"b","type":["boolean","null"]}
]
}

Protobuf所用Schema

message SomeData {
optional int32 i = 1;
optional int64 l = 2;
optional string s = 3;
optional bool b=4;

}

写出的数据:

{
"i" : random,
"l" : random,
"s" : "never",
"b" : random
}

测试对象:

  1. protocProtobuf Schema编译成java类来进行操作
  2. DynamicMessage动态生成所需的数据结构来进行 Protobuf 的序列化操作
  3. GenericMessage根据Avro的定义文件解析出来的Schema进行操作
  4. GenericMessage根据动态生成的Schema进行操作

测试结果:

每个测试用了1,000,000条数据

测试1: 生成文件

其中:

  • ProtobufwriteDelimitedTo方法直接写到文件输出流
  • AvroDataFileWriter生成输出文件

结果:
- 测试对象1耗时501ms
- 测试对象2耗时985ms
- 测试对象3耗时1356ms
- 测试对象4耗时1343ms

另外:

  • Protobuf 文件大小约为28m
  • Avro 文件未压缩的状态大小约为 25m,采用Snappy压缩后,大小变为18m

测试2: 序列化但不生成文件

其中:

  • ProtobuftoByteArray方法得到byte[]
  • AvroDatumWriterDirectBinaryEncoder来得到byte[]

结果:

  • 测试对象1耗时418ms
  • 测试对象2耗时978ms
  • 测试对象3耗时1741ms
  • 测试对象4耗时1748ms

分析:

  • Avro 不生成文件居然比生成文件还要慢,这主要是DirectBinaryEncoder导致的,具体细节还没看
  • Protobuf的两种方式效率差了2倍,这主要是因为对接入的Field所采用的方法不同导致的,如果通过FieldName,速度比直接用对应的get()方法访问速度慢得多

结论

ProtobufAvro 快2~4倍

其中 Avro的序列化也许还有优化的空间,主要在DirectBinaryEncoderEncoder的差异上