内存池优化

✅ 2. 内存池是什么?为什么能优化内存性能?
🔹 定义:

内存池是一种预分配内存块并循环复用的技术,用于减少频繁 new/delete 带来的系统开销和内存碎片。

🔹 为什么有效?

系统调用(如 malloc/free)开销大,频繁分配释放性能低

内存池可以从大块内存中切分出小块,统一管理

适合对象生命周期相似、频繁创建/销毁的场景

🔹 用法示意:
class MyObject {
public:
static void* operator new(size_t size);
static void operator delete(void* ptr);
private:
static MemoryPool pool; // 自定义内存池
};

🔹 使用场景:

游戏服务器、数据库连接管理器、网络包缓存

STL 容器(如 std::list)可自定义分配器实现内存池

什么是内存池(Memory Pool)

内存池是一种内存管理技术,它预先申请一大块连续的内存区域,然后在这个区域里分配和回收内存块,而不是每次都调用系统的动态内存分配(如 malloc / new)。

为什么用内存池?

减少频繁系统调用开销
系统调用分配内存(malloc / free)通常比较慢,而且会带来碎片化问题。内存池通过一次性申请大块内存,避免频繁向操作系统请求内存。

降低内存碎片
动态分配小块内存容易产生碎片,内存池管理固定大小或者类似大小的内存块,有助于减少碎片。

提高分配和回收速度
内存池内部管理结构简单,分配内存时仅仅是从空闲列表取块,回收时放回空闲列表,操作非常快。

提升缓存局部性
由于内存块是连续或者接近的内存,访问时更容易利用 CPU 缓存,提高性能。

简单比喻

你可以把内存池想象成一个“盒子”,里面有很多小格子(内存块):

你需要内存时,从盒子里拿一个空格子,不用每次都去仓库(系统)买。

用完后,把格子放回盒子,下一次可以快速再用。

这样既快又省资源。

例子:游戏中用内存池管理子弹对象

游戏中发射的子弹数量很多,如果每次子弹生成和销毁都调用 new 和 delete,会频繁调用系统内存管理,性能受影响。

用内存池:

预先分配足够多的子弹对象内存块

发射子弹时直接从池中取对象,不用重新分配

子弹消失时放回池中,等待下次使用
简单内存池示例(C++)

这个示例实现一个固定大小内存块的内存池,适合管理很多相同大小的小对象,比如“子弹”、“节点”等。

#include <iostream>
#include <vector>
#include <cstdlib>

class SimpleMemoryPool {
public:
    SimpleMemoryPool(size_t blockSize, size_t blockCount)
        : blockSize_(blockSize), blockCount_(blockCount) {
        pool_ = malloc(blockSize_ * blockCount_);
        freeBlocks_.reserve(blockCount_);
        
        // 初始化空闲链表,所有块都空闲,按地址顺序入队
        for (size_t i = 0; i < blockCount_; ++i) {
            freeBlocks_.push_back(static_cast<char*>(pool_) + i * blockSize_);
        }
    }

    ~SimpleMemoryPool() {
        free(pool_);
    }

    // 从池里分配内存块
    void* allocate() {
        if (freeBlocks_.empty()) {
            std::cerr << "内存池已用尽!" << std::endl;
            return nullptr;
        }
        void* ptr = freeBlocks_.back();
        freeBlocks_.pop_back();
        return ptr;
    }

    // 释放内存块,放回池中
    void deallocate(void* ptr) {
        freeBlocks_.push_back(static_cast<char*>(ptr));
    }

private:
    void* pool_;                 // 大块内存池
    size_t blockSize_;           // 每个内存块大小
    size_t blockCount_;          // 块数
    std::vector<void*> freeBlocks_;  // 空闲块地址栈
};

// 模拟使用内存池
int main() {
    SimpleMemoryPool pool(sizeof(int), 10);  // 10个int大小块的池子

    // 分配3个int块
    int* a = static_cast<int*>(pool.allocate());
    int* b = static_cast<int*>(pool.allocate());
    int* c = static_cast<int*>(pool.allocate());

    *a = 100;
    *b = 200;
    *c = 300;

    std::cout << *a << " " << *b << " " << *c << std::endl;

    // 归还两个块
    pool.deallocate(b);
    pool.deallocate(a);

    // 再分配一个块,应该复用刚释放的块
    int* d = static_cast<int*>(pool.allocate());
    *d = 999;
    std::cout << *d << std::endl;

    // 最后释放所有
    pool.deallocate(c);
    pool.deallocate(d);

    return 0;
}

工作原理总结

初始化时 一次性调用 malloc 分配一大块连续内存。

分配时 从空闲块列表取出一块内存,返回给用户。

释放时 把这块内存地址放回空闲列表,等待复用。

为什么内存池减少内存碎片?

系统 malloc/free 分配的是不同大小的内存,长时间申请释放不定大小内存块,会造成很多零散的小碎片,导致大块内存难以连续申请。

内存池管理的内存块大小是固定的,且所有块连续排布,分配释放都只是简单的地址取出和放回,避免了“内存碎片”的产生。

这种池化管理让内存块高度聚集,减少零散空间。

内存池怎么进行分配?

预先分配一大块连续内存(比如 blockSize * blockCount 大小)

维护一个空闲块链表(比如栈或队列)

每次分配就是从链表取一个地址,释放就是放回链表

不用调用系统分配,快速简洁
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值