├── image ├── step1.png ├── step10.png ├── step11.png ├── step12.png ├── step13.png ├── step14.png ├── step15.png ├── step16.png ├── step17.png ├── step2.png ├── step3.png ├── step4.png ├── step5.png ├── step6.png ├── step7.png ├── step8.png └── step9.png ├── .gitattributes ├── MemoryBlock.h ├── MemoryBlock.cpp ├── .gitignore ├── MemoryPool.h ├── List_Node.h ├── README.md ├── main.cpp └── MemoryPool.cpp /image/step1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DavidLiRemini/MemoryPool/HEAD/image/step1.png -------------------------------------------------------------------------------- /image/step10.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DavidLiRemini/MemoryPool/HEAD/image/step10.png -------------------------------------------------------------------------------- /image/step11.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DavidLiRemini/MemoryPool/HEAD/image/step11.png -------------------------------------------------------------------------------- /image/step12.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DavidLiRemini/MemoryPool/HEAD/image/step12.png -------------------------------------------------------------------------------- /image/step13.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DavidLiRemini/MemoryPool/HEAD/image/step13.png -------------------------------------------------------------------------------- /image/step14.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DavidLiRemini/MemoryPool/HEAD/image/step14.png -------------------------------------------------------------------------------- /image/step15.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DavidLiRemini/MemoryPool/HEAD/image/step15.png -------------------------------------------------------------------------------- /image/step16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DavidLiRemini/MemoryPool/HEAD/image/step16.png -------------------------------------------------------------------------------- /image/step17.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DavidLiRemini/MemoryPool/HEAD/image/step17.png -------------------------------------------------------------------------------- /image/step2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DavidLiRemini/MemoryPool/HEAD/image/step2.png -------------------------------------------------------------------------------- /image/step3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DavidLiRemini/MemoryPool/HEAD/image/step3.png -------------------------------------------------------------------------------- /image/step4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DavidLiRemini/MemoryPool/HEAD/image/step4.png -------------------------------------------------------------------------------- /image/step5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DavidLiRemini/MemoryPool/HEAD/image/step5.png -------------------------------------------------------------------------------- /image/step6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DavidLiRemini/MemoryPool/HEAD/image/step6.png -------------------------------------------------------------------------------- /image/step7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DavidLiRemini/MemoryPool/HEAD/image/step7.png -------------------------------------------------------------------------------- /image/step8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DavidLiRemini/MemoryPool/HEAD/image/step8.png -------------------------------------------------------------------------------- /image/step9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DavidLiRemini/MemoryPool/HEAD/image/step9.png -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | 4 | # Custom for Visual Studio 5 | *.cs diff=csharp 6 | 7 | # Standard to msysgit 8 | *.doc diff=astextplain 9 | *.DOC diff=astextplain 10 | *.docx diff=astextplain 11 | *.DOCX diff=astextplain 12 | *.dot diff=astextplain 13 | *.DOT diff=astextplain 14 | *.pdf diff=astextplain 15 | *.PDF diff=astextplain 16 | *.rtf diff=astextplain 17 | *.RTF diff=astextplain 18 | -------------------------------------------------------------------------------- /MemoryBlock.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | typedef unsigned short USHORT; 5 | struct MemoryBlock 6 | { 7 | //链表前后指针 8 | MemoryBlock*prev; 9 | MemoryBlock* next; 10 | //分配MemoryBlock总大小。 11 | int mSize; 12 | //未分配块个数 13 | int free; 14 | //首个未分配块索引 15 | int first; 16 | //Padding 17 | char mPad[2]; 18 | MemoryBlock(USHORT=1, USHORT = 0); 19 | static void* operator new(size_t, USHORT, USHORT); 20 | static void operator delete(void*); 21 | }; 22 | 23 | -------------------------------------------------------------------------------- /MemoryBlock.cpp: -------------------------------------------------------------------------------- 1 | #include "MemoryBlock.h" 2 | 3 | MemoryBlock::MemoryBlock(USHORT initblock, USHORT unitSize) 4 | :prev(nullptr), 5 | next(nullptr), 6 | mSize(initblock* (unitSize+2)), 7 | free(initblock - 1), 8 | first(1) 9 | { 10 | memset(mPad, 0, mSize - 20); 11 | char* padData = mPad; 12 | for (int i = 1; i< initblock;i++) 13 | { 14 | *reinterpret_cast(padData) = i; 15 | padData += (unitSize+2); 16 | } 17 | } 18 | 19 | void* MemoryBlock::operator new(size_t, USHORT initBlock, USHORT unitSize) 20 | { 21 | return ::operator new(sizeof(MemoryBlock) + initBlock* (unitSize+2)); 22 | } 23 | void MemoryBlock::operator delete(void* p) 24 | { 25 | ::operator delete(p); 26 | } -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Windows image file caches 2 | Thumbs.db 3 | ehthumbs.db 4 | 5 | # Folder config file 6 | Desktop.ini 7 | 8 | # Recycle Bin used on file shares 9 | $RECYCLE.BIN/ 10 | 11 | # Windows Installer files 12 | *.cab 13 | *.msi 14 | *.msm 15 | *.msp 16 | 17 | # Windows shortcuts 18 | *.lnk 19 | 20 | # ========================= 21 | # Operating System Files 22 | # ========================= 23 | 24 | # OSX 25 | # ========================= 26 | 27 | .DS_Store 28 | .AppleDouble 29 | .LSOverride 30 | 31 | # Thumbnails 32 | ._* 33 | 34 | # Files that might appear in the root of a volume 35 | .DocumentRevisions-V100 36 | .fseventsd 37 | .Spotlight-V100 38 | .TemporaryItems 39 | .Trashes 40 | .VolumeIcon.icns 41 | 42 | # Directories potentially created on remote AFP share 43 | .AppleDB 44 | .AppleDesktop 45 | Network Trash Folder 46 | Temporary Items 47 | .apdisk 48 | -------------------------------------------------------------------------------- /MemoryPool.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | 5 | typedef unsigned short USHORT; 6 | struct MemoryBlock; 7 | 8 | 9 | //全局内存池为单例类。使用的时候只需要一个实例即可,并不需要多个实例。 10 | class MemoryPool 11 | { 12 | private: 13 | static USHORT poolMapIndex; 14 | //分配不同内存块时其对应的映射表 15 | std::mappoolMap; 16 | //内存池对齐大小。 17 | const int POOLALIGNMENT = 8; 18 | //初始化内存块 19 | int initBlockCount; 20 | //内存块不足增长的块数。 21 | int growBlockcount; 22 | //首子内存池下标 23 | unsigned firstIndex; 24 | //末内存池下标。 25 | unsigned lastIndex; 26 | //最多16中不同内存块大小,也就是说子内存池最多有16个。 27 | MemoryBlock* memoryHashMap[16]; 28 | MemoryBlock** mpPtr; 29 | //计算不同内存块对应的hashCode 30 | int Hash(int); 31 | //对齐字节 32 | int AlignBytes(int); 33 | //返回分配块大小。 34 | int GetUnitSize(int); 35 | protected: 36 | static MemoryPool* memoryPoolInstance; 37 | MemoryPool(int initBlockSize = 1024, int growBlockSize = 256); 38 | public: 39 | //分配内存 40 | void* Alloc(int); 41 | //释放内存。 42 | void FreeAlloc(void*); 43 | //返回全局内存池实例 44 | static MemoryPool* GetInstance(); 45 | ~MemoryPool(); 46 | }; 47 | -------------------------------------------------------------------------------- /List_Node.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | template 5 | struct List_Node 6 | { 7 | List_Node* prev; 8 | List_Node* next; 9 | T data; 10 | List_Node() 11 | :prev(nullptr), 12 | next(nullptr){} 13 | }; 14 | 15 | template 16 | class ListPool 17 | { 18 | protected: 19 | typedef List_Node ListNode; 20 | public: 21 | typedef ListNode* LinkType; 22 | protected: 23 | LinkType node; 24 | private: 25 | LinkType Create_Node() { 26 | LinkType tmp = new ListNode(); 27 | return tmp; 28 | } 29 | public: 30 | ListPool() 31 | { 32 | Empty_initialize(); 33 | } 34 | void Empty_initialize() 35 | { 36 | node = Create_Node(); 37 | node->prev = node; 38 | node->next = node; 39 | } 40 | void Remove(ListNode& link) 41 | { 42 | assert(link.prev != nullptr); 43 | assert(link.next != nullptr); 44 | link.prev->next = link.next; 45 | link.next->prev = link.prev; 46 | 47 | link.next = nullptr; 48 | link.prev = nullptr; 49 | } 50 | void AddNode(const T& x) 51 | { 52 | LinkType tmp = Create_Node(); 53 | tmp->data = x; 54 | tmp->next = node; 55 | tmp->prev = node->prev; 56 | node->prev->next = tmp; 57 | node->prev = tmp; 58 | } 59 | unsigned ListSize()const 60 | { 61 | unsigned t = 0; 62 | LinkType ptr = node->next; 63 | while (ptr != node) 64 | { 65 | ptr = ptr->next; 66 | ++t; 67 | } 68 | return t; 69 | } 70 | }; 71 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # MemoryPool 2 | 简单有效的内存池实现,有效的减少内存分配引起的效率问题。
3 | `Some illustrations` 4 | 5 | ![](https://raw.githubusercontent.com/DavidLiRemini/MemoryPool/master/image/step1.png) 6 | ![](https://raw.githubusercontent.com/DavidLiRemini/MemoryPool/master/image/step2.png) 7 | ![](https://raw.githubusercontent.com/DavidLiRemini/MemoryPool/master/image/step3.png) 8 | ![](https://raw.githubusercontent.com/DavidLiRemini/MemoryPool/master/image/step4.png) 9 | ![](https://raw.githubusercontent.com/DavidLiRemini/MemoryPool/master/image/step5.png) 10 | ![](https://raw.githubusercontent.com/DavidLiRemini/MemoryPool/master/image/step6.png) 11 | ![](https://raw.githubusercontent.com/DavidLiRemini/MemoryPool/master/image/step7.png) 12 | ![](https://raw.githubusercontent.com/DavidLiRemini/MemoryPool/master/image/step8.png) 13 | ![](https://raw.githubusercontent.com/DavidLiRemini/MemoryPool/master/image/step9.png) 14 | ![](https://raw.githubusercontent.com/DavidLiRemini/MemoryPool/master/image/step10.png) 15 | ![](https://raw.githubusercontent.com/DavidLiRemini/MemoryPool/master/image/step11.png) 16 | ![](https://raw.githubusercontent.com/DavidLiRemini/MemoryPool/master/image/step12.png) 17 | ![](https://raw.githubusercontent.com/DavidLiRemini/MemoryPool/master/image/step13.png) 18 | ![](https://raw.githubusercontent.com/DavidLiRemini/MemoryPool/master/image/step14.png) 19 | ![](https://raw.githubusercontent.com/DavidLiRemini/MemoryPool/master/image/step15.png) 20 | ![](https://raw.githubusercontent.com/DavidLiRemini/MemoryPool/master/image/step16.png) 21 | ![](https://raw.githubusercontent.com/DavidLiRemini/MemoryPool/master/image/step17.png) 22 | -------------------------------------------------------------------------------- /main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "List_Node.h" 3 | #include "MemoryPool.h" 4 | #include 5 | #include 6 | #include 7 | 8 | /** 9 | * Memory Leak Caution! Release memory manually. 10 | */ 11 | MemoryPool* mp = MemoryPool::GetInstance(); 12 | class TestMemoryPool 13 | { 14 | private: 15 | int value1 = 10; 16 | int value2 = 20; 17 | float val = 5.9f; 18 | public: 19 | TestMemoryPool(){} 20 | static void* operator new(size_t) 21 | { 22 | return mp->Alloc(sizeof(TestMemoryPool)); 23 | } 24 | static void operator delete(void* p) { 25 | mp->FreeAlloc(p); 26 | } 27 | }; 28 | 29 | class BigClassTest 30 | { 31 | private: 32 | char bc[500]; 33 | int v = 10; 34 | char* p = nullptr; 35 | public: 36 | BigClassTest() { 37 | //memset(bc, 0, sizeof(bc)); 38 | } 39 | static void* operator new(size_t) 40 | { 41 | return mp->Alloc(sizeof(BigClassTest)); 42 | } 43 | static void operator delete(void* p) { 44 | mp->FreeAlloc(p); 45 | } 46 | }; 47 | class ThirdMemoryTest 48 | { 49 | private: 50 | int v[100]; 51 | std::string s; 52 | public: 53 | ThirdMemoryTest() 54 | { 55 | //memset(v, 0, sizeof(v)); 56 | s = ""; 57 | } 58 | static void* operator new(size_t) 59 | { 60 | return mp->Alloc(sizeof(ThirdMemoryTest)); 61 | } 62 | static void operator delete(void* p) 63 | { 64 | mp->FreeAlloc(p); 65 | } 66 | }; 67 | 68 | void test() 69 | { 70 | TestMemoryPool* v = nullptr; 71 | for (int i = 0; i < 2050; i++) 72 | { 73 | v = new TestMemoryPool(); 74 | } 75 | printf("testing\n"); 76 | 77 | BigClassTest* b = nullptr; 78 | for (int i = 0; i < 3000;i++) 79 | { 80 | b = new BigClassTest(); 81 | } 82 | 83 | ThirdMemoryTest* t = nullptr; 84 | for (int j = 0; j < 1920; j++) 85 | { 86 | t = new ThirdMemoryTest(); 87 | } 88 | 89 | } 90 | 91 | int main() 92 | { 93 | test(); 94 | int p = 12; 95 | int*q = &p; 96 | short v = p; 97 | ListPooliList; 98 | iList.AddNode(10); 99 | for (int i = 98; i > 1; i /= 10) 100 | { 101 | iList.AddNode(i); 102 | } 103 | 104 | printf("List size %u\n", iList.ListSize()); 105 | } 106 | -------------------------------------------------------------------------------- /MemoryPool.cpp: -------------------------------------------------------------------------------- 1 | #include "MemoryPool.h" 2 | #include "MemoryBlock.h" 3 | #include 4 | #include 5 | 6 | MemoryPool* MemoryPool::memoryPoolInstance = nullptr; 7 | USHORT MemoryPool::poolMapIndex = 0; 8 | 9 | MemoryPool::MemoryPool(int initBlockSize /* = 1024 */, int growBlockSize /* = 256 */) 10 | :initBlockCount(initBlockSize), 11 | growBlockcount(growBlockSize), 12 | firstIndex(0), 13 | lastIndex(0), 14 | mpPtr(nullptr) { 15 | memset(memoryHashMap, 0, sizeof(memoryHashMap)); 16 | } 17 | 18 | int MemoryPool::Hash(int value) 19 | { 20 | assert(value > 0); 21 | int hashCode = poolMapIndex; 22 | if (hashCode > 0 && (value == poolMap[hashCode - 1])) 23 | { 24 | return hashCode - 1; 25 | } 26 | poolMap[poolMapIndex++] = value; 27 | return hashCode; 28 | } 29 | 30 | int MemoryPool::AlignBytes(int by) 31 | { 32 | assert(by > 0); 33 | if (by <= 4) 34 | { 35 | return 4; 36 | } 37 | int alignedBytes = (by + POOLALIGNMENT - 1)&(~(POOLALIGNMENT - 1)); 38 | return alignedBytes; 39 | } 40 | 41 | int MemoryPool::GetUnitSize(int index) 42 | { 43 | int unitSize = poolMap[index]; 44 | assert(unitSize != 0 && "unitSize can not be zero"); 45 | return unitSize; 46 | } 47 | 48 | MemoryPool* MemoryPool::GetInstance() 49 | { 50 | if (memoryPoolInstance == nullptr) 51 | { 52 | memoryPoolInstance = new MemoryPool(); 53 | } 54 | return memoryPoolInstance; 55 | } 56 | 57 | void* MemoryPool::Alloc(int bytes) 58 | { 59 | int alignedByte = AlignBytes(bytes); 60 | MemoryBlock* block = nullptr; 61 | MemoryBlock* blockHead = nullptr; 62 | int hashCode = Hash(alignedByte); 63 | 64 | block = memoryHashMap[hashCode]; 65 | if (block == nullptr) 66 | { 67 | assert(memoryHashMap[hashCode] == nullptr); 68 | memoryHashMap[hashCode] = new (initBlockCount, alignedByte)MemoryBlock(initBlockCount, alignedByte); 69 | block = memoryHashMap[hashCode]; 70 | firstIndex = hashCode; 71 | if (hashCode >= firstIndex) 72 | { 73 | lastIndex = hashCode; 74 | } 75 | return block->mPad + 2; 76 | } 77 | blockHead = block; 78 | while(block && !block->free) 79 | { 80 | /*if (block->next == nullptr) 81 | { 82 | blockHead = block; 83 | }*/ 84 | block = block->next; 85 | } 86 | 87 | if (block) 88 | { 89 | char* ptr = block->mPad + (block->first*(alignedByte+2)); 90 | block->first = *((USHORT*)ptr); 91 | --block->free; 92 | return (ptr); 93 | } 94 | else 95 | { 96 | if (growBlockcount == 0) 97 | { 98 | return nullptr; 99 | } 100 | block = new(growBlockcount, alignedByte)MemoryBlock(growBlockcount, alignedByte); 101 | if (block == nullptr) 102 | { 103 | return nullptr; 104 | } 105 | block->next = blockHead; 106 | blockHead->prev = block; 107 | memoryHashMap[hashCode] = block; 108 | 109 | return block->mPad + 2; 110 | } 111 | } 112 | void MemoryPool::FreeAlloc(void* p) 113 | { 114 | unsigned long* pBlock = (unsigned long*)p; 115 | int unitSize = 0; 116 | int indexer = 0; 117 | MemoryBlock* tmp = nullptr; 118 | for (int i = 0; i < 16;i++) 119 | { 120 | tmp = memoryHashMap[i]; 121 | if (memoryHashMap[i] != nullptr) 122 | { 123 | while (tmp != nullptr) 124 | { 125 | if ((unsigned long*)tmp < (unsigned long*)pBlock && 126 | (unsigned long*)pBlock < (unsigned long*)((char*)tmp + tmp->mSize)) 127 | { 128 | unitSize = GetUnitSize(i); 129 | indexer = i; 130 | break; 131 | } 132 | tmp = tmp->next; 133 | } 134 | if (indexer != 0) 135 | { 136 | break; 137 | } 138 | } 139 | } 140 | if (tmp == nullptr) 141 | { 142 | return; 143 | } 144 | 145 | *(USHORT*)p = tmp->first; 146 | tmp->first = ((char*)pBlock - (char*)tmp->mPad) / (unitSize+2); 147 | ++tmp->free; 148 | if ((unitSize+2)* tmp->free == tmp->mSize) 149 | { 150 | //delete 151 | if (tmp->prev == nullptr && tmp->next != nullptr) 152 | { 153 | memoryHashMap[indexer] = tmp->next; 154 | tmp->next = nullptr; 155 | tmp->prev = nullptr; 156 | } 157 | else if (tmp->prev != nullptr && tmp->next != nullptr) 158 | { 159 | tmp->prev->next = tmp->next; 160 | tmp->next->prev = tmp->prev; 161 | tmp->next = nullptr; 162 | tmp->prev = nullptr; 163 | } 164 | else if (tmp->next == nullptr && tmp->prev != nullptr) 165 | { 166 | tmp->prev->next = tmp->next; 167 | tmp->next = nullptr; 168 | tmp->prev = nullptr; 169 | } 170 | delete tmp; 171 | memoryHashMap[indexer] = nullptr; 172 | } 173 | else 174 | { 175 | //do nothing 176 | } 177 | 178 | } 179 | MemoryPool::~MemoryPool() 180 | { 181 | for (auto it : memoryHashMap) 182 | { 183 | if (it != nullptr) 184 | { 185 | delete it; 186 | } 187 | } 188 | } 189 | --------------------------------------------------------------------------------