Mercurial > hg > truffle
comparison src/share/vm/services/memoryManager.cpp @ 1703:f6f3eef8a521
6581734: CMS Old Gen's collection usage is zero after GC which is incorrect
Summary: Management code enabled for use by a concurrent collector.
Reviewed-by: mchung, ysr
author | kevinw |
---|---|
date | Fri, 30 Jul 2010 22:43:50 +0100 |
parents | c18cbe5936b8 |
children | f95d63e2154a |
comparison
equal
deleted
inserted
replaced
1594:b9bc732be7c0 | 1703:f6f3eef8a521 |
---|---|
164 GCStatInfo::~GCStatInfo() { | 164 GCStatInfo::~GCStatInfo() { |
165 FREE_C_HEAP_ARRAY(MemoryUsage*, _before_gc_usage_array); | 165 FREE_C_HEAP_ARRAY(MemoryUsage*, _before_gc_usage_array); |
166 FREE_C_HEAP_ARRAY(MemoryUsage*, _after_gc_usage_array); | 166 FREE_C_HEAP_ARRAY(MemoryUsage*, _after_gc_usage_array); |
167 } | 167 } |
168 | 168 |
169 void GCStatInfo::copy_stat(GCStatInfo* stat) { | |
170 set_index(stat->gc_index()); | |
171 set_start_time(stat->start_time()); | |
172 set_end_time(stat->end_time()); | |
173 assert(_usage_array_size == stat->usage_array_size(), "Must have same array size"); | |
174 for (int i = 0; i < _usage_array_size; i++) { | |
175 set_before_gc_usage(i, stat->before_gc_usage_for_pool(i)); | |
176 set_after_gc_usage(i, stat->after_gc_usage_for_pool(i)); | |
177 } | |
178 } | |
179 | |
180 void GCStatInfo::set_gc_usage(int pool_index, MemoryUsage usage, bool before_gc) { | 169 void GCStatInfo::set_gc_usage(int pool_index, MemoryUsage usage, bool before_gc) { |
181 MemoryUsage* gc_usage_array; | 170 MemoryUsage* gc_usage_array; |
182 if (before_gc) { | 171 if (before_gc) { |
183 gc_usage_array = _before_gc_usage_array; | 172 gc_usage_array = _before_gc_usage_array; |
184 } else { | 173 } else { |
185 gc_usage_array = _after_gc_usage_array; | 174 gc_usage_array = _after_gc_usage_array; |
186 } | 175 } |
187 gc_usage_array[pool_index] = usage; | 176 gc_usage_array[pool_index] = usage; |
188 } | 177 } |
189 | 178 |
179 void GCStatInfo::clear() { | |
180 _index = 0; | |
181 _start_time = 0L; | |
182 _end_time = 0L; | |
183 size_t len = _usage_array_size * sizeof(MemoryUsage); | |
184 memset(_before_gc_usage_array, 0, len); | |
185 memset(_after_gc_usage_array, 0, len); | |
186 } | |
187 | |
188 | |
190 GCMemoryManager::GCMemoryManager() : MemoryManager() { | 189 GCMemoryManager::GCMemoryManager() : MemoryManager() { |
191 _num_collections = 0; | 190 _num_collections = 0; |
192 _last_gc_stat = NULL; | 191 _last_gc_stat = NULL; |
192 _last_gc_lock = new Mutex(Mutex::leaf, "_last_gc_lock", true); | |
193 _current_gc_stat = NULL; | |
193 _num_gc_threads = 1; | 194 _num_gc_threads = 1; |
194 } | 195 } |
195 | 196 |
196 GCMemoryManager::~GCMemoryManager() { | 197 GCMemoryManager::~GCMemoryManager() { |
197 delete _last_gc_stat; | 198 delete _last_gc_stat; |
199 delete _last_gc_lock; | |
200 delete _current_gc_stat; | |
198 } | 201 } |
199 | 202 |
200 void GCMemoryManager::initialize_gc_stat_info() { | 203 void GCMemoryManager::initialize_gc_stat_info() { |
201 assert(MemoryService::num_memory_pools() > 0, "should have one or more memory pools"); | 204 assert(MemoryService::num_memory_pools() > 0, "should have one or more memory pools"); |
202 _last_gc_stat = new GCStatInfo(MemoryService::num_memory_pools()); | 205 _last_gc_stat = new GCStatInfo(MemoryService::num_memory_pools()); |
203 } | 206 _current_gc_stat = new GCStatInfo(MemoryService::num_memory_pools()); |
204 | 207 // tracking concurrent collections we need two objects: one to update, and one to |
205 void GCMemoryManager::gc_begin() { | 208 // hold the publicly available "last (completed) gc" information. |
206 assert(_last_gc_stat != NULL, "Just checking"); | 209 } |
207 _accumulated_timer.start(); | 210 |
208 _num_collections++; | 211 void GCMemoryManager::gc_begin(bool recordGCBeginTime, bool recordPreGCUsage, |
209 _last_gc_stat->set_index(_num_collections); | 212 bool recordAccumulatedGCTime) { |
210 _last_gc_stat->set_start_time(Management::timestamp()); | 213 assert(_last_gc_stat != NULL && _current_gc_stat != NULL, "Just checking"); |
211 | 214 if (recordAccumulatedGCTime) { |
212 // Keep memory usage of all memory pools | 215 _accumulated_timer.start(); |
213 for (int i = 0; i < MemoryService::num_memory_pools(); i++) { | 216 } |
214 MemoryPool* pool = MemoryService::get_memory_pool(i); | 217 // _num_collections now increases in gc_end, to count completed collections |
215 MemoryUsage usage = pool->get_memory_usage(); | 218 if (recordGCBeginTime) { |
216 _last_gc_stat->set_before_gc_usage(i, usage); | 219 _current_gc_stat->set_index(_num_collections+1); |
217 HS_DTRACE_PROBE8(hotspot, mem__pool__gc__begin, | 220 _current_gc_stat->set_start_time(Management::timestamp()); |
218 name(), strlen(name()), | 221 } |
219 pool->name(), strlen(pool->name()), | 222 |
220 usage.init_size(), usage.used(), | 223 if (recordPreGCUsage) { |
221 usage.committed(), usage.max_size()); | 224 // Keep memory usage of all memory pools |
222 } | 225 for (int i = 0; i < MemoryService::num_memory_pools(); i++) { |
223 } | 226 MemoryPool* pool = MemoryService::get_memory_pool(i); |
224 | 227 MemoryUsage usage = pool->get_memory_usage(); |
225 void GCMemoryManager::gc_end() { | 228 _current_gc_stat->set_before_gc_usage(i, usage); |
226 _accumulated_timer.stop(); | 229 HS_DTRACE_PROBE8(hotspot, mem__pool__gc__begin, |
227 _last_gc_stat->set_end_time(Management::timestamp()); | 230 name(), strlen(name()), |
228 | 231 pool->name(), strlen(pool->name()), |
229 int i; | 232 usage.init_size(), usage.used(), |
230 // keep the last gc statistics for all memory pools | 233 usage.committed(), usage.max_size()); |
231 for (i = 0; i < MemoryService::num_memory_pools(); i++) { | 234 } |
232 MemoryPool* pool = MemoryService::get_memory_pool(i); | 235 } |
233 MemoryUsage usage = pool->get_memory_usage(); | 236 } |
234 | 237 |
235 HS_DTRACE_PROBE8(hotspot, mem__pool__gc__end, | 238 // A collector MUST, even if it does not complete for some reason, |
236 name(), strlen(name()), | 239 // make a TraceMemoryManagerStats object where countCollection is true, |
237 pool->name(), strlen(pool->name()), | 240 // to ensure the current gc stat is placed in _last_gc_stat. |
238 usage.init_size(), usage.used(), | 241 void GCMemoryManager::gc_end(bool recordPostGCUsage, |
239 usage.committed(), usage.max_size()); | 242 bool recordAccumulatedGCTime, |
240 | 243 bool recordGCEndTime, bool countCollection) { |
241 _last_gc_stat->set_after_gc_usage(i, usage); | 244 if (recordAccumulatedGCTime) { |
242 } | 245 _accumulated_timer.stop(); |
243 | 246 } |
244 // Set last collection usage of the memory pools managed by this collector | 247 if (recordGCEndTime) { |
245 for (i = 0; i < num_memory_pools(); i++) { | 248 _current_gc_stat->set_end_time(Management::timestamp()); |
246 MemoryPool* pool = get_memory_pool(i); | 249 } |
247 MemoryUsage usage = pool->get_memory_usage(); | 250 |
248 | 251 if (recordPostGCUsage) { |
249 // Compare with GC usage threshold | 252 int i; |
250 pool->set_last_collection_usage(usage); | 253 // keep the last gc statistics for all memory pools |
251 LowMemoryDetector::detect_after_gc_memory(pool); | 254 for (i = 0; i < MemoryService::num_memory_pools(); i++) { |
252 } | 255 MemoryPool* pool = MemoryService::get_memory_pool(i); |
253 } | 256 MemoryUsage usage = pool->get_memory_usage(); |
257 | |
258 HS_DTRACE_PROBE8(hotspot, mem__pool__gc__end, | |
259 name(), strlen(name()), | |
260 pool->name(), strlen(pool->name()), | |
261 usage.init_size(), usage.used(), | |
262 usage.committed(), usage.max_size()); | |
263 | |
264 _current_gc_stat->set_after_gc_usage(i, usage); | |
265 } | |
266 | |
267 // Set last collection usage of the memory pools managed by this collector | |
268 for (i = 0; i < num_memory_pools(); i++) { | |
269 MemoryPool* pool = get_memory_pool(i); | |
270 MemoryUsage usage = pool->get_memory_usage(); | |
271 | |
272 // Compare with GC usage threshold | |
273 pool->set_last_collection_usage(usage); | |
274 LowMemoryDetector::detect_after_gc_memory(pool); | |
275 } | |
276 } | |
277 if (countCollection) { | |
278 _num_collections++; | |
279 // alternately update two objects making one public when complete | |
280 { | |
281 MutexLockerEx ml(_last_gc_lock, Mutex::_no_safepoint_check_flag); | |
282 GCStatInfo *tmp = _last_gc_stat; | |
283 _last_gc_stat = _current_gc_stat; | |
284 _current_gc_stat = tmp; | |
285 // reset the current stat for diagnosability purposes | |
286 _current_gc_stat->clear(); | |
287 } | |
288 } | |
289 } | |
290 | |
291 size_t GCMemoryManager::get_last_gc_stat(GCStatInfo* dest) { | |
292 MutexLockerEx ml(_last_gc_lock, Mutex::_no_safepoint_check_flag); | |
293 if (_last_gc_stat->gc_index() != 0) { | |
294 dest->set_index(_last_gc_stat->gc_index()); | |
295 dest->set_start_time(_last_gc_stat->start_time()); | |
296 dest->set_end_time(_last_gc_stat->end_time()); | |
297 assert(dest->usage_array_size() == _last_gc_stat->usage_array_size(), | |
298 "Must have same array size"); | |
299 size_t len = dest->usage_array_size() * sizeof(MemoryUsage); | |
300 memcpy(dest->before_gc_usage_array(), _last_gc_stat->before_gc_usage_array(), len); | |
301 memcpy(dest->after_gc_usage_array(), _last_gc_stat->after_gc_usage_array(), len); | |
302 } | |
303 return _last_gc_stat->gc_index(); | |
304 } |