dl
dl_buffer_pool.h
浏览该文件的文档.
1
12#pragma once
13
14#include <vector>
15#include <cassert>
16
17namespace dl
18{
21 {
22 public:
23 // index、size仅做返回值(内存不会置0)
24 std::byte* Malloc(size_t new_size, size_t& index, size_t& size)
25 {
26 // 新大小所在index
27 size_t new_index = ToIndex(new_size);
28 index = new_index;
29 if (index == 16)
30 {// 需要的太大
31 size = new_size;
32 return (std::byte*)malloc(new_size);
33 }
34 size = ToSize(new_index);
35
36 return _allNode[index].Get(size);
37 }
38
39 // 传入旧地址、需求大小(不是2的幂)、所在index(返回新index),旧大小(返回新size)
40 // 保留旧内存值,新内存不置0
41 std::byte* Realloc(std::byte* p, size_t new_size, size_t& index, size_t& size)
42 {
43 assert(new_size > size);
44 assert(index <= 16);
45
46 // 新大小所在index
47 size_t new_index = ToIndex(new_size);
48 if (new_index == 16)
49 {// 需要的太大
50 if (index == 16)
51 {// 之前就是自由内存
52 size = new_size * 2;
53 return (std::byte*)realloc(p, size);
54 }
55 else
56 {// 之前是小内存
57 // 归还小内存,并且分配自由内存
58 _allNode[index].Put(p);
59
60 size_t old_size = size;
61 index = 16;
62 size = new_size;
63 std::byte* ret = (std::byte*)malloc(size);
64 memcpy(ret, p, old_size);
65 memset(ret + old_size, 0, size - old_size);
66 return ret;
67 }
68 }
69
70 // 新的是小内存
71 assert(index != 16 && index != new_index);// 之前不可能是自由内存 且不在同一空间
72
73
74 // 归还小内存,并且分配新的小内存(更大的)
75 _allNode[index].Put(p);
76
77 new_size = ToSize(new_index);
78 std::byte* ret = _allNode[new_index].Get(new_size);
79 memcpy(ret, p, size);
80 index = new_index;
81 size = new_size;
82 return ret;
83 }
84 void Free(std::byte* p, size_t index, size_t size)
85 {
86 if (index == 16)
87 {
88 free(p);
89 return;
90 }
91 _allNode[index].Put(p);
92 }
93 std::string Dump()
94 {
95 std::string ret = "--------------Buffer Pool--------------\n";
96 for (size_t i = 0; i < 16; ++i)
97 {
98 size_t size = ToSize(i);
99 std::string unit;
100 if (size < 1024)
101 unit = "byte";
102 else if(size < 1024 * 1024)
103 {
104 unit = "kb";
105 size /= 1024;
106 }
107 else
108 {
109 unit = "mb";
110 size /= 1024 * 1024;
111 }
112 ret += fmt::format("[{:02}] {:<3} {:<4} x {}\n", i, size, unit, _allNode[i]._memFree.size());
113 }
114 return ret;
115 }
116 size_t ToSize(size_t index)
117 {
118 switch (index)
119 {
120 case 0: return 256;
121 case 1: return 512;
122 case 2: return 1024;
123 case 3: return 2048;
124 case 4: return 4096;
125 case 5: return 8192;
126 case 6: return 16384;
127 case 7: return 32768;
128 case 8: return 65536;
129 case 9: return 131072;
130 case 10: return 262144;
131 case 11: return 524288;
132 case 12: return 1048576;
133 case 13: return 2097152;
134 case 14: return 4194304;
135 case 15: return 8388608;
136 default: return 0;
137 }
138 }
139 size_t ToIndex(size_t size)
140 {
141 if (size <= 256) return 0;
142 if (size <= 512) return 1;
143 if (size <= 1024) return 2;
144 if (size <= 2048) return 3;
145 if (size <= 4096) return 4;
146 if (size <= 8192) return 5;
147 if (size <= 16384) return 6;
148 if (size <= 32768) return 7;
149 if (size <= 65536) return 8;
150 if (size <= 131072) return 9;
151 if (size <= 262144) return 10;
152 if (size <= 524288) return 11;
153 if (size <= 1048576) return 12;
154 if (size <= 2097152) return 13;
155 if (size <= 4194304) return 14;
156 if (size <= 8388608) return 15;
157 return 16;
158 }
160 _allNode{}
161 {
162 }
164 {
165 for (auto& iter : _allNode)
166 {
167 while (!iter._memFree.empty())
168 {
169 free(iter._memFree.top());
170 iter._memFree.pop();
171 }
172 }
173 }
174 private:
175
176 class Node
177 {
178 public:
179 std::byte* Get(size_t size)
180 {
181 std::lock_guard guard{ _mutex };
182 if (_memFree.empty())
183 return (std::byte*)malloc(size);
184 else
185 {
186 std::byte* ret = _memFree.top();
187 _memFree.pop();
188 return ret;
189 }
190 }
191 void Put(std::byte* p)
192 {
193 std::lock_guard guard{ _mutex };
194 _memFree.push(p);
195 }
196 std::stack<std::byte*> _memFree;
197 std::mutex _mutex;
198 };
199 std::array<Node, 16> _allNode;
200 };
201
203}
void Free(std::byte *p, size_t index, size_t size)
size_t ToSize(size_t index)
std::byte * Realloc(std::byte *p, size_t new_size, size_t &index, size_t &size)
size_t ToIndex(size_t size)
std::byte * Malloc(size_t new_size, size_t &index, size_t &size)
BufferPool g_bufferPool