最近在學習redis源碼,想着光看不如自己動動手,於是寫了個localRedis
如名字所示,這是個本地數據庫,有着與redis類似的命令接口,但內部實現比較簡單,只提取了一些主要邏輯
如有錯誤或不合理的地方,懇請指出!謝謝!
源碼地址: https://github.com/BAN1993/localRedis
(這篇文章主要是內存池的實現,與redis關係不大~)
目的
做這個內存池主要目的是爲了方便管理內存和減少內存碎片,但是效率會比new/delete低(這裏只是簡單測試結果)。
另外還有一個後面調試才發現的好處(適合學習,不適合用在項目中),可以在程序退出時打印忘記釋放的內存。比如:
#include "base.h"
#include "mallocManager.h"
int main()
{
char* c = (char*)__new(1024);
sprintf(c,"hello word!");
LOG(c);
return 0;
}
最後編譯運行會輸出如下:
[main:8]hello word!
[~mallocManager:10]UNDELETE:filename=main.cpp,line=6
設計
這個內存池的核心思想是每次申請大塊內存,然後拆分成N塊小內存插入到空閒隊列供後面取用。new時從空閒隊列取,隊列爲空就繼續申請大塊內存;delete時將內存插回空閒隊列。
流程
我們會將取用的內存大小向上調整爲整數(2的倍數,8,16,32......2K,4K,8K),每種大小都會維護一個內存池。
比如想要取用一塊char[5]的內存時,我們會返回一塊8字節的內存:
①若相應池中空閒隊列不爲空,直接返回
②若相應池中空閒隊列爲空,先申請一塊8K大小的內存,將它拆分成8192/8塊,逐一插入空閒隊列再返回其一
經過一段時間的取用後,內存使用情況可能如下:
可以看到目前只創建並使用了8,128,4K三種類型的內存池,其中8空閒還比較多;128已滿,下次取用就會擴充;4K還有一塊空閒。
若一次申請的內存大於8K,那麼會直接申請相應大小的內存塊並存到一個big列表中,釋放時也是直接刪除。
例子
#include "base.h"
#include "mallocManager.h"
class TestA
{
public:
TestA(int size)
{
size = size <= 0 ? 1 : size;
// m_p = new char[size];
// or
m_p = (char*)__new(size);
}
~TestA()
{
if(m_p)
{
// delete[] m_p;
// or
__delete(m_p);
}
m_p = nullptr;
}
private:
char* m_p;
};
int main()
{
__new_obj_1(TestA, p, 666);
// do something
// p->...
__delete_obj(TestA, p);
return 0;
}
實現源碼見:https://github.com/BAN1993/localRedis
mallocPool.cpp/.h
mallocManager.cpp/.h