首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> C++ >> 關於C++

C++ 程式記憶體管理精雕細琢:自訂分配器、HeapLayers 架構與效能優化

     編輯:關於C++

一、為什麼需要自訂記憶體分配器?

通用分配器(malloc/new)雖已高度優化,但特定應用(高頻小物件、固定大小區塊、多執行緒競爭)仍有提升空間。GCC、Apache、SQL Server 皆實作專屬分配器。自訂分配器可將分配週期從數百時脈降至個位數。

二、HeapLayers 分層架構設計

採用 Mixin 模式(參數化基底類別),每層僅實作 malloc/free,可組合出靈活的分配策略。

核心介面

template 
struct Allocator : public Super {
    void* malloc(size_t sz);
    void free(void* p);
    enum { Alignment = sizeof(double) };
    size_t getSize(const void* p); // 可選
};

頂層堆:串接系統分配器

struct MallocHeap {
    void* malloc(size_t sz) { return std::malloc(sz); }
    void free(void* p) { std::free(p); }
    size_t getSize(void* p) { return _msize(p); } // MSVC 專用
};

功能層範例:SizeHeap(記錄區塊大小)

template 
struct UseSizeHeap : public Super { // 僅提供 getSize
    static size_t getSize(const void* ptr) {
        return ((FreeObject*)ptr - 1)->sz;
    }
protected:
    union FreeObject { size_t sz; double _dummy; }; // 對齊用
};

template 
class SizeHeap : public UseSizeHeap { // 實作 malloc/free 並記錄大小
    using FreeObject = typename UseSizeHeap::FreeObject;
public:
    void* malloc(size_t sz) {
        FreeObject* ptr = (FreeObject*)SuperHeap::malloc(sz + sizeof(FreeObject));
        ptr->sz = sz;
        return ptr + 1; // 傳回使用者資料區起始位址
    }
    void free(void* p) { SuperHeap::free((FreeObject*)p - 1); }
};

設計精華: 將 getSize 抽離為 UseSizeHeap,系統若已提供大小查詢(如 MSVC _msize)可直接用 MallocHeap,避免重複儲存浪費空間。

三、實用層:FreelistHeap(釋放清單)

針對熱門大小區間維護單向鏈結串列,分配/釋放 O(1)、無額外記憶體開銷(指標存於釋放區塊內)。

template 
struct FLHeap {
    ~FLHeap() { // 釋放殘留區塊
        while (myFreeList) {
            FreeObject* next = myFreeList->next;
            Super::free(myFreeList);
            myFreeList = next;
        }
    }
    void* malloc(size_t s) {
        if (s < S1 || s > S2) return Super::malloc(s);
        if (!myFreeList) return Super::malloc(S2);
        void* p = myFreeList;
        myFreeList = myFreeList->next;
        return p;
    }
    void free(void* p) {
        size_t s = getSize(p);
        if (s < S1 || s > S2) return Super::free(p);
        FreeObject* obj = reinterpret_cast(p);
        obj->next = myFreeList;
        myFreeList = obj;
    }
private:
    struct FreeObject { FreeObject* next; };
    FreeObject* myFreeList = nullptr;
};

組合範例:24~32 位元組區間專用分配器

typedef FLHeap, 24, 32> SmallObjectHeap;

四、原地重新配置

C realloc 會 memcpy,不適用 C++ 物件(需呼叫建構/解構函式)。HeapLayers 擴充介面支援 expand:

template 
struct Allocator : public T {
    void* malloc(size_t sz);
    void free(void* p);
    size_t expand(void* p, size_t min, size_t max); // 嘗試原地擴充
};

頂層堆預設回傳 0 表示不支援。向量 push_back 可受益於原地擴充,效能提升 2 倍以上(Metrowerks 實測)。

五、HeapLayers 內建層類別速查表

分類層名稱功能
頂層堆MallocHeap封裝 malloc/free
MmapHeap虛擬記憶體對應
SbrkHeap連續堆疊擴展
區塊管理ChunkHeap固定大小區塊管理
CoalesceHeap區塊合併/分割
FreelistHeap釋放清單
HybridHeap小/大物件分流
SegHeap一般分離策略
StrictSegHeap嚴格分離策略
工具層ANSIWrapperANSI malloc 相容
DebugHeap偵測越界/重複釋放
LockedHeap執行緒安全鎖定
ProfileHeap碎片統計
ThreadHeap執行緒私有堆
TraceHeap分配追蹤日誌
特殊用途ObstackHeap堆疊式/快速調整大小
ZoneHeap區域分配器
XallocHeap優化堆疊行為
通用堆KingsleyHeap快速但碎片多
LeaHeap速度較慢但碎片少

六、結語與提醒

  • 分層架構讓分配策略可組合、可除錯、可擴充。
  • 記得在解構函式釋放資源(FLHeap 析構即範例)。
  • 針對應用程式分配模式(大小分佈、生命週期、執行緒存取)選擇適當層組合。
  • 祝編程愉快,記憶體零洩漏!
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved