Protocol Buffer Arena allocation
Arena是pb C++版本才有的特性。用來優化msg創建過程中對內存的使用。
pb版本需要3以上。
核心思想:預分配遲回收
好處:
- 減少內存分配回收的成本
- 緩解碎片對象問題,主要是這個目的
- 提高了緩存行的命中率
如何使用
需要在.proto文件中加上下面這行
option cc_enable_arenas = true;
proto在生成時,會為message類生成出arena相關的函數。
import時,也需要帶上該選項。
第一種 使用Arena
#include <google/protobuf/arena.h>
Arena arena;
MyMessage* msg= google::protobuf::Arena::CreateMessage<MyMessage>(&arena);
arena會分配一塊內存使用,不夠時采用倍增算法。
默認的初始分配大小是 256B ,最大分配大小是 8KB。每塊最大8K。
當arena生命周期結束時,會自動回收內存塊。
業務代碼不要delete msg這個指針。
可以通過
arena.SpaceAllocated()
接口獲取實際分配內存的大小。
可以通過
arena.SpaceUsed()
接口獲取實際使用內存的大小。
第二種 自定義內存塊
char m_arena_block[1 * 1024 * 1024] = {};
ArenaOptions options;
options.initial_block = m_arena_block;
options.initial_block_size = sizeof(m_arena_block);
Arena arena(options);
auto* message = Arena::CreateMessage<MyMessage>(&arena)
第一種由於不知道需要分配多大的內存,所以還是有可能會調用new。
一次性分配1M,足矣。
對於string類型和bytes類型,arena特性不生效。
不過,在3.16.0中已經有了ArenaString的實現。
- Do out-of-line allocation and deallocation of string object in ArenaString.
使用粒度
在大多數服務使用場景中,“arena-per-request”模式表現良好。
建議使用arena,大內存場景下,性能有顯著提高。
https://github.com/protocolbuffers/protobuf/issues/4327
https://github.com/protocolbuffers/protobuf/tree/3.16.x/src/google/protobuf