Skip to content

Commit d42b9b1

Browse files
committed
feat(common): 为 Value、IxNodeHandle 和 RmRecord 类添加自定义内存分配器
- 在这些类中重载了 new 和 delete 操作符 - 使用 MemoryPool 实现内存池管理,以提高内存分配和释放的效率 - 注释掉了原有的 malloc 和 free 调用
1 parent 8e99d4e commit d42b9b1

4 files changed

Lines changed: 267 additions & 0 deletions

File tree

Lines changed: 235 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,235 @@
1+
/*-
2+
* Copyright (c) 2013 Cosku Acay, http://www.coskuacay.com
3+
*
4+
* Permission is hereby granted, free of charge, to any person obtaining a
5+
* copy of this software and associated documentation files (the "Software"),
6+
* to deal in the Software without restriction, including without limitation
7+
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
8+
* and/or sell copies of the Software, and to permit persons to whom the
9+
* Software is furnished to do so, subject to the following conditions:
10+
*
11+
* The above copyright notice and this permission notice shall be included in
12+
* all copies or substantial portions of the Software.
13+
*
14+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19+
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
20+
* IN THE SOFTWARE.
21+
*/
22+
23+
#ifndef MEMORY_POOL_HPP
24+
#define MEMORY_POOL_HPP
25+
26+
#include <climits>
27+
#include <cstddef>
28+
29+
template <typename T, size_t BlockSize = 4096>
30+
class MemoryPool {
31+
public:
32+
/* Member types */
33+
typedef T value_type;
34+
typedef T* pointer;
35+
typedef T& reference;
36+
typedef const T* const_pointer;
37+
typedef const T& const_reference;
38+
typedef size_t size_type;
39+
typedef ptrdiff_t difference_type;
40+
typedef std::false_type propagate_on_container_copy_assignment;
41+
typedef std::true_type propagate_on_container_move_assignment;
42+
typedef std::true_type propagate_on_container_swap;
43+
44+
template <typename U>
45+
struct rebind {
46+
typedef MemoryPool<U> other;
47+
};
48+
49+
/* Member functions */
50+
MemoryPool() noexcept;
51+
MemoryPool(const MemoryPool& memoryPool) noexcept;
52+
MemoryPool(MemoryPool&& memoryPool) noexcept;
53+
template <class U>
54+
MemoryPool(const MemoryPool<U>& memoryPool) noexcept;
55+
56+
~MemoryPool() noexcept;
57+
58+
MemoryPool& operator=(const MemoryPool& memoryPool) = delete;
59+
MemoryPool& operator=(MemoryPool&& memoryPool) noexcept;
60+
61+
pointer address(reference x) const noexcept;
62+
const_pointer address(const_reference x) const noexcept;
63+
64+
// Can only allocate one object at a time. n and hint are ignored
65+
pointer allocate(size_type n = 1, const_pointer hint = 0);
66+
void deallocate(pointer p, size_type n = 1);
67+
68+
size_type max_size() const noexcept;
69+
70+
template <class U, class... Args>
71+
void construct(U* p, Args&&... args);
72+
template <class U>
73+
void destroy(U* p);
74+
75+
template <class... Args>
76+
pointer newElement(Args&&... args);
77+
void deleteElement(pointer p);
78+
79+
static MemoryPool* getInstance() {
80+
thread_local static MemoryPool instance;
81+
return &instance;
82+
}
83+
84+
private:
85+
union Slot_ {
86+
value_type element;
87+
Slot_* next;
88+
};
89+
90+
typedef char* data_pointer_;
91+
typedef Slot_ slot_type_;
92+
typedef Slot_* slot_pointer_;
93+
94+
slot_pointer_ currentBlock_;
95+
slot_pointer_ currentSlot_;
96+
slot_pointer_ lastSlot_;
97+
slot_pointer_ freeSlots_;
98+
99+
size_type padPointer(data_pointer_ p, size_type align) const noexcept;
100+
void allocateBlock();
101+
102+
static_assert(BlockSize >= 2 * sizeof(slot_type_), "BlockSize too small.");
103+
};
104+
105+
template <typename T, size_t BlockSize>
106+
inline typename MemoryPool<T, BlockSize>::size_type MemoryPool<T, BlockSize>::padPointer(
107+
data_pointer_ p, size_type align) const noexcept {
108+
uintptr_t result = reinterpret_cast<uintptr_t>(p);
109+
return ((align - result) % align);
110+
}
111+
112+
template <typename T, size_t BlockSize>
113+
MemoryPool<T, BlockSize>::MemoryPool() noexcept {
114+
currentBlock_ = nullptr;
115+
currentSlot_ = nullptr;
116+
lastSlot_ = nullptr;
117+
freeSlots_ = nullptr;
118+
}
119+
120+
template <typename T, size_t BlockSize>
121+
MemoryPool<T, BlockSize>::MemoryPool(const MemoryPool& memoryPool) noexcept : MemoryPool() {}
122+
123+
template <typename T, size_t BlockSize>
124+
MemoryPool<T, BlockSize>::MemoryPool(MemoryPool&& memoryPool) noexcept {
125+
currentBlock_ = memoryPool.currentBlock_;
126+
memoryPool.currentBlock_ = nullptr;
127+
currentSlot_ = memoryPool.currentSlot_;
128+
lastSlot_ = memoryPool.lastSlot_;
129+
freeSlots_ = memoryPool.freeSlots;
130+
}
131+
132+
template <typename T, size_t BlockSize>
133+
template <class U>
134+
MemoryPool<T, BlockSize>::MemoryPool(const MemoryPool<U>& memoryPool) noexcept : MemoryPool() {}
135+
136+
template <typename T, size_t BlockSize>
137+
MemoryPool<T, BlockSize>& MemoryPool<T, BlockSize>::operator=(MemoryPool&& memoryPool) noexcept {
138+
if (this != &memoryPool) {
139+
std::swap(currentBlock_, memoryPool.currentBlock_);
140+
currentSlot_ = memoryPool.currentSlot_;
141+
lastSlot_ = memoryPool.lastSlot_;
142+
freeSlots_ = memoryPool.freeSlots;
143+
}
144+
return *this;
145+
}
146+
147+
template <typename T, size_t BlockSize>
148+
MemoryPool<T, BlockSize>::~MemoryPool() noexcept {
149+
slot_pointer_ curr = currentBlock_;
150+
while (curr != nullptr) {
151+
slot_pointer_ prev = curr->next;
152+
operator delete(reinterpret_cast<void*>(curr));
153+
curr = prev;
154+
}
155+
}
156+
157+
template <typename T, size_t BlockSize>
158+
inline typename MemoryPool<T, BlockSize>::pointer MemoryPool<T, BlockSize>::address(reference x) const noexcept {
159+
return &x;
160+
}
161+
162+
template <typename T, size_t BlockSize>
163+
inline typename MemoryPool<T, BlockSize>::const_pointer MemoryPool<T, BlockSize>::address(
164+
const_reference x) const noexcept {
165+
return &x;
166+
}
167+
168+
template <typename T, size_t BlockSize>
169+
void MemoryPool<T, BlockSize>::allocateBlock() {
170+
// Allocate space for the new block and store a pointer to the previous one
171+
data_pointer_ newBlock = reinterpret_cast<data_pointer_>(operator new(BlockSize));
172+
reinterpret_cast<slot_pointer_>(newBlock)->next = currentBlock_;
173+
currentBlock_ = reinterpret_cast<slot_pointer_>(newBlock);
174+
// Pad block body to staisfy the alignment requirements for elements
175+
data_pointer_ body = newBlock + sizeof(slot_pointer_);
176+
size_type bodyPadding = padPointer(body, alignof(slot_type_));
177+
currentSlot_ = reinterpret_cast<slot_pointer_>(body + bodyPadding);
178+
lastSlot_ = reinterpret_cast<slot_pointer_>(newBlock + BlockSize - sizeof(slot_type_) + 1);
179+
}
180+
181+
template <typename T, size_t BlockSize>
182+
inline typename MemoryPool<T, BlockSize>::pointer MemoryPool<T, BlockSize>::allocate(size_type n, const_pointer hint) {
183+
if (freeSlots_ != nullptr) {
184+
pointer result = reinterpret_cast<pointer>(freeSlots_);
185+
freeSlots_ = freeSlots_->next;
186+
return result;
187+
} else {
188+
if (currentSlot_ >= lastSlot_) allocateBlock();
189+
return reinterpret_cast<pointer>(currentSlot_++);
190+
}
191+
}
192+
193+
template <typename T, size_t BlockSize>
194+
inline void MemoryPool<T, BlockSize>::deallocate(pointer p, size_type n) {
195+
if (p != nullptr) {
196+
reinterpret_cast<slot_pointer_>(p)->next = freeSlots_;
197+
freeSlots_ = reinterpret_cast<slot_pointer_>(p);
198+
}
199+
}
200+
201+
template <typename T, size_t BlockSize>
202+
inline typename MemoryPool<T, BlockSize>::size_type MemoryPool<T, BlockSize>::max_size() const noexcept {
203+
size_type maxBlocks = -1 / BlockSize;
204+
return (BlockSize - sizeof(data_pointer_)) / sizeof(slot_type_) * maxBlocks;
205+
}
206+
207+
template <typename T, size_t BlockSize>
208+
template <class U, class... Args>
209+
inline void MemoryPool<T, BlockSize>::construct(U* p, Args&&... args) {
210+
new (p) U(std::forward<Args>(args)...);
211+
}
212+
213+
template <typename T, size_t BlockSize>
214+
template <class U>
215+
inline void MemoryPool<T, BlockSize>::destroy(U* p) {
216+
p->~U();
217+
}
218+
219+
template <typename T, size_t BlockSize>
220+
template <class... Args>
221+
inline typename MemoryPool<T, BlockSize>::pointer MemoryPool<T, BlockSize>::newElement(Args&&... args) {
222+
pointer result = allocate();
223+
construct<value_type>(result, std::forward<Args>(args)...);
224+
return result;
225+
}
226+
227+
template <typename T, size_t BlockSize>
228+
inline void MemoryPool<T, BlockSize>::deleteElement(pointer p) {
229+
if (p != nullptr) {
230+
p->~value_type();
231+
deallocate(p);
232+
}
233+
}
234+
235+
#endif // MEMORY_POOL_HPP

