1. 大块内存的申请与释放机制解析
在实现高并发内存池时,处理大块内存的申请与释放是一个关键问题。我们需要设计一套高效的机制,既能满足大内存请求的需求,又能保持内存池的整体性能。
1.1 内存分配层级设计
我们的内存池采用三级结构:
- ThreadCache:线程本地缓存,处理小内存块(<=256KB)
- CentralCache:中心缓存,协调多个ThreadCache之间的内存分配
- PageCache:页缓存,管理大块内存(>256KB)
这种分层设计能够有效减少锁竞争,提高并发性能。对于超过256KB的大内存请求,我们选择直接绕过ThreadCache和CentralCache,向PageCache申请,这样可以避免不必要的锁开销和内存碎片。
1.2 大块内存的申请流程
当应用程序请求的内存大小超过256KB时,内存池会执行以下操作:
- 对齐内存大小:使用SizeClass::RoundUp将请求大小对齐到最近的页边界
- 计算需要的页数:将对齐后的大小转换为页数(PAGE_SHIFT通常为13,即8KB一页)
- 加锁访问PageCache:防止多线程竞争
- 调用PageCache::NewSpan获取合适的Span
- 记录分配的内存块大小
- 返回分配的内存地址
关键代码实现:
cpp复制static void* ConcurrentAlloc(size_t size) {
if (size > MAX_BYTES) { // 大于256KB
size_t alignSize = SizeClass::RoundUp(size);
size_t kpage = alignSize >> PAGE_SHIFT;
PageCache::GetInstance()->_pageMtx.lock();
Span* span = PageCache::GetInstance()->NewSpan(kpage);
span->_objSize = size;
PageCache::GetInstance()->_pageMtx.unlock();
