内容简介:LevelDB 源码分析(六):Arena
LevelDB 的简单的内存池,它所作的工作十分简单,申请内存时,将申请到的内存块放入 std::vector blocks_
中,在 Arena 的生命周期结束后,统一释放掉所有申请到的内存,内部结构如下图所示:
Arena 每次按 kBlockSize( static const int kBlockSize = 4096
) 单位向系统申请内存,提供地址对齐内存,记录内存使用。当 memtable 申请内存时,如果 size 不大于 kBlockSize 的四分之一,就在当前空闲的内存 block 中分配,否则,直接向系统申请。这个策略是为了更好的服务小内存的申请,避免个别大内存使用影响。
每次分配固定大小的block 然后在上面不断地进行切分。但是这里必须确保block内存大小足够大,不然不能够正常分配内存.
Arena 类除了构造函数和析构函数,只有3个公有的成员函数(Allocate, allocatedAligned, MemoryUsage),除此之外还有2个私有的成员函数(AllocateFallback 和 AllocateNewBlock)和4个成员变量。
arena.h
class Arena {
public:
Arena();
~Arena();
// 分配 "bytes" 个字节的内存块,并返回这个内存的指针
char* Allocate(size_t bytes);
// 利用 malloc 方式分配内存,正常对齐
char* AllocateAligned(size_t bytes);
// 返回由arena分配的数据所用的内存量
size_t MemoryUsage() const {
return reinterpret_cast<uintptr_t>(memory_usage_.NoBarrier_Load());
}
private:
char* AllocateFallback(size_t bytes); // 如果当前的block不够分配的话,那么需要new一个新的block.
char* AllocateNewBlock(size_t block_bytes); // new新的block逻辑.
// Allocation state
char* alloc_ptr_; // 每分配一个Block,记录当前可用的offset指针
size_t alloc_bytes_remaining_; // 当前还有多少连续的内存地址没有被分配掉
// 每次分配的内存都放入vector中
std::vector<char*> blocks_;
// arena所用的内存总量
port::AtomicPointer memory_usage_;
// 将拷贝构造函数及赋值构造函数设置为private,表示不运行这两个操作
Arena(const Arena&);
void operator=(const Arena&);
};
// 分配bytes大小的内存空间,返回分配的内存的指针
inline char* Arena::Allocate(size_t bytes) {
// The semantics of what to return are a bit messy if we allow
// 0-byte allocations, so we disallow them here (we don't need
// them for our internal use).
assert(bytes > 0);
if (bytes <= alloc_bytes_remaining_) { // 预先分配的内存是否满足当前需求
char* result = alloc_ptr_;
alloc_ptr_ += bytes;
alloc_bytes_remaining_ -= bytes;
return result;
}
return AllocateFallback(bytes); // 如果不满足,就像系统重新申请内存
}
arean.cc
Arena::Arena() : memory_usage_(0) {
alloc_ptr_ = NULL; // First allocation will allocate a block
alloc_bytes_remaining_ = 0;
}
//析构函数,释放内存
Arena::~Arena() {
for (size_t i = 0; i < blocks_.size(); i++) {
delete[] blocks_[i];
}
}
char* Arena::AllocateFallback(size_t bytes) {
// 当请求的内存超过kBlockSize的1/4时,直接分配,以免造成每次Block剩余内存不能利用,产生碎片
if (bytes > kBlockSize / 4) {
char* result = AllocateNewBlock(bytes);
return result;
}
// 如果请求分配的内存小于等于kBlockSize的1/4时,重新分配一个block的内存
// 这个时候会浪费当前Block中剩余的内存。
alloc_ptr_ = AllocateNewBlock(kBlockSize);
alloc_bytes_remaining_ = kBlockSize;
char* result = alloc_ptr_;
alloc_ptr_ += bytes;
alloc_bytes_remaining_ -= bytes;
return result;
}
// 分配bytes大小的内存空间,起始地址内存对齐(void*)
char* Arena::AllocateAligned(size_t bytes) {
const int align = (sizeof(void*) > 8) ? sizeof(void*) : 8; //32位系统下是4,当等于或超过64位系统时,是8
assert((align & (align-1)) == 0); // Pointer size should be a power of 2
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
result = AllocateFallback(bytes);
}
assert((reinterpret_cast<uintptr_t>(result) & (align-1)) == 0);
return result;
}
// 分配一个Block的内存,并放入vector中
char* Arena::AllocateNewBlock(size_t block_bytes) {
char* result = new char[block_bytes];
blocks_.push_back(result);
memory_usage_.NoBarrier_Store(reinterpret_cast<void*>(MemoryUsage() + block_bytes + sizeof(char*)));
return result;
}
从上面可以看到主要提供了两个申请函数:其中一个直接分配内存,另一个可以申请对齐的内存空间。Arena没有直接调用delete/free函数,而是在Arena的析构函数中统一释放所有的内存。
Arena实现的是粗粒度的内存池,每个Block内都可能产生剩余部分内存不能用的问题,且不存在中间释放内存和提供内存复用机制,不适用于在全局使用,且容易造成系统内存碎片。
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:- 以太坊源码分析(36)ethdb源码分析
- [源码分析] kubelet源码分析(一)之 NewKubeletCommand
- libmodbus源码分析(3)从机(服务端)功能源码分析
- [源码分析] nfs-client-provisioner源码分析
- [源码分析] kubelet源码分析(三)之 Pod的创建
- Spring事务源码分析专题(一)JdbcTemplate使用及源码分析
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Introduction to Linear Optimization
Dimitris Bertsimas、John N. Tsitsiklis / Athena Scientific / 1997-02-01 / USD 89.00
"The true merit of this book, however, lies in its pedagogical qualities which are so impressive..." "Throughout the book, the authors make serious efforts to give geometric and intuitive explanations......一起来看看 《Introduction to Linear Optimization》 这本书的介绍吧!