目录:
1.c语言内存池实现
2.C语言内存池
3.c++实现内存池
4.C++内存池的设计和实现
5.c# 内存池
6.C++ 实现高性能内存池
7.c++内存池
8.c语言进程池
9.内存池的实现原理
10.c语言实现线程池
1.c语言内存池实现
一、为什么需要使用内存池在C/C++中我们通常使用malloc,free或new,delete来动态分配内存一方面,因为这些函数涉及到了系统调用,所以频繁的调用必然会导致程序性能的损耗;另一方面,频繁的分配和释放小块内存会导致大量的内存碎片的产生,当碎片积累到一定的量之后,将无法分配到连续的内存空间,系统不得不进行碎片整理来满足分配到连续的空间,这样不仅会导致系统性能损耗,而且会导致程序对内存的利用率低下。
2.C语言内存池
当然,如果我们的程序不需要频繁的分配和释放小块内存,那就没有使用内存池的必要,直接使用malloc,free或new,delete函数即可二、内存池的实现方案内存池的实现原理大致如下:提前申请一块大内存由内存池自己管理,并分成小片供给程序使用。
3.c++实现内存池
程序使用完之后将内存归还到内存池中(并没有真正的从系统释放),当程序再次从内存池中请求内存时,内存池将池子中的可用内存片返回给程序使用我们在设计内存池的实现方案时,需要考虑到以下问题:内存池是否可以自动增长?
4.C++内存池的设计和实现
如果内存池的最大空间是固定的(也就是非自动增长),那么当内存池中的内存被请求完之后,程序就无法再次从内存池请求到内存所以需要根据程序对内存的实际使用情况来确定是否需要自动增长内存池的总内存占用是否只增不减?。
5.c# 内存池
如果内存池是自动增长的,就涉及到了“内存池的总内存占用是否是只增不减”这个问题了试想,程序从一个自动增长的内存池中请求了1000个大小为100KB的内存片,并在使用完之后全部归还给了内存池,而且假设程序之后的逻辑最多之后请求10个100KB的内存片,那么该内存池中的900个100KB的内存片就一直处于闲置状态,程序的内存占用就一直不会降下来。
6.C++ 实现高性能内存池
对内存占用大小有要求的程序需要考虑到这一点内存池中内存片的大小是否固定?如果每次从内存池中的请求的内存片的大小如果不固定,那么内存池中的每个可用内存片的大小就不一致,程序再次请求内存片的时候,内存池就需要在“匹配最佳大小的内存片”和“匹配操作时间”上作出衡量。
7.c++内存池
“最佳大小的内存片”虽然可以减少内存的浪费,但可能会导致“匹配时间”变长内存池是否是线程安全的?是否允许在多个线程中同时从同一个内存池中请求和归还内存片?这个线程安全可以由内存池来实现,也可以由使用者来保证。
8.c语言进程池
内存片分配出去之前和归还到内存池之后,其中的内容是否需要被清除?程序可能出现将内存片归还给内存池之后,仍然使用内存片的地址指针进行内存读写操作,这样就会导致不可预期的结果将内容清零只能尽量的(也不一定能)将问题抛出来,但并不能解决任何问题,而且将内容清零会消耗一定的CPU时间。
9.内存池的实现原理
所以,最终最好还是需要由内存池的使用者来保证这种安全性是否兼容std::allocator?STL标准库中的大多类都支持用户提供一个自定义的内存分配器,默认使用的是std::allocator,如std::string:
10.c语言实现线程池
typedef basic_string string;如果我们的内存池兼容std::allocator,那么我们就可以使用我们自己的内存池来替换默认的std::allocator分配器,如:
typedef basic_string mystring;更多Linux内核视频教程资料文档私信【内核大礼包】自行获取。
三、内存池的具体实现计划实现一个内存池管理的类MemoryPool,它具有如下特性:内存池的总大小自动增长内存池中内存片的大小固定支持线程安全在内存片被归还之后,清除其中的内容兼容std::allocator。
因为内存池的内存片的大小是固定的,不涉及到需要匹配最合适大小的内存片,由于会频繁的进行插入、移除的操作,但查找比较少,故选用链表数据结构来管理内存池中的内存片MemoryPool中有2个链表,它们都是双向链表(设计成双向链表主要是为了在移除指定元素时,能够快速定位该元素的前后元素,从而在该元素被移除后,将其前后元素连接起来,保证链表的完整性):。
data_element_ 记录以及分配出去的内存片free_element_ 记录未被分配出去的内存片MemoryPool实现代码代码中使用了std::mutex等C++11才支持的特性,所以需要编译器最低支持C++11:。
#ifndef PPX_BASE_MEMORY_POOL_H_#define PPX_BASE_MEMORY_POOL_H_#include#include#include
namespace ppx { namespace base { template
ZeroOnDeallocate = true> class MemoryPool { public: /* Member types */typedef
T value_type; typedef T* pointer; typedef T& reference;
typedefconst T* const_pointer; typedefconst T& const_reference;
typedefsize_t size_type; typedefptrdiff_t difference_type; typedef
std::false_type propagate_on_container_copy_assignment; typedefstd::true_type propagate_on_container_move_assignment;
typedefstd::true_type propagate_on_container_swap; template structrebind {
typedef MemoryPool other; }; /* Member functions */ MemoryPool()
noexcept; MemoryPool(const MemoryPool& memoryPool) noexcept; MemoryPool(MemoryPool&& memoryPool)
noexcept; template MemoryPool(constMemoryPool& memoryPool) noexcept; ~MemoryPool()
noexcept; MemoryPool& operator=(const MemoryPool& memoryPool) = delete; MemoryPool&
operator=(MemoryPool&& memoryPool) noexcept; pointer address(reference x)constnoexcept;
const_pointer address(const_reference x)constnoexcept; // Can only allocate one object at a time. n and hint are ignored
pointer allocate(size_type n = 1, const_pointer hint = 0); voiddeallocate(pointer p, size_type n =
1); size_type max_size()constnoexcept; template void
construct(U* p, Args&&… args);template voiddestroy(U* p);template pointernewElement
(Args&&… args);voiddeleteElement(pointer p); private: structElement_ { Element_* pre; Element_* next; };
typedefchar* data_pointer; typedef Element_ element_type; typedef Element_* element_pointer; element_pointer data_element_; element_pointer free_element_;
std::recursive_mutex m_; size_type padPointer(data_pointer p, size_type align)constnoexcept
; voidallocateBlock(); static_assert(BlockSize >= 2 * sizeof(element_type),
“BlockSize too small.”); }; template
inlinetypename MemoryPool::size_type MemoryPool::padPointer(data_pointer p, size_type align)
constnoexcept { uintptr_t result = reinterpret_cast(p); return ((align – result) % align); }
template MemoryPool::MemoryPool()
noexcept { data_element_ = nullptr; free_element_ = nullptr; }
template MemoryPool::MemoryPool(
const MemoryPool& memoryPool) noexcept : MemoryPool() { } template
MemoryPool::MemoryPool(MemoryPool&& memoryPool)
noexcept { std::lock_guard lock(m_); data_element_ = memoryPool.data_element_; memoryPool.data_element_ =
nullptr; free_element_ = memoryPool.free_element_; memoryPool.free_element_ =
nullptr; } template template
MemoryPool::MemoryPool(const MemoryPool& memoryPool)
noexcept : MemoryPool() { } template
ZeroOnDeallocate> MemoryPool& MemoryPool::
operator=(MemoryPool&& memoryPool) noexcept { std::lock_guard lock(m_);
if (this != &memoryPool) { std::swap(data_element_, memoryPool.data_element_);
std::swap(free_element_, memoryPool.free_element_); } return *this; }
template MemoryPool::~MemoryPool()
noexcept { std::lock_guard lock(m_); element_pointer curr = data_element_;
while (curr != nullptr) { element_pointer prev = curr->next; operator
delete(reinterpret_cast(curr)); curr = prev; } curr = free_element_;
while (curr != nullptr) { element_pointer prev = curr->next; operator
delete(reinterpret_cast(curr)); curr = prev; } }
template inlinetypename MemoryPool::pointer MemoryPool::address(reference x)
constnoexcept { return &x; } template
ZeroOnDeallocate> inlinetypename MemoryPool::const_pointer MemoryPool::address(const_reference x)
constnoexcept { return &x; } template
ZeroOnDeallocate> void MemoryPool::allocateBlock() {
// Allocate space for the new block and store a pointer to the previous one data_pointer new_block =
reinterpret_cast (operatornew(BlockSize)); element_pointer new_ele_pointer =
reinterpret_cast(new_block); new_ele_pointer->pre = nullptr; new_ele_pointer->next =
nullptr; if (data_element_) { data_element_->pre = new_ele_pointer; } new_ele_pointer->next = data_element_; data_element_ = new_ele_pointer; }
template inlinetypename MemoryPool::pointer MemoryPool::allocate(size_type n, const_pointer hint) {
std::lock_guard lock(m_); if (free_element_ != nullptr) { data_pointer body =
reinterpret_cast(reinterpret_cast(free_element_) + sizeof(element_type)); size_type bodyPadding = padPointer(body,
alignof(element_type)); pointer result = reinterpret_cast(reinterpret_cast(body + bodyPadding)); element_pointer tmp = free_element_; free_element_ = free_element_->next;
if (free_element_) free_element_->pre = nullptr; tmp->next = data_element_;
if (data_element_) data_element_->pre = tmp; tmp->pre = nullptr; data_element_ = tmp;
return result; } else { allocateBlock(); data_pointer body =
reinterpret_cast(reinterpret_cast(data_element_) + sizeof(element_type)); size_type bodyPadding = padPointer(body,
alignof(element_type)); pointer result = reinterpret_cast(reinterpret_cast(body + bodyPadding));
return result; } } template
inlinevoid MemoryPool::deallocate(pointer p, size_type n) {
std::lock_guard lock(m_); if (p != nullptr) { element_pointer ele_p =
reinterpret_cast(reinterpret_cast(p) – sizeof(element_type));
if (ZeroOnDeallocate) { memset(reinterpret_cast(p), 0, BlockSize –
sizeof(element_type)); } if (ele_p->pre) { ele_p->pre->next = ele_p->next; }
if (ele_p->next) { ele_p->next->pre = ele_p->pre; }
if (ele_p->pre == nullptr) { data_element_ = ele_p->next; } ele_p->pre =
nullptr; if (free_element_) { ele_p->next = free_element_; free_element_->pre = ele_p; }
else { ele_p->next = nullptr; } free_element_ = ele_p; } }
template inlinetypename MemoryPool::size_type MemoryPool::max_size()
constnoexcept { size_type maxBlocks = -1 / BlockSize; return (BlockSize – sizeof
(data_pointer)) / sizeof(element_type) * maxBlocks; } template
bool ZeroOnDeallocate> template inlinevoidMemoryPool:
:construct(U* p, Args&&… args) { new (p) U(std::forward(args)…); }
template template inline
voidMemoryPool::destroy(U* p) { p->~U(); }
template template
inlinetypenameMemoryPool::pointer MemoryPool::newElement(Args&&… args) {
std::lock_guard lock(m_); pointer result = allocate(); construct(result,
std::forward(args)…); return result; } template
BlockSize, bool ZeroOnDeallocate> inlinevoid MemoryPool::deleteElement(pointer p) {
std::lock_guard lock(m_); if (p != nullptr) { p->~value_type(); deallocate(p); } } } }
#endif// PPX_BASE_MEMORY_POOL_H_使用示例:#include#includeusingnamespacestd; classApple
{public: Apple() { id_ = 0; cout << “Apple()” << endl; } Apple(int id) { id_ = id;
cout << “Apple(” << id_ << “)” << endl; } ~Apple() { cout << “~Apple()” << endl; }
voidSetId(int id){ id_ = id; } intGetId(){ return id_; } private: int
id_; }; voidThreadProc(ppx::base::MemoryPool *mp){ int i = 0; while (i++ < 100000) {
char* p0 = (char*)mp->allocate(); char* p1 = (char*)mp->allocate(); mp->deallocate(p0);
char* p2 = (char*)mp->allocate(); mp->deallocate(p1); mp->deallocate(p2); } }
intmain(){ ppx::base::MemoryPool mp; int i = 0; while (i++ < 100000) { char
* p0 = (char*)mp.allocate(); char* p1 = (char*)mp.allocate(); mp.deallocate(p0);
char* p2 = (char*)mp.allocate(); mp.deallocate(p1); mp.deallocate(p2); }
std::thread th0(ThreadProc, &mp); std::thread th1(ThreadProc, &mp); std::thread th2(ThreadProc, &mp)
; th0.join(); th1.join(); th2.join(); Apple *apple = nullptr; { ppx::base::MemoryPool mp2; apple = mp2.newElement(
10); int a = apple->GetId(); apple->SetId(10); a = apple->GetId(); mp2.deleteElement(apple); } apple->SetId(
12); int b = -4 % 4; int *a = nullptr; { ppx::base::MemoryPool mp3; a = mp3.allocate(); *a =
100; //mp3.deallocate(a);int *b = mp3.allocate(); *b = 200; //mp3.deallocate(b);
mp3.deallocate(a); mp3.deallocate(b); int *c = mp3.allocate(); *c =
300; } getchar(); return0; }
2. 分享目的仅供大家学习和交流,您必须在下载后24小时内删除!
3. 不得使用于非法商业用途,不得违反国家法律。否则后果自负!
4. 本站提供的源码、模板、插件等等其他资源,都不包含技术服务请大家谅解!
5. 如有链接无法下载、失效或广告,请联系管理员处理!
6. 本站资源售价只是赞助,收取费用仅维持本站的日常运营所需!
7. 如遇到加密压缩包,请使用WINRAR解压,如遇到无法解压的请联系管理员!
8. 精力有限,不少源码未能详细测试(解密),不能分辨部分源码是病毒还是误报,所以没有进行任何修改,大家使用前请进行甄别
丞旭猿论坛
暂无评论内容