src/share/vm/services/memoryManager.cpp

Print this page

        

@@ -188,46 +188,68 @@
 }
 
 GCMemoryManager::GCMemoryManager() : MemoryManager() {
   _num_collections = 0;
   _last_gc_stat = NULL;
+  _current_gc_stat = NULL;
   _num_gc_threads = 1;
 }
 
 GCMemoryManager::~GCMemoryManager() {
   delete _last_gc_stat;
+  delete _current_gc_stat;
 }
 
 void GCMemoryManager::initialize_gc_stat_info() {
   assert(MemoryService::num_memory_pools() > 0, "should have one or more memory pools");
   _last_gc_stat = new GCStatInfo(MemoryService::num_memory_pools());
+  _current_gc_stat = new GCStatInfo(MemoryService::num_memory_pools());
+  // tracking concurrent collections requires two objects: one to update, and one to
+  // be the publicly available "last (completed) gc".
 }
 
-void GCMemoryManager::gc_begin() {
-  assert(_last_gc_stat != NULL, "Just checking");
+void GCMemoryManager::gc_begin(bool recordGCBeginTime, bool recordPreGCUsage,
+                               bool recordAccumulatedGCTime) {
+  assert(_last_gc_stat != NULL && _current_gc_stat != NULL, "Just checking");
+  if (recordAccumulatedGCTime) {
   _accumulated_timer.start();
-  _num_collections++;
-  _last_gc_stat->set_index(_num_collections);
-  _last_gc_stat->set_start_time(Management::timestamp());
+  }
+  // _num_collections now increases in gc_end, to count completed collections
+  if (recordGCBeginTime) {
+    _current_gc_stat->set_index(_num_collections+1);
+    _current_gc_stat->set_start_time(Management::timestamp());
+  }
 
+  if (recordPreGCUsage) {
   // Keep memory usage of all memory pools
   for (int i = 0; i < MemoryService::num_memory_pools(); i++) {
     MemoryPool* pool = MemoryService::get_memory_pool(i);
     MemoryUsage usage = pool->get_memory_usage();
-    _last_gc_stat->set_before_gc_usage(i, usage);
+      _current_gc_stat->set_before_gc_usage(i, usage);
     HS_DTRACE_PROBE8(hotspot, mem__pool__gc__begin,
       name(), strlen(name()),
       pool->name(), strlen(pool->name()),
       usage.init_size(), usage.used(),
       usage.committed(), usage.max_size());
   }
+  }
 }
 
-void GCMemoryManager::gc_end() {
+// A collector MUST, even if it does not complete for some reason,
+// make a TraceMemoryManagerStats object where countCollection is true, 
+// to ensure the current gc stat is placed in _last_gc_stat.
+void GCMemoryManager::gc_end(bool recordPostGCUsage,
+                             bool recordAccumulatedGCTime,
+                             bool recordGCEndTime, bool countCollection) {
+  if (recordAccumulatedGCTime) {
   _accumulated_timer.stop();
-  _last_gc_stat->set_end_time(Management::timestamp());
+  }
+  if (recordGCEndTime) {
+    _current_gc_stat->set_end_time(Management::timestamp());
+  }
 
+  if (recordPostGCUsage) {
   int i;
   // keep the last gc statistics for all memory pools
   for (i = 0; i < MemoryService::num_memory_pools(); i++) {
     MemoryPool* pool = MemoryService::get_memory_pool(i);
     MemoryUsage usage = pool->get_memory_usage();

@@ -236,11 +258,11 @@
       name(), strlen(name()),
       pool->name(), strlen(pool->name()),
       usage.init_size(), usage.used(),
       usage.committed(), usage.max_size());
 
-    _last_gc_stat->set_after_gc_usage(i, usage);
+      _current_gc_stat->set_after_gc_usage(i, usage);
   }
 
   // Set last collection usage of the memory pools managed by this collector
   for (i = 0; i < num_memory_pools(); i++) {
     MemoryPool* pool = get_memory_pool(i);

@@ -248,6 +270,25 @@
 
     // Compare with GC usage threshold
     pool->set_last_collection_usage(usage);
     LowMemoryDetector::detect_after_gc_memory(pool);
   }
+  }
+  if (countCollection) {
+    _num_collections++;
+    // alternately update two objects making one public when complete
+    GCStatInfo *tmp = _last_gc_stat;
+    _last_gc_stat = _current_gc_stat;
+    _current_gc_stat = tmp;
+#ifdef ASSERT
+    // reset the current stat for diagnosability purposes
+    _current_gc_stat->set_index(0);
+    _current_gc_stat->set_start_time(0);
+    _current_gc_stat->set_end_time(0);
+    for (int i = 0; i < MemoryService::num_memory_pools(); i++) {
+      MemoryUsage empty_usage = MemoryUsage();
+      _current_gc_stat->set_before_gc_usage(i, empty_usage);
+      _current_gc_stat->set_after_gc_usage(i, empty_usage);
+    }
+#endif
+  }
 }