ProtoBuf - Arena
1、概述
最近看 Protocal Buffer 的源码,初次见到这个库源自陈硕的 muduo ,便打算看一看,在此做一下记录。官网文档不能访问,只能凭借代码的自己理解,查看的源码版本为 3.6.0。
初识 Arena 时,发现是个 allocator。Arena 每次分配一大块内存,使用时在已经分配的内存块上获取,用来代替 new/delete 的堆上分配。通过一次申请大块内存,并且一次性释放,同时可取消调用对象的析构函数来提升效率。
Arena 线程安全:多个线程可并发在Arena分配空间。但销毁时非线程安全,销毁线程必须和Arena 的使用者同步。
2、特点
Arena 分配器使用 CreateMessage<T> 接口创建消息:
-类型 T 必须(至少)有两个构造函数:1 不含参数的构造函数,当在堆上分配时使用; 2 含 google::protobuf::Arena* 参数的构造函数,在Arena上分配时使用。当第二种情况传入空指针时,与第一种情况相同。
-类型 T 必须有特殊的特点:定义类型 |InternalArenaConstructable_|。一般被定义为 typedef void 类型。如果没有会在编译时报错。实现在 InternalHelper 模板类中,具体代码如下。
template <typename U>
static char ArenaConstructable(const typename U::InternalArenaConstructable_*);
template <typename U>
static double ArenaConstructable(...); typedef std::integral_constant<bool, sizeof(ArenaConstructable<T>(
static_cast<const T*>())) ==
sizeof(char)>
is_arena_constructable;
-类型T还 *可以* 有特征:| DestructorSkippable_|。如果该类型被定义,在传入非空 Arena指针时,对象的析构函数不会被调用。如果没有该特征,则在Arena销毁时,对象的析构函数一定会被调用。实现方法与上面类似。
template <typename U>
static char DestructorSkippable(const typename U::DestructorSkippable_*);
template <typename U>
static double DestructorSkippable(...); typedef std::integral_constant<
bool, sizeof(DestructorSkippable<T>(static_cast<const T*>())) ==
sizeof(char) ||
std::is_trivially_destructible<T>::value>
is_destructor_skippable;
在 proto 文件中, 设置 option cc_enable_arenas = true; 则使用 Arena 分配器。此时在使用 protoc 编译器生成 pb.h 的代码中会有 InternalArenaConstructable_ 和 DestructorSkippable_的定义,如
typedef void InternalArenaConstructable_;
typedef void DestructorSkippable_;
3、实现
Arena 的实现在 arena.h arena.cc arena_impl.h 中,同时还有专门的字符串域的实现在 arenastring.h 中。其中arena_impl 中是实现存储分配的核心代码,是arena中一个对象。
Arena 的内存结构如下图所示,图使用 Dia 绘制。每个线程都会分配一个Block,在Block上分配一个 SerialArena。Block是个链表结构,在空间分配时,如果该Block空间不够用,则新建一个Block,新Block的大小是旧Block的二倍,同时新Block的next指向旧 Block。一个线程在获取 Arena 时,如果该线程还没分配 Block,则申请一个Block,在该Block上分配 SerialArena,该SerialArena 的 next 指向上个线程的 SerialArena。

在 ArenaImpl 销毁时,首先进行 Cleanup,然后释放所有空间。Cleanup是根据添加的 Cleanup 表,顺序调用各个对象的 cleanup 函数,Cleanup 列表如下图所示。释放空间时会循环销毁每个 SerialArena 的所有 Block。

