别看了,写的过于垃圾。
就比默认malloc快一丢丢。
ver.0.1 (就测试过一次)
mempool.h
1 #pragma once 2 3 #ifndef __MEM_POOL_H_ 4 #define __MEM_POOL_H_ 5 6 #include <memory> 7 8 #include "./list/list.h" 9 10 11 namespace LC 12 { 13 14 inline static constexpr int ALIGN = 8; 15 inline static constexpr int BLOCK_MAX = 1024; 16 inline static constexpr int BLOCK_CAP = BLOCK_MAX / ALIGN; 17 inline static constexpr int BUCKET_CAP = BLOCK_MAX; 18 19 static_assert(ALIGN % 8 == 0); 20 static_assert(BLOCK_MAX % ALIGN == 0); 21 22 inline constexpr int __Align(int num_) noexcept { return (num_ + ALIGN - 1) & ~(ALIGN - 1); } 23 inline constexpr int __Sit(int index_) noexcept { return (index_ + 1) * ALIGN; } 24 inline constexpr int __Index(int num_) noexcept { return (num_ + ALIGN - 1) / ALIGN - 1; } 25 26 struct __Block 27 { 28 __Block* _next = nullptr; 29 }; 30 31 struct __CacheBlock 32 { 33 __CacheBlock(){} 34 __CacheBlock(char* ptr, int size) 35 : _ptr(ptr), _size(size){} 36 37 std::unique_ptr<char[]> _ptr; 38 int _size = 0; 39 }; 40 41 class __MemCache 42 { 43 private: 44 __MemCache(){} 45 ~__MemCache(){} 46 47 private: 48 inline void Create(int size) { size = __Align(size); _cache.emplace(new char[size], size); } 49 50 //@return list. 51 __Block* Apply(int& block_size, int& count); 52 53 private: 54 friend class MemPool; 55 List<__CacheBlock> _cache; 56 }; 57 58 class MemPool 59 { 60 61 public: 62 MemPool(); 63 ~MemPool(); 64 65 public: 66 void* Alloc(int size); 67 template<typename T> void* Alloc() { return Alloc(sizeof(T)); } 68 69 void Free(void* ptr, int size); 70 template<typename T> void Free(T* ptr) { Free(ptr, sizeof(T)); } 71 72 private: 73 void Fill(int index, int count); 74 75 private: 76 __MemCache _mem_cache; 77 __Block* _free[BLOCK_CAP]; 78 }; 79 80 }; 81 82 #endif //!__MEM_POOL_H_
mempool.cpp
1 #include "mempool.h" 2 3 #define DEFAULT_EACH_BLOCK_STORE 16 4 5 namespace LC 6 { 7 8 __Block* __MemCache::Apply(int& block_size, int& count) 9 { 10 block_size = __Align(block_size); 11 int need_size = block_size * count; 12 13 { 14 int def_size = block_size * DEFAULT_EACH_BLOCK_STORE; 15 16 auto* node = _cache.begin(); 17 if(node == nullptr || node->data()._size <= 0) 18 Create(need_size > def_size ? need_size : def_size); 19 } 20 21 __CacheBlock& block = _cache.begin()->data(); 22 char* ptr = block._ptr.get(); 23 int size = block._size; 24 25 if(size <= block_size) 26 { 27 block_size = size; 28 count = 1; 29 return (__Block*)(ptr); 30 } 31 32 __Block* ret = nullptr; 33 int ret_count = 0; 34 for (;size >= block_size;) 35 { 36 char* block_ptr = ptr + size - block_size; 37 38 if(ret == nullptr) 39 ret = (__Block*)(block_ptr); 40 else 41 { 42 ret->_next = (__Block*)(block_ptr); 43 ret = ret->_next; 44 } 45 46 size -= block_size; 47 ++ret_count; 48 49 if(ret_count >= count) 50 { 51 count = ret_count; 52 return ret; 53 } 54 } 55 return ret; 56 } 57 58 MemPool::MemPool() 59 { 60 std::memset(_free, 0, sizeof(_free)); 61 } 62 63 MemPool::~MemPool() 64 { 65 } 66 67 void MemPool::Fill(int index, int count) 68 { 69 int size = __Sit(index); 70 __Block* list = _mem_cache.Apply(size, count); 71 72 __Block*& p = _free[__Index(size)]; 73 list->_next = p; 74 p = list; 75 } 76 77 void* MemPool::Alloc(int size) 78 { 79 if(size > BLOCK_MAX) 80 return malloc(size); 81 82 if(size <= 0) 83 return nullptr; 84 85 LABLE_ALLOC: 86 const int index = __Index(size); 87 __Block* block = _free[index]; 88 if(block == nullptr) 89 { 90 Fill(index, DEFAULT_EACH_BLOCK_STORE); 91 goto LABLE_ALLOC; 92 } 93 94 block = _free[index]; 95 _free[index] = block->_next; 96 return block; 97 } 98 99 void MemPool::Free(void* ptr, int size) 100 { 101 if(ptr == nullptr) 102 return; 103 104 if(size > BLOCK_MAX) 105 { 106 free(ptr); 107 return; 108 } 109 110 const int index = __Index(size); 111 __Block* block = (__Block*)(ptr); 112 block->_next = _free[index]; 113 _free[index] = block; 114 } 115 116 };
list.h
1 #pragma once 2 3 #ifndef __LC_LIST_H 4 #define __LC_LIST_H 5 6 namespace LC 7 { 8 9 template<typename T> 10 class Node final 11 { 12 public: 13 Node(){} 14 explicit Node(Node<T>* next, T&& data) noexcept : _data(std::move(data)), _next(next) {} 15 explicit Node(Node<T>* next, const T& data) noexcept : _data(data), _next(next) {} 16 explicit Node(Node<T>* pre, Node<T>* next, const T& data) noexcept : _pre(pre), _data(data), _next(next) {} 17 18 public: 19 inline T& data() noexcept { return _data; } 20 21 template <typename... TArgs> 22 inline void emplace(TArgs&& ...args){ new(&_data)T(args...); } 23 24 inline void pack(T&& data) noexcept { _data = std::move(data); } 25 inline void pack(const T& data) noexcept { _data = data; } 26 27 inline void link(Node<T>* next) noexcept { _next = next; if(next != nullptr) next->_pre = this; } 28 29 public: 30 T _data; 31 Node<T>* _next = nullptr; 32 Node<T>* _pre = nullptr; 33 }; 34 35 template<typename T> 36 class List 37 { 38 public: 39 List() {} //init head. 40 ~List() { while(_size > 0) pop(); } 41 42 public: 43 //insert at beginning. 44 bool push(Node<T>* node) 45 { 46 if(node == nullptr) 47 return false; 48 49 Node<T>* first = _root._next; 50 _root.link(node); 51 node->link(first); 52 ++_size; 53 return true; 54 } 55 56 bool insert(const T& data) 57 { 58 Node<T>* ins = alloc(); 59 if(ins == nullptr) 60 return false; 61 62 ins->pack(data); 63 64 return push(ins); 65 }; 66 67 bool insert(T&& data) 68 { 69 Node<T>* ins = alloc(); 70 71 if(ins == nullptr) 72 return false; 73 74 ins->pack(std::move(data)); 75 76 return push(ins); 77 }; 78 79 template<typename... TArgs> 80 bool emplace(TArgs&& ...args) 81 { 82 Node<T>* ins = alloc(args...); 83 Node<T>* first = nullptr; 84 if(ins == nullptr) return false; 85 86 return push(ins); 87 } 88 89 inline Node<T>* begin() noexcept { return _root._next; } 90 inline void pop() noexcept 91 { 92 delete pop_not_free(); 93 } 94 95 inline Node<T>* pop_not_free() noexcept 96 { 97 Node<T>* first = begin(); 98 if(first == nullptr) 99 return nullptr; 100 101 Node<T>* second = first->_next; 102 _root.link(second); 103 --_size; 104 105 return first; 106 } 107 108 inline void erase(Node<T>* node) noexcept 109 { 110 if(node == nullptr || node->_pre == nullptr) 111 return; 112 113 node->_pre->link(node->_next); 114 --_size; 115 delete node; 116 } 117 118 inline size_t size() const noexcept { return _size; } 119 120 private: 121 template<typename... TArgs> 122 inline Node<T>* alloc(TArgs&& ...args) 123 { 124 Node<T>* ret = new(std::nothrow) Node<T>(); 125 if(ret != nullptr) ret->emplace(args...); 126 return ret; 127 } 128 129 inline Node<T>* alloc() { return new(std::nothrow) Node<T>(); } 130 131 public: 132 Node<T> _root; 133 size_t _size = 0; 134 }; 135 136 }; // namespace LC 137 #endif
list.cpp
1 //这儿啥也没有
main.cpp
1 #include <iostream> 2 #include <list> 3 #include "list.h" 4 #include <time.h> 5 #include "mempool.h" 6 #include <vector> 7 8 using namespace LC; 9 10 struct meminfo 11 { 12 meminfo(void* p, int s) : _p(p), _size(s){} 13 void* _p; 14 int _size; 15 }; 16 17 18 int main() 19 { 20 std::list<int> aa; 21 LC::List<int> bb; 22 23 int64_t b = clock(); 24 for (int i = 0; i < 10000; ++i) 25 { 26 aa.insert(aa.begin(), i); 27 } 28 std::cout << "std::list<int> aa insert: " << clock() - b << std::endl; 29 30 b = clock(); 31 for (int i = 0; i < 10000; ++i) 32 { 33 bb.insert(i); 34 } 35 std::cout << "LC::List<int> bb insert: " << clock() - b << std::endl; 36 37 b = clock(); 38 for (int i = 0; i < 10000; ++i) 39 { 40 aa.erase(aa.begin()); 41 } 42 std::cout << "std::list<int> aa pop: " << clock() - b << std::endl; 43 44 b = clock(); 45 for (int i = 0; i < 10000; ++i) 46 { 47 bb.pop(); 48 } 49 std::cout << "LC::List<int> bb pop: " << clock() - b << std::endl; 50 51 LC::MemPool mempool; 52 std::vector<meminfo> mems1, mems2; 53 54 const int count = 10000; 55 56 for (size_t i = 0; i < 100; i++) 57 { 58 std::cout << i << " : " << __Index(i) << std::endl; 59 std::cout << __Index(i) << " -> " << __Sit(__Index(i)) << std::endl; 60 } 61 62 b = clock(); 63 for (int i = 0; i < count; ++i) 64 { 65 int size = (rand() + 1) % BLOCK_MAX; 66 void* p = mempool.Alloc(size); 67 std::memset(p, 0, size); 68 mems1.emplace_back(p, size); 69 } 70 std::cout << "mempool alloc: " << clock() - b << std::endl; 71 72 b = clock(); 73 for (int i = 0; i < count; ++i) 74 { 75 int size = (rand() + 1) % BLOCK_MAX; 76 void* p = malloc(size); 77 std::memset(p, 0, size); 78 mems2.emplace_back(p, size); 79 } 80 std::cout << "malloc: " << clock() - b << std::endl; 81 82 b = clock(); 83 for (int i = 0; i < mems1.size(); ++i) 84 { 85 mempool.Free(mems1[i]._p, mems1[i]._size); 86 } 87 std::cout << "mempool free: " << clock() - b << std::endl; 88 89 b = clock(); 90 for (int i = 0; i < mems2.size(); ++i) 91 { 92 free(mems2[i]._p); 93 } 94 std::cout << "free: " << clock() - b << std::endl; 95 96 std::unique_ptr<int> ptrInt(new int(1)); 97 int* p = ptrInt.get(); 98 99 return 0; 100 }