8014862: Add fast Metasapce capacity and used per MetadataType
authorjmasa
Mon, 20 May 2013 22:34:24 -0700
changeset 17628 481e0280aed3
parent 17627 325871034f2c
child 17630 10a659a730ea
8014862: Add fast Metasapce capacity and used per MetadataType Reviewed-by: ehelin, stefank
hotspot/src/share/vm/memory/metaspace.cpp
hotspot/src/share/vm/memory/metaspace.hpp
--- a/hotspot/src/share/vm/memory/metaspace.cpp	Mon May 20 10:44:33 2013 -0700
+++ b/hotspot/src/share/vm/memory/metaspace.cpp	Mon May 20 22:34:24 2013 -0700
@@ -562,6 +562,9 @@
   // protects allocations and contains.
   Mutex* const _lock;
 
+  // Type of metadata allocated.
+  Metaspace::MetadataType _mdtype;
+
   // Chunk related size
   size_t _medium_chunk_bunch;
 
@@ -606,6 +609,7 @@
     return (BlockFreelist*) &_block_freelists;
   }
 
+  Metaspace::MetadataType mdtype() { return _mdtype; }
   VirtualSpaceList* vs_list() const    { return _vs_list; }
 
   Metachunk* current_chunk() const { return _current_chunk; }
@@ -626,7 +630,8 @@
   void initialize();
 
  public:
-  SpaceManager(Mutex* lock,
+  SpaceManager(Metaspace::MetadataType mdtype,
+               Mutex* lock,
                VirtualSpaceList* vs_list);
   ~SpaceManager();
 
@@ -2032,9 +2037,11 @@
   }
 }
 
