阅读Protobuf官网的一些笔记
阅读 Protobuf 官网的一些笔记
Protobuf API(The Protocol Buffer API)
- 每个字段都会有基本的
set_
get_
方法 string
类型的字段可以使用mutable_
方法来直接获得字符串的指针。- 如果是
optional
修饰的类型, 在没有对string类型赋值时也可以使用这个方法mutable_
方法,因为会帮我们自动初始化为empty string
。 - 可重复修改字段
Repeated fields
有特殊的方法:_size
- 获取字段特定的一位数字
- 更新现有的字段
add_
方法,可以添加新的值以便后面修改
通用的方法(Standard Message Methods)
bool IsInitialized() const;
(判断当前字段是否被初始化)string DebugString() const;
(转换为字符串的形式,方便调试查看)void CopyFrom(const Person& from);
(重写给定的消息结构)void Clear();
(清除所有元素,返回空)
序列化与反序列化(Parsing and Serialization
)
- 字符串形式:
bool SerializeToString(string* output) const;
bool ParseFromString(const string& data);
- 文件中持久化:
bool SerializeToOstream(ostream* output) const;
bool ParseFromIstream(istream* input);
google提到:
Protocol Buffers and O-O Design Protocol buffer classes are basically dumb data holders (like structs in C); they don't make good first class citizens in an object model. If you want to add richer behaviour to a generated class, the best way to do this is to wrap the generated protocol buffer class in an application-specific class. Wrapping protocol buffers is also a good idea if you don't have control over the design of the .proto file (if, say, you're reusing one from another project). In that case, you can use the wrapper class to craft an interface better suited to the unique environment of your application: hiding some data and methods, exposing convenience functions, etc. You should never add behaviour to the generated classes by inheriting from them. This will break internal mechanisms and is not good object-oriented practice anyway.
特别提到 Protobuf
是根据面向对象设计的设计理念来设计的。所以我们可以把面向对象设计的设计思路应用其中。
- 原生的
protobuf Message
功能是比较单一的,可以把protobuf
的结构化数据通过应用程序来进一步封装,达到功能更丰富的地步。
继承Protobuf数据结构(Extending a Protocol Buffer)
为了使Protobuf
拥有向前兼容,向后拓展的能力,需要按照如下做:
- 不可以改变标签的数字。因为这个是
Protobuf
在存储时的key
啊。 - 不可以添加或删除
required
修饰的字段 - 可以删除
optional
或repeated
字段 - 可以添加新的
optional
或repeated
修饰的字段,但是标签需要是唯一不冲突的。
从这里可以看到,Protobuf
在底层的存储方式是 Tag-Length-Value
,标识-长度-字段值。其中的Length
是可选的。
为了兼容和健壮,字段被删除或者更新时,对于应用程序来说是透明的(对于旧代码,已删除的可选字段将只有默认值,已删除的重复字段将为空。新代码还将透明地读取旧消息),最好是在定义字段最后加上默认值,并且是在使用时先通过 has_
方法 来判断该字段是否存在。
- 默认值
string(NULL)
booleans(false)
number(0)
优化建议(Optimization Tips)
Protobuf
已经被极度优化过了,所以才有如今的这么高效,但是还可以提供下面几个建议达到更优:
尽可能复用消息对象。即使在清除内存时,消息依然保留分配给它们的任何内存,以便将来复用。因此,如果正在连续处理许多具有相同类型和类似结构的消息,那么最好每次复用相同的消息对象,以减轻内存分配器的负载。然而,随着时间的推移,对象可能会变得膨胀,特别是当您的消息在“形状”上发生变化时,或者如果您偶尔构造一个比通常大得多的消息时。您应该通过调用
SpaceUsed
方法来监视消息对象的大小,并在达到某个大小时强制删除对象释放内存。
系统默认的内存分配器通过多个线程分配大量小对象时优化可能不太好,可以尝试使用
tcmalloc
代替。
高级用法(Advanced Usage)
Protobuf
的一个关键特性是反射。我们可以遍历消息的字段并操作它们的值,而无需针对任何特定的消息类型编写代码。
使用反射的一种非常有用的方法是将Protobuf
消息格式转换为其他编码(如XML
或JSON
)。
反射更高级的用途可能是查找同一类型的两个消息之间的差异,或者开发一种“协议消息正则表达式”,可以在其中编写匹配特定消息内容的表达式。这样就可以实现动态的修改消息结构,达到运行时修改协议类型。
阅读Protobuf官网的一些笔记的更多相关文章
- 你会阅读appium官网文档吗
高效学习appium第一步,学会查看appium官方文档.如果能把appium文档都通读一遍,对学习appium大有益处. 而能做到通读appium官方文档的人,想必不是很多,刚开始学习appium的 ...
- 公司官网建站笔记(一):腾讯云服务器装CentOS8.2系统、重置密码、远程ssh登陆、sftp传递文件以及新建开发者账户
前言 本篇使用的是腾讯云服务器,讲解了部署安装服务器CentOS8.2系统,重置密码,添加用户,远程登陆,远程传递文件等基本流程. 前提条件 购买了腾讯云服务器,如下图: 云服务器 ...
- 【工利其器】必会工具之(二)Android开发者官网篇
前言 当刚开始踏入Android程序员这个行业的时候,想必绝大多数的人都和笔者一样,热血沸腾,激情四射,买了很多讲解Android开发的书籍.当开发某个功能需要学习某方面知识的时候,大家又成了“面向百 ...
- 超细讲解Django打造大型企业官网
本文为知了课堂黄勇老师讲的<超细讲解Django打造大型企业官网>的笔记. 第一章 Django预热 1.创建virtualenv虚拟环境 2.URL组成部分详解 3.Django介绍 4 ...
- 后端——框架——容器框架——spring_core——《官网》阅读笔记——初篇
1.知识体系 spring-core的知识点大概分为以下几个部分 IOC容器 Bean的配置,XML方式和注解方式 Bean的管理,bean的生命周期,bean的作用域等等 与Bean相关联的接口和对 ...
- 官网实例详解-目录和实例简介-keras学习笔记四
官网实例详解-目录和实例简介-keras学习笔记四 2018-06-11 10:36:18 wyx100 阅读数 4193更多 分类专栏: 人工智能 python 深度学习 keras 版权声明: ...
- Spring官网阅读 | 总结篇
接近用了4个多月的时间,完成了整个<Spring官网阅读>系列的文章,本文主要对本系列所有的文章做一个总结,同时也将所有的目录汇总成一篇文章方便各位读者来阅读. 下面这张图是我整个的写作大 ...
- Spring官网阅读(十八)Spring中的AOP
文章目录 什么是AOP AOP中的核心概念 切面 连接点 通知 切点 引入 目标对象 代理对象 织入 Spring中如何使用AOP 1.开启AOP 2.申明切面 3.申明切点 切点表达式 excecu ...
- Spring官网阅读(十六)Spring中的数据绑定
文章目录 DataBinder UML类图 使用示例 源码分析 bind方法 doBind方法 applyPropertyValues方法 获取一个属性访问器 通过属性访问器直接set属性值 1.se ...
随机推荐
- [Selenium]等待元素出现之后再消失,界面上的loading icon都属于这种类型,之前的方法总是卡死,换这种方法目前还好用的
等待元素出现之后再消失,界面上的loading icon都属于这种类型,之前的方法总是卡死,换这种方法目前还好用的 /** * Check if the element present with cu ...
- UI / UX设计师如何玩转用户心理学原理?
以下内容由Mockplus团队翻译整理,仅供学习交流,Mockplus是更快更简单的原型设计工具. 众所周知,心理学在APP的用户体验设计中起着非常重要的作用.通过了解我们的设计是如何被感知的,我们可 ...
- MDK5使用技巧
1.文本美化 修改 修改字体以及颜色如下: 修改用户自定义的关键字,如下: 代码编辑技巧 1.TAB键的妙用 使用TAB键可以整体向右移动相应位,使用SHIFT+TAB键整体左移相应位. 2.快速定位 ...
- 我们常说的CDN到底是什么?
程序员每天提及的无数词当中,有一个是「CDN」,Ta的中文名是「内容分发网络」,读中文是令人蒙逼的,英文名是Content Delivery Network. CDN有啥用呢?它主要用来解决什么问题呢 ...
- Servlet.service() for servlet UserServlet threw exception java.lang.NullPointerException 空指针异常
错误付现: 严重: Servlet.service() for servlet UserServlet threw exceptionjava.lang.NullPointerException at ...
- RECONSUME_LATER
Failure consumption,later try to consume. ================MessageExt [queueId=0, storeSize=134, queu ...
- vue 使用axios 数据请求第三方插件的使用
axios 基于http客户端的promise,面向浏览器和nodejs 特色 浏览器端发起XMLHttpRequests请求 node端发起http请求 支持Promise API 监听请求和返回 ...
- 如何在Windows环境下安装Linux系统虚拟机
如何在Windows环境下安装Linux系统虚拟机 本篇经验写给想要入门学习C语言的小白们.Windows系统因为使用窗口图形化,操作简单,功能多样,所以我们在Windows环境下可以做到很多,但想要 ...
- Thread.sleep() 和 Thread.yield() 区别
1. Thread.yield(): api中解释: 暂停当前正在执行的线程对象,并执行其他线程. 注意:这里的其他也包含当前线程,所以会出现以下结果. public class Test exten ...
- Task的运行原理和工作窃取(work stealing)
在net4.0以前,当调用ThreadPool.QueueUserWorkItem方法往线程池中插入作业时,会把作业内容(其实就是一个委托)放到线程池中的一个全局队列中,然后线程池中的线程按照先进先出 ...