当前位置: 首页 > news >正文

Google protobuf使用技巧和经验总结

技巧 & 经验

性能优化

把repeated message结构尽可能摊平为基础类型的repeated字段

基础类型的repeated字段,包含 repeated int32, int64, float,double,bool等,但不包含string、bytes、message

比如:

message Item {
    int32 id = 1;
    int32 score = 2;
}

message R {
    repeated Item items = 1;
}

改为下面的设计,会提升序列化和反序列效率

message R {
    repeated int32 item_id = 1;
    repeated int32 item_score = 2;
}

原理是非string的基础类型的repeated字段,在申请内存时pb会申请连续线性大块内存,效率高;而message 的repeated字段,会按对象逐个去申请空间。

善用arena管理内存

  • arena对基础类型,比如int32, int64, float,double,bool等管理效率优化明显
  • arena不会管理字符串类型的内存申请。

用固定长度repeated uint32 替换字符串

字符串是一种不定长的数据结构,内存管理方式成本较高。通过转换成repeated uint32类型,则可以获得更高效的管理。

除此之外,repeated uint32 也支持由arena管理。

善用Any类型

假设3个网络服务的调用关系如下:
A->B->C。
其中存在某些pb结构仅会由B透传给C,而B不需要解析,则可以把这些pb放入定义为any类型的字段中。

利用protobuf一些特性来规避陷阱

良好的可扩展性 & 保留未定义字段

良好的可扩展性使得protobuf更好地向后兼容。上游更新了proto,新增字段,下游虽然没有更新proto文件,但是新增的字段依然可以保留,来自上游的字段可以透传给下游。拼接下游请求的结构pb时,尽可能使用CopyFrom,避免把字段逐个set。

使用编号定位存储的字段

为了更好地向后兼容,应该避免修改proto文件中现有字段的名字、类型。需要修改时,通过追加新字段(字段编号增加),弃用旧字段的方式。

故障相关

protobuf被广泛使用,饱经业界考验,如果遇到问题,绝大多数还是自身软件设计的问题。遇到问题,首先不应该怀疑protobuf,应该把视角集中到去发现自身的系统设计缺陷中。

一次内存泄露的故障排查

现象:

公司里一个c++网络服务中, PV较低时没有内存泄露;而PV较高,cpu idle降到30%以下,开始内存泄露,直到OOM。

排查过程:

用了 tcmalloc和gperf,逐步定位是protobuf 申请 repeated字段的空间,没有及时释放。repeated字段约1k~1w的规模。然后逐步缩小范围。

结果:

竟然是释放内存,都放到了一个线程中。当流量大时,单个线程计算能力成为瓶颈,内存释放变慢,表现为内存泄漏。


转载请注明来源,原地址保持持续更新。
博客首页:作程的技术博客
文章标题:《Google protobuf使用技巧和经验总结》
本文链接:https://it.zuocheng.net/google-protobuf-skills-experience-zh

相关文章:

  • Kotlin协程:Flow基础原理
  • linux格式化输入输出
  • 一篇文章告诉你,为什么必须要学Excel?
  • Intellij IDEA--Undo Commit,Revert Commit,Drop Commit的区别
  • 三个工厂模式(通俗易懂)
  • 本地环境下启动openFaas创建的Java的云函数
  • Java 第三阶段增强分析需求,代码实现能力【正则表达式】
  • Java基础【理解版】
  • 《Mycat分布式数据库架构》之搭建详解
  • Opencv项目实战:02 角度探测器
  • OSPF —— 多区域部署 + ABR + ASBR + 路由重分发
  • 猿创征文|JVM之图解垃圾收集器2-Shenandoah和ZGC
  • springboot+安卓app电子阅览室系统毕业设计源码016514
  • 第04章 第04章 队列
  • 智慧工业+数字孪生,打造智慧设备运维最优解
  • php的引用
  • Consul Config 使用Git做版本控制的实现
  • Docker容器管理
  • Java超时控制的实现
  • js
  • Netty源码解析1-Buffer
  • Python学习笔记 字符串拼接
  • redis学习笔记(三):列表、集合、有序集合
  • Sublime Text 2/3 绑定Eclipse快捷键
  • Vue2.x学习三:事件处理生命周期钩子
  • 半理解系列--Promise的进化史
  • 名企6年Java程序员的工作总结,写给在迷茫中的你!
  • 七牛云 DV OV EV SSL 证书上线,限时折扣低至 6.75 折!
  • 如何将自己的网站分享到QQ空间,微信,微博等等
  • 如何使用Mybatis第三方插件--PageHelper实现分页操作
  • 吐槽Javascript系列二:数组中的splice和slice方法
  • 一起来学SpringBoot | 第三篇:SpringBoot日志配置
  • ​Spring Boot 分片上传文件
  • ​你们这样子,耽误我的工作进度怎么办?
  • ​人工智能之父图灵诞辰纪念日,一起来看最受读者欢迎的AI技术好书
  • ​用户画像从0到100的构建思路
  • ###C语言程序设计-----C语言学习(3)#
  • (Java岗)秋招打卡!一本学历拿下美团、阿里、快手、米哈游offer
  • (js)循环条件满足时终止循环
  • (第8天)保姆级 PL/SQL Developer 安装与配置
  • (规划)24届春招和25届暑假实习路线准备规划
  • (汇总)os模块以及shutil模块对文件的操作
  • (接口自动化)Python3操作MySQL数据库
  • (转) SpringBoot:使用spring-boot-devtools进行热部署以及不生效的问题解决
  • (转)四层和七层负载均衡的区别
  • (转)我也是一只IT小小鸟
  • .NET C#版本和.NET版本以及VS版本的对应关系
  • .NET MVC第三章、三种传值方式
  • .NET 跨平台图形库 SkiaSharp 基础应用
  • .net/c# memcached 获取所有缓存键(keys)
  • .NetCore实践篇:分布式监控Zipkin持久化之殇
  • @manytomany 保存后数据被删除_[Windows] 数据恢复软件RStudio v8.14.179675 便携特别版...
  • [ vulhub漏洞复现篇 ] Grafana任意文件读取漏洞CVE-2021-43798
  • [20171101]rman to destination.txt
  • [20171113]修改表结构删除列相关问题4.txt