暂时先写到这里吧。
ProtoBuf - Arena的更多相关文章
- caffe编译环境的错误:..build_release/src/caffe/proto/caffe.pb.h:23:35: fatal error: google/protobuf/arena.h: 没有那个文件
在搭建caffe的环境时出现错误: .build_release/src/caffe/proto/caffe.pb.h:23:35: fatal error: google/protobuf/aren ...
- fatal error: google/protobuf/arena.h:没有那个文件或目录
安装caffe时make all会出现这个错误,按照https://github.com/BVLC/caffe/issues/4988说法,可能时libprotobuf-dev过时了,需要从源码重新变 ...
- 在UnrealEngine4中使用Google Protobuf
转自:https://blog.csdn.net/or_7r_ccl/article/details/54986393 在UnrealEngine4中使用Google Protobuf ...
- protobuf ubuntu 18.04环境下安装
(t20190518) luo@luo-All-Series:~/MyFile$ (t20190518) luo@luo-All-Series:~/MyFile$ (t20190518) luo@lu ...
- Proto3:Arena分配指南
Arena分配是仅C++有的功能,在使用Protocol Buffer时,它可以帮助你优化你的内存使用,提高性能.在.proto文件中启用Arena分配会在生成的C++代码中添加处理Arena分配的额 ...
- C++操作Kafka使用Protobuf进行跨语言数据交互
C++操作Kafka使用Protobuf进行跨语言数据交互 Kafka 是一种分布式的,基于发布 / 订阅的消息系统.主要设计目标如下: 以时间复杂度为 O(1) 的方式提供消息持久化能力,即使对 T ...
- [OpenCV] Install OpenCV 3.4 with DNN
目标定位 一.开始全面支持 Tensorflow OpenCV3.4 新功能 当前最新进展OpenCV 3.4 dev:https://github.com/opencv/opencv/tree/ma ...
- ubuntu18.04+ cuda9.0+opencv3.1+caffe-ssd安装
详细Ubuntu18.04,CUDA9.0,OpenCV3.1,Tensorflow完全配置指南 问题1:使用Cmake编译opencv源码 CMake Error: The following va ...
- 记intel杯比赛中各种bug与debug【其二】:intel caffe的使用和大坑
放弃使用pytorch,学习caffe 本文仅记录个人观点,不免存在许多错误 Caffe 学习 caffe模型生成需要如下步骤 编写network.prototxt 编写solver.prototxt ...
随机推荐
- MySQL 三种关联查询的方式: ON vs USING vs 传统风格
看看下面三个关联查询的 SQL 语句有何区别? 1SELECT * FROM film JOIN film_actor ON (film.film_id = film_actor.film_id) 2 ...
- RestTemplate中headers中添加Host不生效
在使用restTemplate访问内网接口时,不打算指host,支持ip访问,所以我们需要再header中指定host.但经调试,发现HttpURLConnection中Host无法覆盖.解决方案: ...
- (拓展欧几里得)51NOD 1256 乘法逆元
给出2个数M和N(M < N),且M与N互质,找出一个数K满足0 < K < N且K * M % N = 1,如果有多个满足条件的,输出最小的. 输入 输入2个数M, N中间用空 ...
- C++this详解
以前对this指针误解挺多的,在这里单独写一篇进行总结,有不对之处,欢迎指正批评! 一.问题 1.一个类中的不同对象在调用自己的成员函数时,其实它们调用的是同一段函数代码,那么成员函数如何知道要访问哪 ...
- 笔记——malloc、free、不同数据类型操作、.pyc文件、python安装第三方包、验证一个网站的所有链接有效性
C — malloc( ) and free( ) C 语言中使用malloc( )函数申请的内存空间,为什么一定要使用free释放? **malloc()函数功能:是从堆区申请一段连续的空间,函数结 ...
- redis的多实例
redis的多实例功能,可以在一个机器上,启动多个redis服务端 vim redis.conf ,写入以下内容(不要加上注释) port 6379 bind 0.0.0.0 daemonize no ...
- ural1076 Trash 垃圾
Description You were just hired as CEO of the local junkyard.One of your jobs is dealing with the in ...
- poj 3164 Command Network (朱刘算法)
题目链接: http://poj.org/problem?id=3164 题目大意: 有n个点(用坐标表示)各点编号分别为1—>n,m条单向路,问能否存在一个花费价值最小的网络,能使从1点到达任 ...
- HDU 6096 树套树
思路: 网上的题解有AC自动机的,有trie树的,还有(乱搞?)的 首先把输入的那n个串按照字典序排序, 把n个串翻转以后再按照字典序排序 这样我们发现, 查的前缀在字典序排序后是一段区间, 查的后缀 ...
- 有关LD_LIBRARY_PATH与ld.so.conf
我之前写过一篇关于LD_LIBRARY_PATH与gcc/g++ -L的关系的文章,于是我自己用CPACK制作了一个Debian安装包,然后我在/home/.bashrc里添加了export LD_L ...