Protobuf(Protocol Buffers)和 JSON 都是数据序列化格式,但它们在许多方面有着显著的不同。以下是对两者的一些主要比较:

  1. 数据大小和速度:

    • Protobuf:由于 Protobuf 是二进制格式,因此它生成的数据通常比 JSON 小很多,这使得 Protobuf 在网络传输中更加高效。同时,Protobuf 的解析和序列化速度也比 JSON 快。
    • JSON:JSON 是文本格式,它生成的数据通常比 Protobuf 大,且解析和序列化速度较慢。
  2. 可读性和易用性:
    • Protobuf:Protobuf 是二进制格式,人类无法直接阅读。此外,使用 Protobuf 需要预先定义数据结构(.proto 文件),这增加了使用的复杂性。
    • JSON:JSON 是文本格式,人类可以直接阅读和编辑。此外,JSON 的数据结构可以在运行时动态定义,这使得 JSON 更易于使用。
  3. 类型安全和版本兼容性:
    • Protobuf:Protobuf 支持静态类型检查,这可以在编译时捕获类型错误。此外,Protobuf 设计了一套版本兼容性机制,可以在不破坏旧版本的情况下添加新的字段。
    • JSON:JSON 是动态类型的,无法在编译时捕获类型错误。此外,JSON 没有内置的版本兼容性机制,如果数据结构发生变化,可能需要修改代码以适应新的结构。
  4. 支持的语言:
    • Protobuf:Google 提供了多种语言的 Protobuf 库,包括 C++、Java、Python、Golang 等。
    • JSON:几乎所有的编程语言都支持 JSON。
  5. 学习成本:
    • Protobuf:Protobuf 的学习曲线相对较陡。你需要理解 Protobuf 的语法,学习如何编写 .proto 文件,并且需要了解如何使用 Protobuf 编译器生成代码。此外,你还需要理解 Protobuf 的版本兼容性规则。
    • JSON:JSON 的学习曲线相对较平。JSON 的语法非常简单,大多数人可以在很短的时间内掌握。此外,几乎所有的编程语言都内置了 JSON 的支持,你不需要安装任何额外的库就可以开始使用 JSON。
  6. 使用成本:
    • Protobuf:Protobuf 的使用成本相对较高。首先,你需要为每个数据结构编写一个 .proto 文件,然后使用 Protobuf 编译器生成代码。此外,如果你的数据结构发生了变化,你需要更新 .proto 文件并重新生成代码。这些步骤都需要额外的时间和工作。
    • JSON:JSON 的使用成本相对较低。你可以直接在代码中定义数据结构,无需任何额外的步骤。此外,如果你的数据结构发生了变化,你只需要更新你的代码,无需任何其他操作。

总的来说,Protobuf 和 JSON 各有优劣,适用于不同的场景。如果你需要高效的数据传输和严格的类型检查,那么 Protobuf 可能是一个好选择。如果你需要易于使用和人类可读的数据格式,那么 JSON 可能更适合你。

下面以一个简单的例子来对Protobuf和JSON运行效率进行简单对比。

定义proto文件

首先通过.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代码。

Benchmark

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: 恋水无意


