hotspot/src/share/vm/services/memoryManager.cpp
changeset 6245 c37d2cf6de1a
parent 5547 f4b087cbb361
child 7397 5b173b4ca846
equal deleted inserted replaced
5717:54c9f1acbd37 6245:c37d2cf6de1a
   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 }