-SpaceManager::SpaceManager(Mutex* lock,
+SpaceManager::SpaceManager(Metaspace::MetadataType mdtype,
+                           Mutex* lock,
                            VirtualSpaceList* vs_list) :
   _vs_list(vs_list),
+  _mdtype(mdtype),
   _allocated_blocks_words(0),
   _allocated_chunks_words(0),
   _allocated_chunks_count(0),
@@ -2050,27 +2057,27 @@
   _allocated_chunks_words = _allocated_chunks_words + words;
   _allocated_chunks_count++;
   // Global total of capacity in allocated Metachunks
-  MetaspaceAux::inc_capacity(words);
+  MetaspaceAux::inc_capacity(mdtype(), words);
   // Global total of allocated Metablocks.
   // used_words_slow() includes the overhead in each
   // Metachunk so include it in the used when the
   // Metachunk is first added (so only added once per
   // Metachunk).
-  MetaspaceAux::inc_used(Metachunk::overhead());
+  MetaspaceAux::inc_used(mdtype(), Metachunk::overhead());
 }
 
 void SpaceManager::inc_used_metrics(size_t words) {
   // Add to the per SpaceManager total
   Atomic::add_ptr(words, &_allocated_blocks_words);
   // Add to the global total
-  MetaspaceAux::inc_used(words);
+  MetaspaceAux::inc_used(mdtype(), words);
 }
 
 void SpaceManager::dec_total_from_size_metrics() {
-  MetaspaceAux::dec_capacity(allocated_chunks_words());
-  MetaspaceAux::dec_used(allocated_blocks_words());
+  MetaspaceAux::dec_capacity(mdtype(), allocated_chunks_words());
+  MetaspaceAux::dec_used(mdtype(), allocated_blocks_words());
   // Also deduct the overhead per Metachunk
-  MetaspaceAux::dec_used(allocated_chunks_count() * Metachunk::overhead());
+  MetaspaceAux::dec_used(mdtype(), allocated_chunks_count() * Metachunk::overhead());
 }
 
 void SpaceManager::initialize() {
@@ -2470,8 +2477,8 @@
 // MetaspaceAux
 
 
-size_t MetaspaceAux::_allocated_capacity_words = 0;
-size_t MetaspaceAux::_allocated_used_words = 0;
+size_t MetaspaceAux::_allocated_capacity_words[] = {0, 0};
+size_t MetaspaceAux::_allocated_used_words[] = {0, 0};
 
 size_t MetaspaceAux::free_bytes() {
   size_t result = 0;
@@ -2484,40 +2491,40 @@
   return result;
 }
 
-void MetaspaceAux::dec_capacity(size_t words) {
+void MetaspaceAux::dec_capacity(Metaspace::MetadataType mdtype, size_t words) {
   assert_lock_strong(SpaceManager::expand_lock());
-  assert(words <= _allocated_capacity_words,
+  assert(words <= allocated_capacity_words(mdtype),
     err_msg("About to decrement below 0: words " SIZE_FORMAT
-            " is greater than _allocated_capacity_words " SIZE_FORMAT,
-            words, _allocated_capacity_words));
-  _allocated_capacity_words = _allocated_capacity_words - words;
+            " is greater than _allocated_capacity_words[%u] " SIZE_FORMAT,
+            words, mdtype, allocated_capacity_words(mdtype)));
+  _allocated_capacity_words[mdtype] -= words;
 }
 
-void MetaspaceAux::inc_capacity(size_t words) {
+void MetaspaceAux::inc_capacity(Metaspace::MetadataType mdtype, size_t words) {
   assert_lock_strong(SpaceManager::expand_lock());
   // Needs to be atomic
-  _allocated_capacity_words = _allocated_capacity_words + words;
+  _allocated_capacity_words[mdtype] += words;
 }
 
-void MetaspaceAux::dec_used(size_t words) {
-  assert(words <= _allocated_used_words,
+void MetaspaceAux::dec_used(Metaspace::MetadataType mdtype, size_t words) {
+  assert(words <= allocated_used_words(mdtype),
     err_msg("About to decrement below 0: words " SIZE_FORMAT
-            " is greater than _allocated_used_words " SIZE_FORMAT,
-            words, _allocated_used_words));
+            " is greater than _allocated_used_words[%u] " SIZE_FORMAT,
+            words, mdtype, allocated_used_words(mdtype)));
   // For CMS deallocation of the Metaspaces occurs during the
   // sweep which is a concurrent phase.  Protection by the expand_lock()
   // is not enough since allocation is on a per Metaspace basis
   // and protected by the Metaspace lock.
   jlong minus_words = (jlong) - (jlong) words;
-  Atomic::add_ptr(minus_words, &_allocated_used_words);
+  Atomic::add_ptr(minus_words, &_allocated_used_words[mdtype]);
 }
 
-void MetaspaceAux::inc_used(size_t words) {
+void MetaspaceAux::inc_used(Metaspace::MetadataType mdtype, size_t words) {
   // _allocated_used_words tracks allocations for
   // each piece of metadata.  Those allocations are
   // generally done concurrently by different application
   // threads so must be done atomically.
-  Atomic::add_ptr(words, &_allocated_used_words);
+  Atomic::add_ptr(words, &_allocated_used_words[mdtype]);
 }
 
 size_t MetaspaceAux::used_bytes_slow(Metaspace::MetadataType mdtype) {
@@ -2619,21 +2626,19 @@
                 SIZE_FORMAT "K, used " SIZE_FORMAT "K,"
                 " reserved " SIZE_FORMAT "K",
                 allocated_capacity_bytes()/K, allocated_used_bytes()/K, reserved_in_bytes()/K);
-#if 0
-// The calls to capacity_bytes_slow() and used_bytes_slow() cause
-// lock ordering assertion failures with some collectors.  Do
-// not include this code until the lock ordering is fixed.
-  if (PrintGCDetails && Verbose) {
-    out->print_cr("  data space     "
-                  SIZE_FORMAT "K, used " SIZE_FORMAT "K,"
-                  " reserved " SIZE_FORMAT "K",
-                  capacity_bytes_slow(nct)/K, used_bytes_slow(nct)/K, reserved_in_bytes(nct)/K);
-    out->print_cr("  class space    "
-                  SIZE_FORMAT "K, used " SIZE_FORMAT "K,"
-                  " reserved " SIZE_FORMAT "K",
-                  capacity_bytes_slow(ct)/K, used_bytes_slow(ct)/K, reserved_in_bytes(ct)/K);
-  }
-#endif
+
+  out->print_cr("  data space     "
+                SIZE_FORMAT "K, used " SIZE_FORMAT "K,"
+                " reserved " SIZE_FORMAT "K",
+                allocated_capacity_bytes(nct)/K,
+                allocated_used_bytes(nct)/K,
+                reserved_in_bytes(nct)/K);
+  out->print_cr("  class space    "
+                SIZE_FORMAT "K, used " SIZE_FORMAT "K,"
+                " reserved " SIZE_FORMAT "K",
+                allocated_capacity_bytes(ct)/K,
+                allocated_used_bytes(ct)/K,
+                reserved_in_bytes(ct)/K);
 }
 
 // Print information for class space and data space separately.
@@ -2717,24 +2722,42 @@
 void MetaspaceAux::verify_capacity() {
 #ifdef ASSERT
   size_t running_sum_capacity_bytes = allocated_capacity_bytes();
-  // For purposes of the running sum of used, verify against capacity
+  // For purposes of the running sum of capacity, verify against capacity
   size_t capacity_in_use_bytes = capacity_bytes_slow();
   assert(running_sum_capacity_bytes == capacity_in_use_bytes,
     err_msg("allocated_capacity_words() * BytesPerWord " SIZE_FORMAT
             " capacity_bytes_slow()" SIZE_FORMAT,
             running_sum_capacity_bytes, capacity_in_use_bytes));
+  for (Metaspace::MetadataType i = Metaspace::ClassType;
+       i < Metaspace:: MetadataTypeCount;
+       i = (Metaspace::MetadataType)(i + 1)) {
+    size_t capacity_in_use_bytes = capacity_bytes_slow(i);
+    assert(allocated_capacity_bytes(i) == capacity_in_use_bytes,
+      err_msg("allocated_capacity_bytes(%u) " SIZE_FORMAT
+              " capacity_bytes_slow(%u)" SIZE_FORMAT,
+              i, allocated_capacity_bytes(i), i, capacity_in_use_bytes));
+  }
 #endif
 }
 
 void MetaspaceAux::verify_used() {
 #ifdef ASSERT
   size_t running_sum_used_bytes = allocated_used_bytes();
-  // For purposes of the running sum of used, verify against capacity
+  // For purposes of the running sum of used, verify against used
   size_t used_in_use_bytes = used_bytes_slow();
   assert(allocated_used_bytes() == used_in_use_bytes,
     err_msg("allocated_used_bytes() " SIZE_FORMAT
-            " used_bytes_slow()()" SIZE_FORMAT,
+            " used_bytes_slow()" SIZE_FORMAT,
             allocated_used_bytes(), used_in_use_bytes));
+  for (Metaspace::MetadataType i = Metaspace::ClassType;
+       i < Metaspace:: MetadataTypeCount;
+       i = (Metaspace::MetadataType)(i + 1)) {
+    size_t used_in_use_bytes = used_bytes_slow(i);
+    assert(allocated_used_bytes(i) == used_in_use_bytes,
+      err_msg("allocated_used_bytes(%u) " SIZE_FORMAT
+              " used_bytes_slow(%u)" SIZE_FORMAT,
+              i, allocated_used_bytes(i), i, used_in_use_bytes));
+  }
 #endif
 }
 
@@ -2835,7 +2858,7 @@
   assert(space_list() != NULL,
     "Metadata VirtualSpaceList has not been initialized");
 
-  _vsm = new SpaceManager(lock, space_list());
+  _vsm = new SpaceManager(Metaspace::NonClassType, lock, space_list());
   if (_vsm == NULL) {
     return;
   }
@@ -2849,7 +2872,7 @@
     "Class VirtualSpaceList has not been initialized");
 
   // Allocate SpaceManager for classes.
-  _class_vsm = new SpaceManager(lock, class_space_list());
+  _class_vsm = new SpaceManager(Metaspace::ClassType, lock, class_space_list());
   if (_class_vsm == NULL) {
     return;
   }
--- a/hotspot/src/share/vm/memory/metaspace.hpp	Mon May 20 10:44:33 2013 -0700
+++ b/hotspot/src/share/vm/memory/metaspace.hpp	Mon May 20 22:34:24 2013 -0700
@@ -86,7 +86,10 @@
   friend class MetaspaceAux;
 
  public:
-  enum MetadataType {ClassType, NonClassType};
+  enum MetadataType {ClassType = 0,
+                     NonClassType = ClassType + 1,
+                     MetadataTypeCount = ClassType + 2
+  };
   enum MetaspaceType {
     StandardMetaspaceType,
     BootMetaspaceType,
@@ -184,20 +187,22 @@
  public:
   // Running sum of space in all Metachunks that has been
   // allocated to a Metaspace.  This is used instead of
-  // iterating over all the classloaders
-  static size_t _allocated_capacity_words;
+  // iterating over all the classloaders. One for each
+  // type of Metadata
+  static size_t _allocated_capacity_words[Metaspace:: MetadataTypeCount];
   // Running sum of space in all Metachunks that have
-  // are being used for metadata.
-  static size_t _allocated_used_words;
+  // are being used for metadata. One for each
+  // type of Metadata.
+  static size_t _allocated_used_words[Metaspace:: MetadataTypeCount];
 
  public:
   // Decrement and increment _allocated_capacity_words
-  static void dec_capacity(size_t words);
-  static void inc_capacity(size_t words);
+  static void dec_capacity(Metaspace::MetadataType type, size_t words);
+  static void inc_capacity(Metaspace::MetadataType type, size_t words);
 
   // Decrement and increment _allocated_used_words
-  static void dec_used(size_t words);
-  static void inc_used(size_t words);
+  static void dec_used(Metaspace::MetadataType type, size_t words);
+  static void inc_used(Metaspace::MetadataType type, size_t words);
 
   // Total of space allocated to metadata in all Metaspaces.
   // This sums the space used in each Metachunk by
@@ -211,18 +216,32 @@
   static size_t free_chunks_total();
   static size_t free_chunks_total_in_bytes();
 
+  static size_t allocated_capacity_words(Metaspace::MetadataType mdtype) {
+    return _allocated_capacity_words[mdtype];
+  }
   static size_t allocated_capacity_words() {
-    return _allocated_capacity_words;
+    return _allocated_capacity_words[Metaspace::ClassType] +
+           _allocated_capacity_words[Metaspace::NonClassType];
+  }
+  static size_t allocated_capacity_bytes(Metaspace::MetadataType mdtype) {
+    return allocated_capacity_words(mdtype) * BytesPerWord;
   }
   static size_t allocated_capacity_bytes() {
-    return _allocated_capacity_words * BytesPerWord;
+    return allocated_capacity_words() * BytesPerWord;
   }
 
+  static size_t allocated_used_words(Metaspace::MetadataType mdtype) {
+    return _allocated_used_words[mdtype];
+  }
   static size_t allocated_used_words() {
-    return _allocated_used_words;
+    return _allocated_used_words[Metaspace::ClassType] +
+           _allocated_used_words[Metaspace::NonClassType];
+  }
+  static size_t allocated_used_bytes(Metaspace::MetadataType mdtype) {
+    return allocated_used_words(mdtype) * BytesPerWord;
   }
   static size_t allocated_used_bytes() {
-    return _allocated_used_words * BytesPerWord;
+    return allocated_used_words() * BytesPerWord;
   }
 
   static size_t free_bytes();