src/common/common.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -348,6 +348,16 @@ struct Value {
348348
return false;
349349
}
350350
}
351+
352+
void* operator new (size_t size) {
353+
return static_cast<void *>(MemoryPool<Value>::getInstance()->allocate(size));
354+
// return ::std::malloc(size);
355+
}
356+
357+
void operator delete (void *ptr) {
358+
MemoryPool<Value>::getInstance()->deallocate(static_cast<Value *>(ptr));
359+
// ::std::free(ptr);
360+
}
351361
};
352362

353363
// 前向声明 ArithExpr

src/index/ix_index_handle.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -293,6 +293,16 @@ class IxNodeHandle {
293293
}
294294
return key_value;
295295
}
296+
297+
void* operator new (size_t size) {
298+
return static_cast<void *>(MemoryPool<IxNodeHandle>::getInstance()->allocate(size));
299+
// return ::std::malloc(size);
300+
}
301+
302+
void operator delete (void *ptr) {
303+
MemoryPool<IxNodeHandle>::getInstance()->deallocate(static_cast<IxNodeHandle *>(ptr));
304+
// ::std::free(ptr);
305+
}
296306
};
297307

298308
/**

src/record/rm_defs.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@
2929

3030
#include "defs.h"
3131
#include "storage/buffer_pool_manager.h"
32+
#include "common/MemoryPool/MemoryPool.hpp"
33+
#include "common/getFunctionTime.h"
3234

3335
/** @brief 表示无效的页面号 */
3436
constexpr int RM_NO_PAGE = -1;
@@ -248,4 +250,14 @@ struct RmRecord {
248250
allocated_ = false;
249251
data = nullptr;
250252
}
253+
254+
void* operator new (size_t size) {
255+
return static_cast<void *>(MemoryPool<RmRecord>::getInstance()->allocate(size));
256+
// return ::std::malloc(size);
257+
}
258+
259+
void operator delete (void *ptr) {
260+
MemoryPool<RmRecord>::getInstance()->deallocate(static_cast<RmRecord *>(ptr));
261+
// ::std::free(ptr);
262+
}
251263
};

0 commit comments

Comments
 (0)