C++ 高性能内存池设计与实现
在现代 C++ 开发中,频繁的 malloc/free 或 new/delete 调用往往成为性能瓶颈。这不仅涉及系统调用的开销,还会导致堆内存碎片化。为了解决这些问题,我们通常引入内存池技术——预先向操作系统申请大块内存,在内部进行细粒度管理,从而减少系统交互频率并优化内存利用率。
核心概念与原理
定位 new (Placement New)
在内存池场景中,我们通常已经分配了原始内存块,需要在这块内存上构造对象。此时不能直接使用 new T(),因为它会再次分配内存。我们需要使用 Placement New:
class MyClass {
public:
MyClass() { /* 初始化 */ }
};
char buffer[sizeof(MyClass)];
MyClass* obj = new (buffer) MyClass(); // 在 buffer 地址直接构造对象
这种方式不会调用 operator new,而是直接在指定地址调用构造函数。销毁时,需显式调用析构函数 obj->~MyClass(),但内存本身由内存池统一管理,不在此处释放。
内存碎片问题
内存碎片主要分为两类:
- 外碎片:空闲内存总量足够,但不连续,无法满足大对象分配请求。
- 内碎片:由于对齐要求,分配给对象的实际空间大于其所需大小,导致部分空间浪费。
内存池通过定长分配和对象复用机制,能有效缓解这两类问题。
基础实现:定长内存池
我们先设计一个简单的定长内存池,作为后续高并发版本的基础组件。核心思路是维护一个自由链表(Free List),记录已释放的内存块。
关键代码结构
#pragma once
#include <iostream>
#include <vector>
#include <new>
#include <time.h>
using std::cout;
using std::endl;
#ifdef _WIN32
#include
{
* ptr = (, kpage << , MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
;
(ptr == ) std::();
ptr;
}
< >
{
:
{
T* obj = ;
(_freeList) {
* next = *((**)_freeList);
obj = (T*)_freeList;
_freeList = next;
} {
(_remainingBytes < (T)) {
_remainingBytes = * ;
_memory = (*)(_remainingBytes >> );
(!_memory) std::();
}
obj = (T*)_memory;
objSize = (T) < (*) ? (*) : (T);
_memory += objSize;
_remainingBytes -= objSize;
}
(obj) T;
obj;
}
{
obj->~();
*(**)obj = _freeList;
_freeList = obj;
}
:
* _memory = ;
* _freeList = ;
_remainingBytes = ;
};


