C/C++教程

C++ 基础 内存池

本文主要是介绍C++ 基础 内存池,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

别看了,写的过于垃圾。

就比默认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 }

 

这篇关于C++ 基础 内存池的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!