protobuf与stream的简单比较

使用protobuf与传统的stream作比较
1.协议模型:

package tutorial;

option java_package = "com.example.tutorial";
option java_outer_classname = "RoleTest";
message Role {
optional int64 id = 1;
optional string name = 2;
optional string email = 3;
}


即此协议包括id name email三个字段。

2.write写法比较
protobuf的写法如下

public static byte[] protobufEncode() throws Exception{
Builder builder = Role.newBuilder();
builder.setId(id);
builder.setName(name);
builder.setEmail(mail);
Role build = builder.build();
byte[] byteArray = build.toByteArray();
return byteArray;
}



stream的写法如下

public static byte[] streamEncode() throws Exception{
ByteArrayOutputStream bos = new ByteArrayOutputStream();
DataOutputStream output = new DataOutputStream(bos);
output.writeLong(id);
output.writeUTF(name);
output.writeUTF(mail);
byte[] bytes = bos.toByteArray();
return bytes;
}



可以看出protobuf是不用在代码体现按照顺序write,而stream则需要。

3.read的写法比较

protobuf的写法如下

public static void protobufDecode(byte[] data) throws Exception{
Role role = Role.parseFrom(data);
System.err.println(role.getId()+",name:"+role.getName()+",email:"+role.getEmail());
}



stream的写法如下

public static void streamDecode(byte[] data) throws IOException{
ByteArrayInputStream bis = new ByteArrayInputStream(data);
DataInputStream input = new DataInputStream(bis);
long id = input.readLong();
String name = input.readUTF();
String email = input.readUTF();
System.err.println(id+",name:"+name+",email:"+email);
}



跟write一样,protobuf是不用按照顺序读,直接可以转换成一个对象。

4.write的特殊情况
有一些协议的第一个字段是表示结果(如回复添加好友)。在操作验证失败的情况下,一般客户端会
提示一些语句,如'此玩家已经是您的好友'。这种操作失败的协议通常除第一个字段以后的字段(好友id、名字、性别等)都是
可以忽略的,但是用普通的stream方式去read,一定要完整读完,否则会抛异常。
而protobuf则可以在定义协议的时候使用optional关键字表示此字段是可以不发送的,所以用protobuf,可以这样写


public static byte[] protobufEncode() throws Exception{
Builder builder = Role.newBuilder();
builder.setId(id);
//builder.setName(name);
//builder.setEmail(mail);
Role build = builder.build();
byte[] byteArray = build.toByteArray();
return byteArray;
}


读取的时候能够正常转换成对象,而没发送的字段按照字段类型的默认值来表示,如string默认是'',boolean是false,int32是0

5.流量对比
protobuf在压缩成byte[]的时候会动态计算字段的大小,但是会占用位,具体未看明白,看比较。
A.只发送整形的对比
用long型id,为以下情况

id:1
stream,len:8
[0, 0, 0, 0, 0, 0, 0, 1]
protobuf,len:2
[16, 1]

id:1000
stream,len:8
[0, 0, 0, 0, 0, 0, 3, -24]
protobuf,len:3
[16, -24, 7]

id:1000000
stream,len:8
[0, 0, 0, 0, 0, 15, 66, 64]
protobuf,len:4
[16, -64, -124, 61]

id:10000000000
stream,len:8
[0, 0, 0, 2, 84, 11, -28, 0]
protobuf,len:6
[16, -128, -56, -81, -96, 37]

id:10000000000000
stream,len:8
[0, 0, 9, 24, 78, 114, -96, 0]
protobuf,len:8
[16, -128, -64, -54, -13, -124, -93, 2]

id:1000000000000000
stream,len:8
[0, 3, -115, 126, -92, -58, -128, 0]
protobuf,len:9
[16, -128, -128, -102, -90, -22, -81, -29, 1]

id:100000000000000000
stream,len:8
[1, 99, 69, 120, 93, -118, 0, 0]
protobuf,len:10
[16, -128, -128, -88, -20, -123, -81, -47, -79, 1]

可以看出,当id数值小的时候,protobuf会比stream好,当数值到一定时,两者相同,当数值很大,protobuf会比stream差。

B.只发送字符串

name:k
stream,len:3
[0, 1, 107]
protobuf,len:3
[10, 1, 107]


name:kyle
stream,len:6
[0, 4, 107, 121, 108, 101]
protobuf,len:6
[10, 4, 107, 121, 108, 101]

name:kylekyle
stream,len:10
[0, 8, 107, 121, 108, 101, 107, 121, 108, 101]
protobuf,len:10
[10, 8, 107, 121, 108, 101, 107, 121, 108, 101]

name:kylekylekyle
stream,len:14
[0, 12, 107, 121, 108, 101, 107, 121, 108, 101, 107, 121, 108, 101]
protobuf,len:14
[10, 12, 107, 121, 108, 101, 107, 121, 108, 101, 107, 121, 108, 101]

可以看出,发送字符串是差不多的。


6.性能对比
发送id name email,作不同次数的读写循环对比,id选取两者流量相同10000000000000

id:10000000000000,name:kyle,email:kyle@qq.com
loop times:100
stream,spend:2 ms
protobuf,spend:30 ms

id:10000000000000,name:kyle,email:kyle@qq.com
loop times:10000
stream,spend:33 ms
protobuf,spend:81 ms

id:10000000000000,name:kyle,email:kyle@qq.com
loop times:100000
stream,spend:176 ms
protobuf,spend:178 ms

id:10000000000000,name:kyle,email:kyle@qq.com
loop times:1000000
stream,spend:1590 ms
protobuf,spend:1179 ms

比较奇怪,当循环数比较小时,stream领先,当循环数比较大时,protobuf领先
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值