标签:style blog http java 使用 os io strong
背景
我们都知道,对于一个高性能的服务器端程序来说,内存的使用非常重要。C++提供了new/delete来管理内存的申请和释放,但是对于小对象来说,直接使用new/delete代价比较大,要付出额外的空间和时间,性价比不高。
另外,我们也要避免多次的申请和释放引起的内存碎片。一旦碎片到达一定程度,即使剩余内存总量够用,但由于缺乏足够的连续空闲空间,导致内存不够用的假象。
c++ STL为了避免内存碎片,实现一个复杂的内存池,leveldb中则没有那么复杂,只是实现了一个"一次性"内存池Arena。
在leveldb里面,并不是所有的地方都使用了这个内存池,主要是memtable使用,主要是用于临时存放用户的更新数据,由于更新的数据可能很小,所以这里使用内存池就很合适。
原理
为了避免小对象的频繁分配,需要减少对new的调用,最简单的做法就是申请大块的内存,多次分给客户。
leveldb用一个vector<char *>来保存所有的内存分配记录,默认每次申请4k的内存,记录下剩余指针和剩余内存字节数,每当有新的申请,如果当前剩余的字节能满足需要,则直接返回给用户,如果不能,对于超过1k的请求,直接new返回,小于1K的请求,则申请一个新的4k块,从中分配一部分给用户。
但是这样的一个问题就是当前块剩余的部分就浪费了,改进的方法,针对每个block都记录剩余字节,这样就需要遍历来查找合适的block,要付出一些性能的代价。google的做法是浪费就浪费吧:-)
至于释放,需要释放整个内存池来释放所占内存,这个和leveldb的需求有关,memtable不需要释放单次内存,flush到硬盘后整个memtable销毁。
Arena.h
//z 2014-06-05 10:48:50 L.209‘47470 BG57IV3 T1840949363.K.F1370514324[T6,L108,R4,V118]
-
- #ifndef STORAGE_LEVELDB_UTIL_ARENA_H_
- #define STORAGE_LEVELDB_UTIL_ARENA_H_
-
- #include <cstddef>
- #include <vector>
- #include <assert.h>
- #include <stdint.h>
-
- namespace leveldb
- {
- class Arena
- {
- public:
- Arena();
- ~Arena();
-
-
- char* Allocate(size_t bytes);
-
-
- char* AllocateAligned(size_t bytes);
-
-
-
-
- size_t MemoryUsage() const
- {
- return blocks_memory_ + blocks_.capacity() * sizeof(char*);
- }
-
- private:
- char* AllocateFallback(size_t bytes);
- char* AllocateNewBlock(size_t block_bytes);
-
-
- char* alloc_ptr_;
- size_t alloc_bytes_remaining_;
-
-
- std::vector<char*> blocks_;
-
-
- size_t blocks_memory_;
-
-
- Arena(const Arena&);
- void operator=(const Arena&);
- };
-
- inline char* Arena::Allocate(size_t bytes)
- {
-
-
-
- assert(bytes > 0);
-
- if (bytes <= alloc_bytes_remaining_)
- {
- char* result = alloc_ptr_;
- alloc_ptr_ += bytes;
- alloc_bytes_remaining_ -= bytes;
- return result;
- }
-
-
-
-
- return AllocateFallback(bytes);
- }
-
- }
-
- #endif // STORAGE_LEVELDB_UTIL_ARENA_H_
//z 2014-06-05 10:48:50 L.209‘47470 BG57IV3 T1840949363.K.F1370514324[T6,L108,R4,V118]
arena.cc
-
- #include "util/arena.h"
- #include <assert.h>
-
- namespace leveldb {
-
- static const int kBlockSize = 4096;
-
-
- Arena::Arena() {
- blocks_memory_ = 0;
- alloc_ptr_ = NULL;
- alloc_bytes_remaining_ = 0;
- }
-
- Arena::~Arena() {
-
- for (size_t i = 0; i < blocks_.size(); i++) {
- delete[] blocks_[i];
- }
- }
-
- char* Arena::AllocateFallback(size_t bytes) {
-
- if (bytes > kBlockSize / 4) {
-
-
- char* result = AllocateNewBlock(bytes);
- return result;
- }
-
-
-
- alloc_ptr_ = AllocateNewBlock(kBlockSize);
- alloc_bytes_remaining_ = kBlockSize;
-
-
- char* result = alloc_ptr_;
-
- alloc_ptr_ += bytes;
-
- alloc_bytes_remaining_ -= bytes;
- return result;
- }
-
- char* Arena::AllocateAligned(size_t bytes) {
-
- const int align = sizeof(void*);
- assert((align & (align-1)) == 0);
-
- 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 {
-
-
-
- result = AllocateFallback(bytes);
- }
-
- assert((reinterpret_cast<uintptr_t>(result) & (align-1)) == 0);
- return result;
- }
-
-
- char* Arena::AllocateNewBlock(size_t block_bytes) {
- char* result = new char[block_bytes];
- blocks_memory_ += block_bytes;
- blocks_.push_back(result);
- return result;
- }
-
- }
//z 2014-06-05 10:48:50 L.209‘47470 BG57IV3 T1840949363.K.F1370514324[T6,L108,R4,V118]
leveldb Arena,布布扣,bubuko.com
leveldb Arena
标签:style blog http java 使用 os io strong
原文地址:http://www.cnblogs.com/shenzhaohai1989/p/3904808.html