目录
引言
这是我关于Google leveldb的第一篇源码解读系列,我不会对所有源码进行解读,但我尽量保证讲到的点都比较清楚(在精不在多嘛)。
leveldb中的Arena是一个简单的、一次性的内存池的实现,它不像《STL源码剖析》中的内存池那样复杂、容错性强,因为它主要用于Memtable这种不断增加空间、空间满了之后一并存入SST的场景,因此它也是不支持手动调用Delete操作,由析构函数一起调用。
成员变量
// Allocation state
char* alloc_ptr_;
size_t alloc_bytes_remaining_;
// Array of new[] allocated memory blocks
std::vector<char*> blocks_;
// Total memory usage of the arena.
std::atomic<size_t> memory_usage_;
Arena主体部分是一个std::vector<char*>,它用于管理所有分配的内存块。
alloc_ptr_和alloc_bytes_remaining_都是当前正在使用的内存块的状态变量,用于指明可用内存的起点和剩余空间。
memory_usage_则是一个原子变量,用于在高并发场景下统计总体内存使用大小。
除此之外,Arena没有任何其他多余的成员变量,因为它是一次性的,并且存在一定浪费的,这点我们在文章后面讨论。
于是Arena大概长这样:

啥?这图画的居然还一长一短的,并且使用到的内存块居然不是最后一块,为什么呢,我们继续往下看吧!
MemoryUsage
Arena提供三大接口:Allocate、AllocateAligned和MemoryUsage。
我们将从最简单的MemoryUsage讲起。
// Returns an estimate of the total memory usage of data allocated
// by the arena.
size_t MemoryUsage() const {
return memory_usage_.load(std::memory_order_relaxed);
}
由于没有deallocate操作,memory_usage_是只增不减的,增幅为block_bytes + sizeof(char*),其中sizeof(char*)被认为是vector中一个指针大小。
std::memory_order_relaxed只保证操作是原子的,但多核同步顺序是“relaxed”的,并不像std::memory_order_acquire和std::memory_order_release那样有更强的保证,感兴趣可以了解一下。
~Arena
// 需求:memtable不需要单次释放内存
Arena::~Arena() {
for (size_t i = 0; i < blocks_.size(); i++) {
delete[] blocks_[i];
}

本文详细解读了leveldb中的 Arena 内存池,介绍了其内存分配接口、字节对齐逻辑以及优点和缺点。重点剖析了AllocateAligned函数,涉及内存对齐原理和优化策略。

2183

被折叠的 条评论
为什么被折叠?



