SpiecsEngine
 
Loading...
Searching...
No Matches
PageCache.cpp
Go to the documentation of this file.
1/**
2* @file PageCache.cpp.
3* @brief The PageCache Class Implementation.
4* @author tcmalloc.
5*/
6
7#include "Pchheader.h"
8#include "PageCache.h"
9
10namespace Spices {
11
13
15 {
16 std::unique_lock<std::mutex> lock(m_Mutex);
17
18 return InternalNewSpan(k);
19 }
20
21 scl::span* PageCache::MapObjectToSpan(void* obj) const
22 {
23 /**
24 * @brief Get page id by memory.
25 */
26 const size_t id = (reinterpret_cast<size_t>(obj) >> MemoryPool::PAGE_SHIFT);
27
28 /**
29 * @brief Find span in map.
30 */
31 void* s = m_IdSpanMap.get(id);
32
33 if (s)
34 {
35 return static_cast<scl::span*>(s);
36 }
37 else
38 {
39 return nullptr;
40 }
41 }
42
44 {
45 std::unique_lock<std::mutex> lock(m_Mutex);
46
47 /**
48 * @brief Release to system.
49 */
50 if (s->m_NPages > MemoryPool::PAGE_NUM - 1)
51 {
52 void* ptr = reinterpret_cast<void*>(s->m_PageId << MemoryPool::PAGE_SHIFT);
53 SystemFree(ptr);
54
55 m_IdSpanMap.set(s->m_PageId, nullptr);
56 m_SpanPool.Delete(s);
57
58 return;
59 }
60
61 /**
62 * @brief Merge to left.
63 */
64 for(;;)
65 {
66 const size_t leftId = s->m_PageId - 1;
67
68 scl::span* leftSpan = static_cast<scl::span*>(m_IdSpanMap.get(leftId));
69
70 if (!leftSpan)
71 {
72 break;
73 }
74
75 if (leftSpan->m_IsUse)
76 {
77 break;
78 }
79
80 if (leftSpan->m_NPages + s->m_NPages > MemoryPool::PAGE_NUM - 1)
81 {
82 break;
83 }
84
85 s->m_PageId = leftSpan->m_PageId;
86 s->m_NPages += leftSpan->m_NPages;
87
88 m_SpanLists[leftSpan->m_NPages].Erase(leftSpan);
89 m_SpanPool.Delete(leftSpan);
90 }
91
92 /**
93 * @brief Merge to right.
94 */
95 for (;;)
96 {
97 const size_t rightId = s->m_PageId + s->m_NPages;
98
99 scl::span* rightSpan = static_cast<scl::span*>(m_IdSpanMap.get(rightId));
100
101 if (!rightSpan)
102 {
103 break;
104 }
105
106 if (rightSpan->m_IsUse)
107 {
108 break;
109 }
110
111 if (rightSpan->m_NPages + s->m_NPages > MemoryPool::PAGE_NUM - 1)
112 {
113 break;
114 }
115
116 s->m_NPages += rightSpan->m_NPages;
117
118 m_SpanLists[rightSpan->m_NPages].Erase(rightSpan);
119 m_SpanPool.Delete(rightSpan);
120 }
121
122 /**
123 * @brief Push span to list.
124 */
125 m_SpanLists[s->m_NPages].PushFront(s);
126 s->m_IsUse = false;
127
128 m_IdSpanMap.set(s->m_PageId, s);
129 m_IdSpanMap.set(s->m_PageId + s->m_NPages - 1, s);
130 }
131
133 {
134 assert(k > 0);
135
136 /**
137 * @brief Allocate from system.
138 */
139 if (k > MemoryPool::PAGE_NUM - 1)
140 {
141 void* ptr = SystemAlloc(k);
142 scl::span* s = m_SpanPool.New();
143 s->m_PageId = reinterpret_cast<size_t>(ptr) >> MemoryPool::PAGE_SHIFT;
144 s->m_NPages = k;
145 s->m_BlockSize = k * (1 << MemoryPool::PAGE_SHIFT);
146
147 m_IdSpanMap.set(s->m_PageId, s);
148
149 return s;
150 }
151
152 /**
153 * @brief Has empty pages in pc.
154 */
155 if (!m_SpanLists[k].Empty())
156 {
157 /**
158 * @brief Pop a span.
159 */
160 scl::span* s = m_SpanLists[k].PopFront();
161 s->m_BlockSize = k * (1 << MemoryPool::PAGE_SHIFT);
162
163 for (size_t i = 0; i < s->m_NPages; ++i)
164 {
165 m_IdSpanMap.set(s->m_PageId + i, s);
166 }
167
168 return s;
169 }
170
171 /**
172 * @brief Iter begger span, try find spare pages in pc.
173 */
174 for (size_t i = k + 1; i < MemoryPool::PAGE_NUM; ++i)
175 {
176 if (!m_SpanLists[i].Empty())
177 {
178 /**
179 * @brief Pop a span.
180 */
181 scl::span* nSpan = m_SpanLists[i].PopFront();
182
183 /**
184 * @brief New a span to split bigger span.
185 */
186 scl::span* kSpan = m_SpanPool.New();
187 kSpan->m_PageId = nSpan->m_PageId;
188 kSpan->m_NPages = k;
189 kSpan->m_BlockSize = (1 << MemoryPool::PAGE_SHIFT) * k;
190
191 nSpan->m_PageId += k;
192 nSpan->m_NPages -= k;
193 nSpan->m_BlockSize = (1 << MemoryPool::PAGE_SHIFT) * nSpan->m_NPages;
194
195 /**
196 * @brief Push splited span to list.
197 */
198 m_SpanLists[nSpan->m_NPages].PushFront(nSpan);
199
200 m_IdSpanMap.set(nSpan->m_PageId, nSpan);
201 m_IdSpanMap.set(nSpan->m_PageId + nSpan->m_NPages - 1, nSpan);
202
203 for (size_t j = 0; j < kSpan->m_NPages; ++j)
204 {
205 m_IdSpanMap.set(kSpan->m_PageId + j, kSpan);
206 }
207
208 return kSpan;
209 }
210 }
211
212 /**
213 * @brief Allocate memory from system if no spare pages in pc.
214 */
215 void* ptr = SystemAlloc(MemoryPool::PAGE_NUM - 1);
216
217 /**
218 * @brief New a span to mamage this memory.
219 */
220 scl::span* bigSpan = m_SpanPool.New();
221 bigSpan->m_PageId = reinterpret_cast<size_t>(ptr) >> MemoryPool::PAGE_SHIFT;
222 bigSpan->m_NPages = MemoryPool::PAGE_NUM - 1;
223 bigSpan->m_BlockSize = (1 << MemoryPool::PAGE_SHIFT) * bigSpan->m_NPages;
224
225 /**
226 * @brief Push span to list.
227 */
228 m_SpanLists[MemoryPool::PAGE_NUM - 1].PushFront(bigSpan);
229
230 return InternalNewSpan(k);
231 }
232}
static PageCache m_PageCache
this single instance.
Definition PageCache.h:86
scl::span * MapObjectToSpan(void *obj) const
Find span by memory pointer.
Definition PageCache.cpp:21
scl::span * InternalNewSpan(size_t k)
Fetch pages span(internal call).
void ReleaseSpanToPageCache(scl::span *s)
Release span from cc to pc,.
Definition PageCache.cpp:43
scl::span * NewSpan(size_t k)
Fetch pages span.
Definition PageCache.cpp:14
Page memory cache. Third level of memory allocator.
Definition PageCache.h:21
bool m_IsUse
True if in use.
Definition SpanList.h:61
Used for manage multiple page memory.
Definition SpanList.h:15
static void SystemFree(void *ptr)
Free memory to system.
Definition MemoryPool.h:133