在 Go 中使用 Protocol Buffers

各位准备好了吗!这一次,我们将深入探讨 Protocol Buffers(protobuf)及其在数据序列化中的超能力所在。

介绍

Protocol Buffers,也被称为 protobuf,是由谷歌开发的一种语言无关的二进制序列化格式。其主要目的是为了高效地序列化结构化数据,用于系统间通信和数据存储。

Protocol Buffers 的主要优势:

  1. 紧凑性:Protobuf 提供高效的序列化,生成较小的消息大小,提升带宽利用效率。
  2. 模式演进:Protobuf 支持模式演进而不破坏兼容性,允许对数据结构进行无缝更新。
  3. 高效的序列化和反序列化:Protobuf 提供快速高效的序列化,提升整体系统性能。
  4. 跨平台支持:Protobuf 允许不同平台和语言之间无缝交换数据。

这些优势使得 Protobuf 成为在 Go 应用程序中进行高效数据通信和存储的强大工具。

它比 JSON 和 XML 更好的地方:

XML,即可扩展标记语言,就像一张地图,用标签帮助组织和结构化数据。它以一种人类和机器都能理解的方式呈现信息。然而,XML 可能冗长并占用更多空间,这可能降低性能,使数据传输效率降低。

JSON,即 JavaScript 对象表示法,就像一个信使,使用简单的键值结构来表示数据对象。它因易于阅读和使用而在 Web 服务之间传输数据时变得流行。但 JSON 的基于文本的格式可能导致更大的文件大小,从而影响数据传输速度。

相比之下,Protocol Buffers(protobuf)在数据序列化领域脱颖而出。它就像一个魔术,将数据转换为紧凑高效的二进制格式。Protobuf 以快速的数据处理和适应变化的数据结构而闻名,并且在不破坏兼容性的情况下进行操作。它可以与不同的编程语言一起使用,并确保数据的可靠性。

总之,XML 和 JSON 各有用途,但如果您需要强大且高效的数据序列化解决方案,Protocol Buffer(protobuf)是首选。它提供紧凑性、速度、灵活性和兼容性,使其成为高效处理数据的首选方案。

在 Golang 中的序列化性能:Protocol Buffers vs. JSON

