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 }