-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathPageCache.cpp
More file actions
149 lines (149 loc) · 4.68 KB
/
Copy pathPageCache.cpp
File metadata and controls
149 lines (149 loc) · 4.68 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
#include"PageCache.h"
#include<assert.h>
PageCache PageCache::m_instance; // 静态变量的定义
Span* PageCache::NewSpan(size_t k)
{
if (k == 0) throw(PageCacheException("Function NewSpan: Alloc pages is 0\n"));
// 大于NPAGES页的内存不挂载进PageCache
// 但大于MAX_BYTES>>PAGE_SHIFT页小于NPAGES页的要挂载进PageCache
if (k > NPAGES - 1)
{
void* ptr = SystemAlloc(k);
// Span* span = new Span;
Span* span = m_spanPool.New();
span->m_pageId = reinterpret_cast<PAGE_ID>(ptr) >> PAGE_SHIFT;
// m_idSpanMap[span->m_pageId] = span;
m_idSpanMap.set(span->m_pageId, span);
span->m_n = k;
return span;
}
// 先检查第k个桶里面有没有Span
if (m_spanLists[k].Empty() == false)
{
Span* kSpan = m_spanLists[k].PopFront();
// 建立id和Span的映射,方便CentralCache回收小块内存时,查找对应的Span
for (int i = 0; i < kSpan->m_n; i++)
{
// m_idSpanMap[kSpan->m_pageId + i] = kSpan;
m_idSpanMap.set(kSpan->m_pageId+i, kSpan);
}
return kSpan;
}
// 检查一下后面的桶里面有没有Span,如果有就进行切分
for (int i = k + 1; i < NPAGES; i++)
{
if (m_spanLists[i].Empty() == false)
{
// 此处只修改Span的起始页号,切分Span并存入m_freelists在CentralCache::GetOneSpan进行
Span* nSpan = m_spanLists[i].PopFront();
// Span* kSpan = new Span;
Span* kSpan = m_spanPool.New();
kSpan->m_pageId = nSpan->m_pageId;
kSpan->m_n = k;
nSpan->m_pageId += k;
nSpan->m_n -= k;
m_spanLists[nSpan->m_n].PushFront(nSpan);
// 建立id和Span的映射,方便CentralCache回收小块内存时,查找对应的Span
for (int i = 0; i < kSpan->m_n; i++)
{
// m_idSpanMap[kSpan->m_pageId + i] = kSpan;
m_idSpanMap.set(kSpan->m_pageId + i, kSpan);
}
// 建立nSpan首尾页号的映射,方便将Span回收进PageCache时的查找
// m_idSpanMap[nSpan->m_pageId] = nSpan;
// m_idSpanMap[nSpan->m_pageId+nSpan->m_n-1] = nSpan;
m_idSpanMap.set(nSpan->m_pageId, nSpan);
m_idSpanMap.set(nSpan->m_pageId + nSpan->m_n-1, nSpan);
return kSpan;
}
}
// 不存在大块的Span,无法进行切分,直接向堆申请128页的Span
// Span* bigSpan = new Span;
Span* bigSpan = m_spanPool.New();
void* ptr = SystemAlloc(NPAGES - 1);
bigSpan->m_pageId = (PAGE_ID)ptr >> PAGE_SHIFT;
bigSpan->m_n = NPAGES - 1;
m_spanLists[bigSpan->m_n].PushFront(bigSpan);
return NewSpan(k);
}
std::mutex* PageCache::GetMutex()
{
return &m_pageMtx;
}
Span* PageCache::MapObjectToSpan(void* obj)
{
// std::unique_lock<std::mutex> lock(m_pageMtx);
PAGE_ID id = (PAGE_ID)obj >> PAGE_SHIFT; // 算出obj小内存对应的页号
auto ret = m_idSpanMap.get(id);
if (ret != nullptr)
{
return reinterpret_cast<Span*>(ret);
}
else
{
throw(PageCacheException("Function MapObjectToSpan: Span not found!\n"));
// assert(false);
}
return nullptr;
}
void PageCache::ReleaseSpanToPageCache(Span* span)
{
// 对span前后的页尝试进行合并,缓解内存外碎片的问题
// 大于NPAGES-1页的,直接还给堆
if (span->m_n > NPAGES - 1)
{
void* ptr =reinterpret_cast<void*>(span->m_pageId << PAGE_SHIFT);
SystemFree(ptr);
// delete span;
m_spanPool.Delete(span);
return;
}
else
{
while (1)
{
PAGE_ID prevId = span->m_pageId - 1;
Span* ret =reinterpret_cast<Span*>(m_idSpanMap.get(prevId));
// 如果prevId没有对应的Span,则不合并
if (ret ==nullptr) break;
// 如果prevId对应的Span正在使用,则不合并
if (ret->m_isuse == true) break;
// 如果合并后超过了128页,则不合并
if (ret->m_n + span->m_n > NPAGES - 1) break;
Span* prevSpan = ret;
span->m_n += prevSpan->m_n;
span->m_pageId = prevSpan->m_pageId;
// 将prevSpan从PageCache中删除
m_spanLists[prevSpan->m_n].Erase(prevSpan);
// 此处delete是将向内存申请的span的内存空间还回去
// 而不是将span管理的m_freelist的内存还回去
// delete prevSpan;
m_spanPool.Delete(prevSpan);
}
while (1)
{
PAGE_ID nextId = span->m_pageId + span->m_n;
Span* ret = reinterpret_cast<Span*>(m_idSpanMap.get(nextId));
// 如果nextId没有对应的Span,则不合并
if (ret == nullptr) break;
// 如果nextId对应的Span正在使用,则不合并
if (ret->m_isuse == true) break;
// 如果合并后超过了128页,则不合并
if (ret->m_n + span->m_n > NPAGES - 1) break;
Span* nextSpan = ret;
span->m_n += nextSpan->m_n;
// 将prevSpan从PageCache中删除
m_spanLists[nextSpan->m_n].Erase(nextSpan);
// 此处delete是将向内存申请的span的内存空间还回去
// 而不是将span管理的m_freelist的内存还回去
// delete nextSpan;
m_spanPool.Delete(nextSpan);
}
m_spanLists[span->m_n].PushFront(span);
span->m_isuse = false;
// m_idSpanMap[span->m_pageId] = span;
// m_idSpanMap[span->m_pageId + span->m_n - 1] = span;
m_idSpanMap.set(span->m_pageId, span);
m_idSpanMap.set(span->m_pageId + span->m_n - 1, span);
}
}