class Arena 是Level DB中的重要数据结构,它是一个简易的内存池管理类。
内存资源管理模型
Level DB 内存管理模型如图1所示,在内存分配上,Level DB每次预先申请KBlock大小的资源,新分配的内存请求会预先在last KBlocak的资源上进行划分。在大内存的分配上(> 1/4 KBlock Size),当无法从last KBloc上进行划分,会独立从堆空间直接申请资源。这样做可以最大限度的减少内存碎片,即内存碎片最大不会超过(1/4 KBlock Size)。
图1. Level DB资源管理模型
因为系统调用申请堆空间的资源还是很耗费时间的,对于小内存的处理可以有效的提高系统效率。
图2. Level DB资源分配流程
图2是Level DB资源分配的流程图。
代码细节
char* Arena::AllocateAligned(size_t bytes) {const int align = (sizeof(void*) > 8) ? sizeof(void*) : 8;//align & (align - 1) 消除低位的二进制bits中的1,如果align & (align - 1)) == 0,代表 //二进制bits中只有一个1,即align是2的指数的数字static_assert((align & (align - 1)) == 0,"Pointer size should be a power of 2");//align - alloc_ptr_ & (align - 1) 为了内存对齐,新申请指针需要额外申请的空间大小(slop)size_t current_mod = reinterpret_cast<uintptr_t>(alloc_ptr_) & (align - 1);size_t slop = (current_mod == 0 ? 0 : align - current_mod);size_t needed = bytes + slop;char* result;if (needed <= alloc_bytes_remaining_) {result = alloc_ptr_ + slop;alloc_ptr_ += needed;alloc_bytes_remaining_ -= needed;} else {// AllocateFallback always returned aligned memory//如果新申请内存,不需要计算slop,因为新申请的内存资源(pointer)是内存对齐的result = AllocateFallback(bytes);}assert((reinterpret_cast<uintptr_t>(result) & (align - 1)) == 0);return result;
}
安全问题
// TODO(costan): This member is accessed via atomics, but the others are// accessed without any locking. Is this OK?std::atomic<size_t> memory_usage_;
从上面这段注释可以看出整个class Arena还不是多线程安全的,因为里面的其他的member variable并没有(临界资源)安全保护。