C++内存池(MemPool)
本文最后更新于2 天前,其中的信息可能已经过时,如有错误请自行更正!

image

C++内存池(MemPool)

1. 什么是内存池

定义:预先分配大块内存并自行管理,提高小对象分配性能。1、减少系统调用;2、提高内存利用率;3、提升缓存命中率。

2. C++内存池框架

#include <iostream>
#include <vector>
#include <cassert>
#include <cstddef>
#include <chrono>


// 对齐到指定的对齐边界,确保返回的地址是对齐的
static inline std::size_t alignUp(std::size_t n, std::size_t align) {
    return (n + (align - 1)) & ~(align - 1);
}

class FixedSizePool {
public:
    explicit FixedSizePool(std::size_t block_size, std::size_t blocks_per_page = 1024) : 
        block_size_(adjustBlockSize(block_size)),
        blocks_per_page_(blocks_per_page),
        free_list_(nullptr) {}  // explicit用于修饰类的构造函数或转换函数,禁止隐式类型转换,只能进行显式转换,从而避免意外的类型转换导致的逻辑错误。

    ~FixedSizePool() {
        for (void* page : pages_) {
            ::operator delete[](page); // 全局删除操作符释放内存
        }
    }

    // 分配一个块
    void* allocate() {
        if (free_list_ == nullptr) {
            expand(); // 如果空闲链表为空,扩展内存
        }
        Node* head = free_list_;
        free_list_ = head->next;
        return head;
    }

    // 释放一个块
    void deallocate(void* ptr) {
        if (ptr == nullptr) return;
        Node* node = static_cast<Node*>(ptr);
        node->next = free_list_;
        free_list_ = node;
    }

    std::size_t getBlockSize() const {
        return block_size_;
    }
    std::size_t getBlocksPerPage() const {
        return blocks_per_page_;
    }

private:
    // 调整块大小,确保有至少能存放一个指针的大小,否则无法维护空闲链表
    std::size_t adjustBlockSize(std::size_t size) {
        std::size_t min = sizeof(void*);
        std::size_t a = alignUp(size < min ? min : size, alignof(void*)); // alignof返回输入类型的对齐规则大小
        return a;
    }

    //每次向系统申请一页的内存并把这一页的内存切为很多小块,并把这些小块挂到空闲链表中
    void expand() {
        // 一整页内存的字节数
        std::size_t page_bytes = block_size_ * blocks_per_page_;
        char* page = static_cast<char*>(::operator new[](page_bytes)); // 全局new操作符分配内存
        pages_.push_back(page); // 记录已分配的页

        // 将新页切割成多个块并加入空闲链表
        char* block = static_cast<char*>(page);
        for (std::size_t i = 0; i < blocks_per_page_; ++i) {
            deallocate(block + i * block_size_); // 复用
            // char* current_block = page + i * block_size_;
            // Node* node = reinterpret_cast<Node*>(current_block);
            // node->next = free_list_;
            // free_list_ = node;
        }
    }

    struct Node {Node* next;}; // 维护一个单链表,每个节点指向一个空闲块
    Node* free_list_; // 空闲块链表头指针,每次分配和释放都从这里操作

    std::size_t block_size_; // 每个块的大小
    std::size_t blocks_per_page_; // 每页可以分配的块数
    std::vector<void*> pages_; // 所有已经分配的“页” - 析构统一释放

};

3. 内存对齐

// 对齐到指定的对齐边界,确保返回的地址是对齐的
static inline std::size_t alignUp(std::size_t n, std::size_t align) {  //inline提高性能
    return (n + (align - 1)) & ~(align - 1);
}

4. 对象池应用

struct Particle
{
    float x, y, z;
    int life;

    static void* operator new(std::size_t n);
    static void operator delete(void* p) noexcept;  //noexcept用于指定函数不会抛出异常(或明确声明可能抛出异常),帮助编译器进行优化并增强代码的异常安全性

    void update() { ++life; }
};

static FixedSizePool g_particle_pool(sizeof(Particle), 4096);

void* Particle::operator new(std::size_t n) {
    return g_particle_pool.allocate();
}

void Particle::operator delete(void* p) noexcept {
    g_particle_pool.deallocate(p);
}

5. 测试

int main() {
    std::vector<Particle*> vec;
    vec.reserve(10000);

    auto start = std::chrono::high_resolution_clock::now();

    for (int i = 0; i < 10000; i++) {
        Particle* p = new Particle{ 0,0,0,0 };
        vec.push_back(p);
    }
    for (auto* p : vec) delete p;

    auto end = std::chrono::high_resolution_clock::now();
    auto duration = std::chrono::duration_cast<std::chrono::microseconds>(end - start);

    std::cout << "FixedSizePool-生成 10000 Particle 耗时: " << duration.count() << " 微秒" << std::endl;

    return 0;
}

image

C++内存池(MemPool) by meiguihua
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