Protobuf vs JSON的更多相关文章

  1. protobuf与json互相转换

    Java http://code.google.com/p/protobuf-java-format/ maven <dependency> <groupId>com.goog ...

  2. protobuf转json

    方法介绍 protobuf的介绍在这里就不详细介绍了,主要是俺也是刚接触,感兴趣的同学可以去搜索相关博客或者直接去看源码以及google的官方文档(官方文档表示很吃力)或者去这个网站:https:// ...

  3. protobuf与json相互转换的方法

    google的protobuf对象转json,不能直接使用FastJson之类的工具进行转换,原因是protobuf生成对象的get方法,返回的类型有byte[],而只有String类型可以作为jso ...

  4. protobuf与json转换

    protobuf对象不能直接使用jsonlib去转,因为protobuf生成的对象的get方法返回的类型有byte[],而只有String类型可以作为json的key,protobuf提供方法进行转换 ...

  5. protobuf json xml比较

    1 protobuf/xml/json对比 从数据的存储格式的角度进行对比 假如要存储一个键值对: {price:150} 1.1 protobuf的表示方式 message  Test { opti ...

  6. Protobuf有没有比JSON快5倍?用代码来击破pb性能神话

    转 http://www.sohu.com/a/136487507_505779 2017-04-26 07:58 程序设计 /58 /技术 导读:Google 的 Protocol Buffers ...

  7. Protobuf的简单介绍、使用和分析

      Protobuf的简单介绍.使用和分析   一.protobuf是什么? protobuf(Google Protocol Buffers)是Google提供一个具有高效的协议数据交换格式工具库( ...

  8. 通讯协议序列化解读(一) Protobuf详解教程

    前言:说到JSON可能大家很熟悉,是目前应用最广泛的一种序列化格式,它使用起来简单方便,而且拥有超高的可读性.但是在越来越多的应用场景里,JSON冗长的缺点导致它并不是一种最优的选择. 一.常用序列化 ...

  9. Android Protobuf应用及原理

    前言 之前一直忙于移动端日志SDK Trojan的开源工作,已十分稳定地运行在饿了么团队App中,集成了日志加密和解密功能.哎呀,允许我卖个狗皮膏药,不用不知道,用了就知道,从此爱不释手,Trojan ...

  10. Swoole http server + yaf, swoole socket server + protobuf 等小结

    拥抱swoole, 拥抱更好的php Swoole 是什么? Yaf 是什么? 接触swoole已经4年多了,一直没有好好静下心来学习.一直在做web端的应用,对网络协议和常驻内存型服务器一窍不通.一 ...

随机推荐

  1. 2022-04-08:在一张 无向 图上,节点编号0~N-1。老鼠开始在1节点,猫在2节点,0号节点是洞,老鼠想进洞, 老鼠第先出发,猫后出发,轮流行动。 在每个玩家的行动中,他们 必须 沿着图中与所

    2022-04-08:在一张 无向 图上,节点编号0~N-1.老鼠开始在1节点,猫在2节点,0号节点是洞,老鼠想进洞, 老鼠第先出发,猫后出发,轮流行动. 在每个玩家的行动中,他们 必须 沿着图中与所 ...

  2. 3 分钟利用 FastGPT 和 Laf 将 ChatGPT 接入企业微信

    原文链接:https://forum.laf.run/d/556 FastGPT 是一个超级的 ChatGPT 平台项目,功能非常强大: 集成了 ChatGPT.GPT4 和 Claude 可以使用任 ...

  3. drf——5个视图扩展类、9个视图子类、视图集、drf之路由

    5个视图扩展类 # 写5个类(不叫视图类 视图拓展类 需要配合GenericAPIView一起用) 每个类有一个方法 以后想写哪个接口 就继承哪个类即可 from rest_framework.res ...

  4. ConcurrentHashMap是如何实现的?

    众所周知 ConcurrentHashMap 是 HashMap 的多线程版本,HashMap 在并发操作时会有各种问题,比如死循环问题.数据覆盖等问题.而这些问题,只要使用 ConcurrentHa ...

  5. 在树莓派上使用numpy实现简单的神经网络推理,pytorch在服务器或PC上训练好模型保存成numpy格式的数据,推理在树莓派上加载模型

    这几天又在玩树莓派,先是搞了个物联网,又在尝试在树莓派上搞一些简单的神经网络,这次搞得是mlp识别mnist手写数字识别 训练代码在电脑上,cpu就能训练,很快的: 1 import torch 2 ...

  6. .Net全网最简RabbitMQ操作【强烈推荐】

    [前言] 本文自1年前的1.0版本推出以来,已被业界大量科技公司采用.同时也得到了.Net圈内多位大佬的关注+推荐,文章也被多家顶级.Net/C#公众号转载. 现在更新到了7.0版本,更好的服务各位. ...

  7. Java NIO原理 (Selector、Channel、Buffer、零拷贝、IO多路复用)

    系列文章目录和关于我 零丶背景 最近有很多想学的,像netty的使用.原理源码,但是苦于自己对于操作系统和nio了解不多,有点无从下手,遂学习之. 一丶网络io的过程 上图粗略描述了网络io的过程,了 ...

  8. global average pooling

    首先需要对深度网络中常见的pooling方式,以及全连接层有大致的了解.(此处略过不提.) paper: Network in Network fully connected layer 的缺点 在N ...

  9. C++面试八股文:override和finial关键字有什么作用?

    某日二师兄参加XXX科技公司的C++工程师开发岗位第22面: (二师兄好苦逼,节假日还在面试...) 面试官:C++的继承了解吗? 二师兄:(不好意思,你面到我的强项了..)了解一些. 面试官:什么是 ...

  10. mysql主从-主主架构设计

    前言: 1. mysql主从.主主复制应用场景很多,其原理主推,从定时根据binlog增量拉取更新 2. 如果主/从机器硬件负载过高,或者网络延迟就会造成同步延迟 3. 延迟是必然,mysql复制同步 ...