STL两级空间配置器<128kb(内存池+自由链表)与一级空间配置器(mmap(),allocate())

STL 的两级空间配置器(Two-Level Allocator)

STL(标准模板库)中的 两级空间配置器(Two-Level Allocator)SGI STL(Silicon Graphics STL) 设计的 内存管理机制,用于 提高小对象(≤128B)和大对象(>128B)的分配效率


1. 什么是两级空间配置器?

在 SGI STL 的 __default_alloc_template(SGI STL 的默认分配器)中,采用 两级(Two-Level)策略

  • 第一级配置器(一级分配器):直接调用 malloc()free(),用于 大对象(>128B)
  • 第二级配置器(二级分配器):管理 小对象(≤128B),采用 内存池(Memory Pool)+ 自由链表(Free List),避免频繁调用 malloc(),提高性能。

2. 为什么使用两级空间配置器?

传统 malloc() 存在的问题

  • 小对象分配开销大:大量小对象频繁 malloc() / free() 会增加系统调用开销
  • 内存碎片化:多个小对象可能占据非连续的内存,导致 内存碎片问题

两级空间配置器的优势

  • 减少 malloc() / free() 频率,提高性能(特别是小对象)。
  • 减少内存碎片,优化内存利用率
  • 支持内存池管理,回收小对象,提高分配效率

3. 一级空间配置器(大对象)

一级配置器用于 大对象(>128B),直接调用 malloc()free()

SGI STL 一级配置器

#include 
#include 

class MallocAllocator {
public:
    static void* allocate(size_t size) {
        void* result = std::malloc(size); // 直接调用 malloc
        if (!result) {
            std::cerr << "malloc failed\n";
            exit(1);
        }
        return result;
    }

    static void deallocate(void* ptr) {
        std::free(ptr); // 直接调用 free
    }
};

int main() {
    void* ptr = MallocAllocator::allocate(256); // 大于 128B,直接 malloc
    MallocAllocator::deallocate(ptr);
}

适用于大对象(避免复杂管理,减少 malloc() 次数)


4. 二级空间配置器(小对象)

二级配置器用于 小对象(≤128B),采用 内存池(Memory Pool)+ 自由链表(Free List),减少 malloc() 调用,提高效率。

SGI STL 二级配置器

#include 
#include 

class PoolAllocator {
private:
    static const size_t MAX_SIZE = 128; // 小对象最大 128B
    static const size_t CHUNK = 20; // 每次分配 20 个对象

    struct Obj {
        Obj* next;
    };

    static Obj* free_list[MAX_SIZE / 8]; // 自由链表,管理小对象
    static void* refill(size_t size);

public:
    static void* allocate(size_t size) {
        if (size > MAX_SIZE) return std::malloc(size); // 大对象走一级配置器
        size_t index = size / 8;
        if (!free_list[index]) refill(size);
        Obj* head = free_list[index];
        free_list[index] = head->next;
        return head;
    }

    static void deallocate(void* ptr, size_t size) {
        if (size > MAX_SIZE) { std::free(ptr); return; }
        size_t index = size / 8;
        Obj* node = (Obj*)ptr;
        node->next = free_list[index];
        free_list[index] = node;
    }
};

// 初始化自由链表
PoolAllocator::Obj* PoolAllocator::free_list[MAX_SIZE / 8] = {nullptr};

// 申请新内存块(批量分配)
void* PoolAllocator::refill(size_t size) {
    size_t num = CHUNK; // 一次性分配 20 个
    void* chunk = std::malloc(size * num);
    Obj* first = (Obj*)chunk;
    Obj* current = first;
    for (size_t i = 1; i < num; i++) {
        Obj* next = (Obj*)((char*)chunk + i * size);
        current->next = next;
        current = next;
    }
    current->next = nullptr;
    free_list[size / 8] = first->next;
    return first;
}

int main() {
    void* p1 = PoolAllocator::allocate(64); // 走二级配置器(小对象)
    PoolAllocator::deallocate(p1, 64);
}

关键点

  • 自由链表(Free List)管理小对象,避免频繁 malloc()
  • 一次性 malloc() 批量分配 CHUNK=20 个对象,减少 malloc() 次数
  • 释放时,加入自由链表,等待复用

适用于小对象,提高分配效率!


5. 两级空间配置器的策略

策略 一级配置器(大对象) 二级配置器(小对象)
适用范围 大于 128B 的对象 小于等于 128B 的对象
底层实现 malloc() / free() 内存池 + 自由链表
内存分配 直接分配 预分配多个对象
性能 开销大(系统调用) 高效(减少 malloc() 频率)
碎片化 可能导致碎片 减少碎片,管理更精细

6. STL 中 allocator 的实现

在现代 C++ STL(如 std::allocator),默认使用 malloc() / free(),但可以 自定义内存分配器

#include 
#include 
#include 

template <typename T>
struct CustomAllocator {
    using value_type = T;

    T* allocate(size_t n) {
        return static_cast<T*>(::operator new(n * sizeof(T))); // 使用 new 代替 malloc
    }

    void deallocate(T* p, size_t) {
        ::operator delete(p);
    }
};

int main() {
    std::vector<int, CustomAllocator<int>> vec;
    vec.push_back(42);
    std::cout << vec[0] << std::endl;
}

std::allocator 可定制 STL 容器的内存分配!


7. 结论

STL 采用 “两级空间配置器” 来优化内存管理

  1. 一级配置器(大对象)malloc() / free()(适用于 >128B 对象)。
  2. 二级配置器(小对象)内存池(Memory Pool)+ 自由链表(Free List)(适用于 ≤128B 对象)。

两级分配器的优点

  • 减少 malloc() / free() 频率,提高小对象分配效率。
  • 减少内存碎片,提高内存复用率。
  • 适用于 STL 容器(std::vectorstd::mapstd::list)的高效内存管理。

掌握两级空间配置器,优化 C++ STL 内存分配!

你可能感兴趣的:(c++,链表,开发语言)