使用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领先
分享到:
相关推荐
7. **与其他序列化库的比较** - 与XML和JSON相比,protobuf-net的序列化结果通常更小,传输和解析速度更快。 - 相较于BinaryFormatter,protobuf-net提供跨平台兼容性,且序列化的数据格式更加紧凑。 8. **总结**...
protobuf是Protocol Buffers的简称,它是Google开发的一种数据序列化协议,用于结构化数据的序列化,类似于XML、JSON,但更小、更快、更简单。protobuf 3.11版本是一个稳定且广泛使用的版本,提供了许多改进和新特性...
ProtoBuf-net是.NET平台上对ProtoBuf的实现,它提供了一种简单且高效的方式来序列化和反序列化.NET对象,适用于Unity环境。 Netty则是一个高性能、异步的Java网络应用框架,常用于服务器端开发,提供了高度定制化的...
总的来说,protobuf-3.8.0在VS2019中的使用涉及到.proto文件的编写、protoc编译器的调用、生成源代码的集成以及C++代码的编写与执行。这使得数据序列化变得简单,便于在网络通信、数据存储和跨平台项目中使用。
4. **易于使用**:protobuf-net提供了直观的API,可以轻松地将数据模型与protobuf消息类型对应起来。 **protobuf-net的使用步骤:** 1. **定义数据模型**:使用.proto文件定义数据结构,类似于接口或者类的声明。...
在Unity工程中,我们同样引入protobuf-net库,但需要考虑与C#服务器的交互。Unity支持异步网络操作,我们可以通过Unity的`UnityWebRequest`或`NetworkTransport`组件发送和接收数据。当收到服务器返回的数据时,使用...
在跨语言通信中,如C#与Java,protobuf提供了一个标准的接口,使得不同平台和语言之间的数据交换变得简单。Java端也可以使用Google的官方protobuf库,两者通过protobuf定义的.proto文件进行通信协议的约定。 总的来...
1. **序列化与反序列化**:创建一个对象实例,然后使用BinaryFormatter和ProtoBuf的相应方法进行序列化和反序列化。注意,ProtoBuf需要定义数据结构的.proto文件,并通过编译工具生成对应的C#类。 2. **压缩与解...
这种方法简单直接,但需要注意内存管理,确保在使用完后释放内存。 ### 方法三:使用`std::ostringstream`和`string::c_str()` 另一种方法是使用`std::ostringstream`将protobuf消息序列化为字符串,然后通过`...
为了测试 protobuf 支持是否正常工作,我们可以创建一个简单的 DTO 类(Data Transfer Object),并使用 `ProtoContract` 和 `ProtoMember` 属性标记需要序列化的成员。例如: ```csharp [ProtoContract] public ...
以下是一个简单的示例,展示如何在C++中使用protobuf和zlib进行数据压缩和解压缩: ```cpp #include <google/protobuf/io/coded_stream.h> #include <google/protobuf/io/zero_copy_stream.h> #include <google/...
#include <google/protobuf/io/coded_stream.h> #include <google/protobuf/io/zero_copy_stream_impl.h> #include <google/protobuf/text_format.h> Person person; google::protobuf::TextFormat::...
Logger.e("Stream", "onNext"); } // ... }); ``` gRPC 提供了一种高效、灵活的方式来实现分布式系统的通信。通过使用 Protocol Buffer 定义服务接口,生成客户端代码,并使用 gRPC 客户端调用服务端的方法,...
GRPC的核心设计理念是使分布式系统中的服务间通信变得简单、高效且安全。 1. Protocol Buffers(protobuf) Protocol Buffers是Google开发的一种数据序列化协议,用于结构化数据的编码和解码。相比XML或JSON,...
例如,`grpc.NewServer` 用于创建服务器实例,`grpc.RegisterService` 注册服务,`grpc.Dial` 连接到 gRPC 服务器,`clientConn.NewStream` 创建一个双向流用于异步通信等。 **最佳实践**: - 使用版本管理工具(如...
12. **测试与调试**:在完成服务端和客户端的实现后,可以通过gRPC的测试工具进行交互测试,如使用`grpcurl`或编写简单的测试脚本。 本项目的压缩包"grpc-streaming-demo-master"可能包含了Go和Python的源代码示例...
在GRPC中,服务端和客户端之间的交互主要有四种模式:简单请求(Unary Call)、服务器流(Server Streaming)、客户端流(Client Streaming)以及双向流(Bidirectional Streaming)。下面我们将详细探讨这四种模式...
这里,我们讨论的是一种基于C++实现的简单且可扩展的序列化方法,其灵感来源于Google的Protocol Buffers(protobuf)。 首先,`WHBSerial.h`可能包含了序列化接口的定义,它提供了基础的序列化和反序列化操作。这个...
这里给出一个简单的RPC实现示例,使用Python的socket库: ```python # 服务器端 import socket def remote_service(data): return "Service result: " + data s = socket.socket(socket.AF_INET, socket.SOCK_...