29 #include "gc/z/zStat.hpp" |
29 #include "gc/z/zStat.hpp" |
30 #include "logging/log.hpp" |
30 #include "logging/log.hpp" |
31 |
31 |
32 static const ZStatCounter ZCounterPageCacheHitL1("Memory", "Page Cache Hit L1", ZStatUnitOpsPerSecond); |
32 static const ZStatCounter ZCounterPageCacheHitL1("Memory", "Page Cache Hit L1", ZStatUnitOpsPerSecond); |
33 static const ZStatCounter ZCounterPageCacheHitL2("Memory", "Page Cache Hit L2", ZStatUnitOpsPerSecond); |
33 static const ZStatCounter ZCounterPageCacheHitL2("Memory", "Page Cache Hit L2", ZStatUnitOpsPerSecond); |
|
34 static const ZStatCounter ZCounterPageCacheHitL3("Memory", "Page Cache Hit L3", ZStatUnitOpsPerSecond); |
34 static const ZStatCounter ZCounterPageCacheMiss("Memory", "Page Cache Miss", ZStatUnitOpsPerSecond); |
35 static const ZStatCounter ZCounterPageCacheMiss("Memory", "Page Cache Miss", ZStatUnitOpsPerSecond); |
|
36 |
|
37 ZPageCacheFlushClosure::ZPageCacheFlushClosure(size_t requested) : |
|
38 _requested(requested), |
|
39 _flushed(0) {} |
|
40 |
|
41 size_t ZPageCacheFlushClosure::overflushed() const { |
|
42 return _flushed > _requested ? _flushed - _requested : 0; |
|
43 } |
35 |
44 |
36 ZPageCache::ZPageCache() : |
45 ZPageCache::ZPageCache() : |
37 _available(0), |
46 _available(0), |
38 _small(), |
47 _small(), |
39 _medium(), |
48 _medium(), |
65 } |
74 } |
66 |
75 |
67 remote_numa_id++; |
76 remote_numa_id++; |
68 } |
77 } |
69 |
78 |
70 ZStatInc(ZCounterPageCacheMiss); |
|
71 return NULL; |
79 return NULL; |
72 } |
80 } |
73 |
81 |
74 ZPage* ZPageCache::alloc_medium_page() { |
82 ZPage* ZPageCache::alloc_medium_page() { |
75 ZPage* const l1_page = _medium.remove_first(); |
83 ZPage* const page = _medium.remove_first(); |
76 if (l1_page != NULL) { |
84 if (page != NULL) { |
77 ZStatInc(ZCounterPageCacheHitL1); |
85 ZStatInc(ZCounterPageCacheHitL1); |
78 return l1_page; |
86 return page; |
79 } |
87 } |
80 |
88 |
81 ZStatInc(ZCounterPageCacheMiss); |
|
82 return NULL; |
89 return NULL; |
83 } |
90 } |
84 |
91 |
85 ZPage* ZPageCache::alloc_large_page(size_t size) { |
92 ZPage* ZPageCache::alloc_large_page(size_t size) { |
86 // Find a page with the right size |
93 // Find a page with the right size |
87 ZListIterator<ZPage> iter(&_large); |
94 ZListIterator<ZPage> iter(&_large); |
88 for (ZPage* l1_page; iter.next(&l1_page);) { |
95 for (ZPage* page; iter.next(&page);) { |
89 if (l1_page->size() == size) { |
96 if (size == page->size()) { |
90 // Page found |
97 // Page found |
91 _large.remove(l1_page); |
98 _large.remove(page); |
92 ZStatInc(ZCounterPageCacheHitL1); |
99 ZStatInc(ZCounterPageCacheHitL1); |
93 return l1_page; |
100 return page; |
94 } |
101 } |
95 } |
102 } |
96 |
103 |
97 ZStatInc(ZCounterPageCacheMiss); |
104 return NULL; |
98 return NULL; |
105 } |
|
106 |
|
107 ZPage* ZPageCache::alloc_oversized_medium_page(size_t size) { |
|
108 if (size <= ZPageSizeMedium) { |
|
109 return _medium.remove_first(); |
|
110 } |
|
111 |
|
112 return NULL; |
|
113 } |
|
114 |
|
115 ZPage* ZPageCache::alloc_oversized_large_page(size_t size) { |
|
116 // Find a page that is large enough |
|
117 ZListIterator<ZPage> iter(&_large); |
|
118 for (ZPage* page; iter.next(&page);) { |
|
119 if (size <= page->size()) { |
|
120 // Page found |
|
121 _large.remove(page); |
|
122 return page; |
|
123 } |
|
124 } |
|
125 |
|
126 return NULL; |
|
127 } |
|
128 |
|
129 ZPage* ZPageCache::alloc_oversized_page(size_t size) { |
|
130 ZPage* page = alloc_oversized_large_page(size); |
|
131 if (page == NULL) { |
|
132 page = alloc_oversized_medium_page(size); |
|
133 } |
|
134 |
|
135 if (page != NULL) { |
|
136 ZStatInc(ZCounterPageCacheHitL3); |
|
137 } |
|
138 |
|
139 return page; |
99 } |
140 } |
100 |
141 |
101 ZPage* ZPageCache::alloc_page(uint8_t type, size_t size) { |
142 ZPage* ZPageCache::alloc_page(uint8_t type, size_t size) { |
102 ZPage* page; |
143 ZPage* page; |
103 |
144 |
|
145 // Try allocate exact page |
104 if (type == ZPageTypeSmall) { |
146 if (type == ZPageTypeSmall) { |
105 page = alloc_small_page(); |
147 page = alloc_small_page(); |
106 } else if (type == ZPageTypeMedium) { |
148 } else if (type == ZPageTypeMedium) { |
107 page = alloc_medium_page(); |
149 page = alloc_medium_page(); |
108 } else { |
150 } else { |
109 page = alloc_large_page(size); |
151 page = alloc_large_page(size); |
110 } |
152 } |
111 |
153 |
|
154 if (page == NULL) { |
|
155 // Try allocate potentially oversized page |
|
156 ZPage* const oversized = alloc_oversized_page(size); |
|
157 if (oversized != NULL) { |
|
158 if (size < oversized->size()) { |
|
159 // Split oversized page |
|
160 page = oversized->split(type, size); |
|
161 |
|
162 // Cache remainder |
|
163 free_page_inner(oversized); |
|
164 } else { |
|
165 // Re-type correctly sized page |
|
166 page = oversized->retype(type); |
|
167 } |
|
168 } |
|
169 } |
|
170 |
112 if (page != NULL) { |
171 if (page != NULL) { |
113 _available -= page->size(); |
172 _available -= page->size(); |
|
173 } else { |
|
174 ZStatInc(ZCounterPageCacheMiss); |
114 } |
175 } |
115 |
176 |
116 return page; |
177 return page; |
117 } |
178 } |
118 |
179 |
119 void ZPageCache::free_page(ZPage* page) { |
180 void ZPageCache::free_page_inner(ZPage* page) { |
120 const uint8_t type = page->type(); |
181 const uint8_t type = page->type(); |
121 if (type == ZPageTypeSmall) { |
182 if (type == ZPageTypeSmall) { |
122 _small.get(page->numa_id()).insert_first(page); |
183 _small.get(page->numa_id()).insert_first(page); |
123 } else if (type == ZPageTypeMedium) { |
184 } else if (type == ZPageTypeMedium) { |
124 _medium.insert_first(page); |
185 _medium.insert_first(page); |
125 } else { |
186 } else { |
126 _large.insert_first(page); |
187 _large.insert_first(page); |
127 } |
188 } |
128 |
189 } |
|
190 |
|
191 void ZPageCache::free_page(ZPage* page) { |
|
192 free_page_inner(page); |
129 _available += page->size(); |
193 _available += page->size(); |
130 } |
194 } |
131 |
195 |
132 bool ZPageCache::flush_list_inner(ZPageCacheFlushClosure* cl, ZList<ZPage>* from, ZList<ZPage>* to) { |
196 bool ZPageCache::flush_list_inner(ZPageCacheFlushClosure* cl, ZList<ZPage>* from, ZList<ZPage>* to) { |
133 ZPage* const page = from->last(); |
197 ZPage* const page = from->last(); |