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字段,会按对象逐个去申请空间。

这种设计还有一个好处就是不会触发调用析构函数,如果采取 repeated Item 这种结构,会触发大量的析构函数,浪费 CPU 与 时间。(by chengyuxuan_yutian@163.com)

善用arena管理内存

  • arena对基础类型,比如int32, int64, float,double,bool等管理效率优化明显
  • arena不会管理string类型的内存申请(更高的版本已经支持,待验证)。

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

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

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

善用Any类型

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

善用浅拷贝机制(set_allocated_xxx/release)

CopyFrom是深拷贝,若要实现浅拷贝则可以通过 set_allocated_xxx/release 两个函数进行控制

结合arena使用浅拷贝机制(unsafe_arena_set_allocated)

set_allocated_xxx的风险在于,pb析构的时候会把元素也析构掉,无法重复利用。且在一些特殊场景,在无法控制pb析构而不能使用release函数。这些场景可能是pb的析构工作由框架控制,旧的代码封装层次太深等。

这种情况可以使用unsafe_arena_set_allocated_xxx 避开这个问题。

使用陷阱

不要有交叉依赖

举例一C++系统中,模块A依赖 PB;模块B依赖PB,而模块C依赖A和B。则编译模块C时一定要同时编译A、B、PB。

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

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

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

使用编号定位存储的字段

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

故障相关

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

一次内存泄露的故障排查

现象:

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

排查过程:

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

结果:

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

总结

protobuf释放的代价较大,不要全部的protobuf只放在一个线程操作。场景距离,lru cache的过期元素剔除。

https://www.cnblogs.com/zgwu/p/10403939.html

工程师文化&工匠精神名言名句

Scientists study the world as it is. Engineers create the world that has never been. –Theodore von Kármán

但尽管Google的核心算法出自冰雪聪明的工程师创新,但能否拧成一股绳才是公司持续发展的关键。

不要去做设计高手,只去做综合素质高手! –贝聿铭

知者创物,巧者述之守之,世谓之工。百工之事,皆圣人之作也。 –《考工记》

我亦无他,惟手熟尔。(欧阳修《卖油翁》)

打工的状态并不可怕,打工的心态很可怕。(付守永《工匠精神》)

人心惟危,道心惟微;惟精惟一,允执厥中。(《尚书·大禹谟》)

建于精诚,工于品质。–作者:宋杰

在长期实践中,我们培育形成了爱岗敬业、争创一流、艰苦奋斗、勇于创新、淡泊名利、甘于奉献的劳模精神,崇尚劳动、热爱劳动、辛勤劳动、诚实劳动的劳动精神,执着专注、精益求精、一丝不苟、追求卓越的工匠精神。劳模精神、劳动精神、工匠精神是以爱国主义为核心的民族精神和以改革创新为核心的时代精神的生动体现,是鼓舞全党全国各族人民风雨无阻、勇敢前进的强大精神动力。——《人民日报》2020年11月25日

劳动者素质对一个国家、一个民族发展至关重要。技术工人队伍是支撑中国制造、中国创造的重要基础,对推动经济高质量发展具有重要作用。要健全技能人才培养、使用、评价、激励制度,大力发展技工教育,大规模开展职业技能培训,加快培养大批高素质劳动者和技术技能人才。要在全社会弘扬精益求精的工匠精神,激励广大青年走技能成才、技能报国之路。——《人民日报》2019年9月24日

执着专注、精益求精、一丝不苟、追求卓越。(领导人讲话)