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
+ }
}