言归正传,让我们动手实践。

  1. 访问官方 Protocol Buffers GitHub 仓库(https://github.com/protocolbuffers/protobuf)下载与您操作系统兼容的编译器。
  2. 使用 .proto 文件格式定义一个 Protocol Buffers 消息模式。
protobuf 复制代码
syntax = "proto3";
package main;
option go_package = "/;msgmodel";

message MyMessage {
  int32 id = 1;
  string name = 2;
  string email = 3;
}
  1. 编译文件

protoc --- go_out=. ./*proto

这个命令从 protobuf 模式生成 Go 代码绑定。--go_out 标志指定输出应为 Go 语言。这将生成一个 msg.pb.go 文件,其中包含您的 protobuf 模式所需的代码绑定。

  1. 在 Golang 中实现一个基准测试,使用 protobuf 和 JSON 对大型数据集进行序列化。
go 复制代码
package main

import (
	"encoding/json"
	"github.com/golang/protobuf/proto"
	"go-protobuf/model/message"
	"log"
	"testing"
)

const (
	iteration = 10000000 //Number of iterations for the benchmark test
)

func generateDataset() []*message.MyMessage {
	var dataset []*message.MyMessage

	for i := 0; i < iteration; i++ {
		data := &message.MyMessage{
			Email: "johndoe@example.com",
			Name:  "John Doe",
			Id:    int32(i),
		}
		dataset = append(dataset, data)
	}

	return dataset
}

func BenchmarkProtobufSerialisation(b *testing.B) {
	dataset := generateDataset()

	b.ResetTimer()
	for n := 0; n < b.N; n++ {
		for _, data := range dataset {
			_, err := proto.Marshal(data)
			if err != nil {
				log.Fatal(err)
			}
		}
	}
}

func BenchmarkJSONSerialization(b *testing.B) {
	dataset := generateDataset()

	b.ResetTimer()
	for n := 0; n < b.N; n++ {
		for _, data := range dataset {
			_, err := json.Marshal(data)
			if err != nil {
				log.Fatal(err)
			}
		}
	}
}
func main() {
	// Run the benchmark tests
	testing.Benchmark(BenchmarkProtobufSerialisation)
	testing.Benchmark(BenchmarkJSONSerialization)
}
  1. 根据基准测试结果(如下所示),很明显,就速度而言,Protocol Buffers(Protobuf)的序列化性能优于 JSON。与 JSON 的序列化基准测试相比,Protobuf 的序列化基准测试完成时间明显较短。

内存性能比较:JSON vs. Protocol Buffers

  1. 在 Golang 中实现一个基准测试,比较使用 Protocol Buffers 和 JSON 处理大型数据集时的内存使用情况。
go 复制代码
package main

import (
	"encoding/json"
	"github.com/golang/protobuf/proto"
	"go-protobuf/model/message"
	"log"
	"runtime"
	"runtime/debug"
	"testing"
)

const (
	iteration = 100000000 //Number of iterations for the benchmark test
)

func generateDataset() []*message.MyMessage {
	var dataset []*message.MyMessage

	for i := 0; i < iteration; i++ {
		data := &message.MyMessage{
			Email: "johndoe@example.com",
			Name:  "John Doe",
			Id:    int32(i),
		}
		dataset = append(dataset, data)
	}

	return dataset
}

func BenchmarkProtobufSerialisation(b *testing.B) {
	dataset := generateDataset()

	b.ResetTimer()
	for n := 0; n < b.N; n++ {
		for _, data := range dataset {
			_, err := proto.Marshal(data)
			if err != nil {
				log.Fatal(err)
			}
		}
	}

	measureMemoryUsage(b)
}

func BenchmarkJSONSerialization(b *testing.B) {
	dataset := generateDataset()

	b.ResetTimer()
	for n := 0; n < b.N; n++ {
		for _, data := range dataset {
			_, err := json.Marshal(data)
			if err != nil {
				log.Fatal(err)
			}
		}
	}

	measureMemoryUsage(b)

}
func measureMemoryUsage(b *testing.B) {
	debug.FreeOSMemory()
	var mem runtime.MemStats
	runtime.GC()
	runtime.ReadMemStats(&mem)
	b.ReportMetric(float64(mem.Alloc)/1024/1024, "Memory_MB")
}

func main() {
	// Run the benchmark tests
	testing.Benchmark(BenchmarkProtobufSerialisation)
	testing.Benchmark(BenchmarkJSONSerialization)

}
  1. 尽管差异很小,但基准测试结果表明,与 Protobuf 序列化相比,JSON 序列化使用了更多的内存。平均而言,JSON 序列化消耗了约 0.2052 MB 的内存,而 Protobuf 序列化仅使用了约 0.2042 MB。尽管差异很小,但很明显 Protobuf 在内存使用方面更加高效。这意味着 Protobuf 的紧凑二进制格式有助于节省内存,使其成为处理大型数据集和提高性能的良好选择。

结论

现在是总结的时候了!!!

与在 Golang 中的 JSON 序列化相比,Protocol Buffers(protobuf)展现出了更优越的性能和内存效率。借助其紧凑的二进制格式和高效的序列化机制,protobuf 提供了更小的消息大小、提升了网络效率,并减少了带宽使用。此外,其模式演进能力允许对数据模型进行无缝更新。虽然 JSON 有其优势,但在需要高速和高内存效率的数据序列化场景中,protobuf 出类拔萃,实现了优化的数据传输和改善的系统性能。

相关推荐
侠客行031711 小时前
Mybatis连接池实现及池化模式
java·mybatis·源码阅读
蛇皮划水怪11 小时前
深入浅出LangChain4J
java·langchain·llm
较劲男子汉13 小时前
CANN Runtime零拷贝传输技术源码实战 彻底打通Host与Device的数据传输壁垒
运维·服务器·数据库·cann
灰子学技术13 小时前
go response.Body.close()导致连接异常处理
开发语言·后端·golang
老毛肚13 小时前
MyBatis体系结构与工作原理 上篇
java·mybatis
wypywyp13 小时前
8. ubuntu 虚拟机 linux 服务器 TCP/IP 概念辨析
linux·服务器·ubuntu
风流倜傥唐伯虎13 小时前
Spring Boot Jar包生产级启停脚本
java·运维·spring boot
Doro再努力13 小时前
【Linux操作系统10】Makefile深度解析:从依赖推导到有效编译
android·linux·运维·服务器·编辑器·vim
senijusene13 小时前
Linux软件编程:IO编程,标准IO(1)
linux·运维·服务器
不像程序员的程序媛13 小时前
Nginx日志切分
服务器·前端·nginx