Protobuf(Protocol Buffers)和 JSON 都是数据序列化格式,但它们在许多方面有着显著的不同。以下是对两者的一些主要比较:
总的来说,Protobuf 和 JSON 各有优劣,适用于不同的场景。如果你需要高效的数据传输和严格的类型检查,那么 Protobuf 可能是一个好选择。如果你需要易于使用和人类可读的数据格式,那么 JSON 可能更适合你。
下面以一个简单的例子来对Protobuf和JSON运行效率进行简单对比。
首先通过.proto
来定义所需的结构:
syntax = "proto3";
package pvsj.proto;
option go_package = "./;proto";
import "google/protobuf/struct.proto";
message Base {
string tx_hash = 1;
int64 timestamp = 2;
google.protobuf.Struct extra = 3;
uint64 block_number = 4;
int32 category = 5;
}
message CertGen {
string id = 1;
string issuer = 2;
string name = 3;
string number = 4;
string seal_name = 5;
string seal_number = 6;
string sign_hash = 7;
string date = 8;
Base base = 9;
}
然后通过protoc
生成响应的go代码。
main.go
内容如下:
package main
import (
"encoding/json"
"math/rand"
"time"
"github.com/bytedance/sonic"
"github.com/google/uuid"
pb "github.com/mengbin92/pvsj/proto"
"google.golang.org/protobuf/proto"
"google.golang.org/protobuf/types/known/structpb"
)
func init() {
rand.New(rand.NewSource(time.Now().UnixNano()))
uuid.SetRand(rand.New(rand.NewSource(time.Now().UnixNano())))
}
func main() {
}
// 使用protobuf进行序列化和反序列化
func genProto(num int) {
for i := 0; i < num; i++ {
data := map[string]interface{}{
"name": uuid.NewString(),
"age": rand.Int(),
"score": rand.Float64(),
}
extra, _ := structpb.NewStruct(data)
base := &pb.Base{
TxHash: uuid.NewString(),
Timestamp: time.Now().Unix(),
Extra: extra,
BlockNumber: rand.Uint64(),
Category: rand.Int31(),
}
gen := &pb.CertGen{
Id: uuid.NewString(),
Issuer: uuid.NewString(),
Name: uuid.NewString(),
Number: uuid.NewString(),
SealName: uuid.NewString(),
SealNumber: uuid.NewString(),
SignHash: uuid.NewString(),
Date: time.Now().Format(time.DateTime),
Base: base,
}
genBytes, _ := proto.Marshal(gen)
proto.Unmarshal(genBytes, gen)
}
}
// 使用sonic对json进行序列化和反序列化
func genJsonSonic(num int) {
for i := 0; i < num; i++ {
data := map[string]interface{}{
"name": uuid.NewString(),
"age": rand.Int(),
"score": rand.Float64(),
}
extra, _ := structpb.NewStruct(data)
base := &pb.Base{
TxHash: uuid.NewString(),
Timestamp: time.Now().Unix(),
Extra: extra,
BlockNumber: rand.Uint64(),
Category: rand.Int31(),
}
gen := &pb.CertGen{
Id: uuid.NewString(),
Issuer: uuid.NewString(),
Name: uuid.NewString(),
Number: uuid.NewString(),
SealName: uuid.NewString(),
SealNumber: uuid.NewString(),
SignHash: uuid.NewString(),
Date: time.Now().Format(time.DateTime),
Base: base,
}
genBytes, _ := sonic.Marshal(gen)
sonic.Unmarshal(genBytes, gen)
}
}
// 使用标准库对json进行序列化和反序列化
func genJsonStd(num int) {
for i := 0; i < num; i++ {
data := map[string]interface{}{
"name": uuid.NewString(),
"age": rand.Int(),
"score": rand.Float64(),
}
extra, _ := structpb.NewStruct(data)
base := &pb.Base{
TxHash: uuid.NewString(),
Timestamp: time.Now().Unix(),
Extra: extra,
BlockNumber: rand.Uint64(),
Category: rand.Int31(),
}
gen := &pb.CertGen{
Id: uuid.NewString(),
Issuer: uuid.NewString(),
Name: uuid.NewString(),
Number: uuid.NewString(),
SealName: uuid.NewString(),
SealNumber: uuid.NewString(),
SignHash: uuid.NewString(),
Date: time.Now().Format(time.DateTime),
Base: base,
}
genBytes, _ := json.Marshal(gen)
json.Unmarshal(genBytes, gen)
}
}
bench_test.go
内容如下:
package main
import (
"testing"
)
func BenchmarkGenProto(b *testing.B) {
genProto(b.N)
}
func BenchmarkGenJsonSonic(b *testing.B) {
genJsonSonic(b.N)
}
func BenchmarkGenJsonStd(b *testing.B) {
genJsonStd(b.N)
}
声明:本作品采用署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0)进行许可,使用时请注明出处。
Author: mengbin
blog: mengbin
Github: mengbin92
cnblogs: 恋水无意