< prev index next >

src/hotspot/share/memory/metaspace/metaspaceStatistics.cpp

Print this page
rev 60538 : imported patch jep387-all.patch

@@ -1,8 +1,8 @@
 /*
- * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2018 SAP SE. All rights reserved.
+ * Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018, 2020 SAP SE. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License version 2 only, as
  * published by the Free Software Foundation.

@@ -20,245 +20,218 @@
  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  *
  */
+
 #include "precompiled.hpp"
 
-#include "memory/metaspace/metachunk.hpp"
+
+#include "memory/metaspace/chunkLevel.hpp"
 #include "memory/metaspace/metaspaceCommon.hpp"
 #include "memory/metaspace/metaspaceStatistics.hpp"
+
 #include "utilities/debug.hpp"
 #include "utilities/globalDefinitions.hpp"
 #include "utilities/ostream.hpp"
 
 namespace metaspace {
 
-// FreeChunksStatistics methods
 
-FreeChunksStatistics::FreeChunksStatistics()
-: _num(0), _cap(0)
-{}
-
-void FreeChunksStatistics::reset() {
-  _num = 0; _cap = 0;
+// Returns total word size of all chunks in this manager.
+void cm_stats_t::add(const cm_stats_t& other) {
+  for (chunklevel_t l = chunklevel::LOWEST_CHUNK_LEVEL; l <= chunklevel::HIGHEST_CHUNK_LEVEL; l ++) {
+    num_chunks[l] += other.num_chunks[l];
+    committed_word_size[l] += other.committed_word_size[l];
+  }
 }
 
-void FreeChunksStatistics::add(uintx n, size_t s) {
-  _num += n; _cap += s;
+// Returns total word size of all chunks in this manager.
+size_t cm_stats_t::total_word_size() const {
+  size_t s = 0;
+  for (chunklevel_t l = chunklevel::LOWEST_CHUNK_LEVEL; l <= chunklevel::HIGHEST_CHUNK_LEVEL; l ++) {
+    s += num_chunks[l] * chunklevel::word_size_for_level(l);
+  }
+  return s;
 }
 
-void FreeChunksStatistics::add(const FreeChunksStatistics& other) {
-  _num += other._num;
-  _cap += other._cap;
+// Returns total committed word size of all chunks in this manager.
+size_t cm_stats_t::total_committed_word_size() const {
+  size_t s = 0;
+  for (chunklevel_t l = chunklevel::LOWEST_CHUNK_LEVEL; l <= chunklevel::HIGHEST_CHUNK_LEVEL; l ++) {
+    s += committed_word_size[l];
+  }
+  return s;
 }
 
-void FreeChunksStatistics::print_on(outputStream* st, size_t scale) const {
-  st->print(UINTX_FORMAT, _num);
-  st->print(" chunks, total capacity ");
-  print_scaled_words(st, _cap, scale);
-}
 
-// ChunkManagerStatistics methods
+void cm_stats_t::print_on(outputStream* st, size_t scale) const {
+  // Note: used as part of MetaspaceReport so formatting matters.
+  size_t total_size = 0;
+  size_t total_committed_size = 0;
+  for (chunklevel_t l = chunklevel::LOWEST_CHUNK_LEVEL; l <= chunklevel::HIGHEST_CHUNK_LEVEL; l ++) {
+    st->cr();
+    chunklevel::print_chunk_size(st, l);
+    st->print(": ");
+    if (num_chunks[l] > 0) {
+      const size_t word_size = num_chunks[l] * chunklevel::word_size_for_level(l);
 
-void ChunkManagerStatistics::reset() {
-  for (ChunkIndex i = ZeroIndex; i < NumberOfInUseLists; i = next_chunk_index(i)) {
-    _chunk_stats[i].reset();
-  }
-}
+      st->print("%4d, capacity=", num_chunks[l]);
+      print_scaled_words(st, word_size, scale);
 
-size_t ChunkManagerStatistics::total_capacity() const {
-  return _chunk_stats[SpecializedIndex].cap() +
-      _chunk_stats[SmallIndex].cap() +
-      _chunk_stats[MediumIndex].cap() +
-      _chunk_stats[HumongousIndex].cap();
-}
+      st->print(", committed=");
+      print_scaled_words_and_percentage(st, committed_word_size[l], word_size, scale);
 
-void ChunkManagerStatistics::print_on(outputStream* st, size_t scale) const {
-  FreeChunksStatistics totals;
-  for (ChunkIndex i = ZeroIndex; i < NumberOfInUseLists; i = next_chunk_index(i)) {
-    st->cr();
-    st->print("%12s chunks: ", chunk_size_name(i));
-    if (_chunk_stats[i].num() > 0) {
-      st->print(UINTX_FORMAT_W(4) ", capacity ", _chunk_stats[i].num());
-      print_scaled_words(st, _chunk_stats[i].cap(), scale);
+      total_size += word_size;
+      total_committed_size += committed_word_size[l];
     } else {
       st->print("(none)");
     }
-    totals.add(_chunk_stats[i]);
   }
   st->cr();
-  st->print("%19s: " UINTX_FORMAT_W(4) ", capacity=", "Total", totals.num());
-  print_scaled_words(st, totals.cap(), scale);
+  st->print("Total word size: ");
+  print_scaled_words(st, total_size, scale);
+  st->print(", committed: ");
+  print_scaled_words_and_percentage(st, total_committed_size, total_size, scale);
   st->cr();
 }
 
-// UsedChunksStatistics methods
-
-UsedChunksStatistics::UsedChunksStatistics()
-: _num(0), _cap(0), _used(0), _free(0), _waste(0), _overhead(0)
-{}
-
-void UsedChunksStatistics::reset() {
-  _num = 0;
-  _cap = _overhead = _used = _free = _waste = 0;
+#ifdef ASSERT
+void cm_stats_t::verify() const {
+  assert(total_committed_word_size() <= total_word_size(),
+         "Sanity");
 }
+#endif
 
-void UsedChunksStatistics::add(const UsedChunksStatistics& other) {
-  _num += other._num;
-  _cap += other._cap;
-  _used += other._used;
-  _free += other._free;
-  _waste += other._waste;
-  _overhead += other._overhead;
-  DEBUG_ONLY(check_sanity());
-}
 
-void UsedChunksStatistics::print_on(outputStream* st, size_t scale) const {
+void in_use_chunk_stats_t::print_on(outputStream* st, size_t scale) const {
   int col = st->position();
-  st->print(UINTX_FORMAT_W(4) " chunk%s, ", _num, _num != 1 ? "s" : "");
-  if (_num > 0) {
+  st->print("%4d chunk%s, ", num, num != 1 ? "s" : "");
+  if (num > 0) {
     col += 14; st->fill_to(col);
 
-    print_scaled_words(st, _cap, scale, 5);
-    st->print(" capacity, ");
+    print_scaled_words(st, word_size, scale, 5);
+    st->print(" capacity,");
+
+    col += 20; st->fill_to(col);
+    print_scaled_words_and_percentage(st, committed_words, word_size, scale, 5);
+    st->print(" committed, ");
 
     col += 18; st->fill_to(col);
-    print_scaled_words_and_percentage(st, _used, _cap, scale, 5);
+    print_scaled_words_and_percentage(st, used_words, word_size, scale, 5);
     st->print(" used, ");
 
     col += 20; st->fill_to(col);
-    print_scaled_words_and_percentage(st, _free, _cap, scale, 5);
+    print_scaled_words_and_percentage(st, free_words, word_size, scale, 5);
     st->print(" free, ");
 
     col += 20; st->fill_to(col);
-    print_scaled_words_and_percentage(st, _waste, _cap, scale, 5);
-    st->print(" waste, ");
+    print_scaled_words_and_percentage(st, waste_words, word_size, scale, 5);
+    st->print(" waste ");
 
-    col += 20; st->fill_to(col);
-    print_scaled_words_and_percentage(st, _overhead, _cap, scale, 5);
-    st->print(" overhead");
   }
-  DEBUG_ONLY(check_sanity());
 }
 
 #ifdef ASSERT
-void UsedChunksStatistics::check_sanity() const {
-  assert(_overhead == (Metachunk::overhead() * _num), "Sanity: Overhead.");
-  assert(_cap == _used + _free + _waste + _overhead, "Sanity: Capacity.");
+void in_use_chunk_stats_t::verify() const {
+  assert(word_size >= committed_words &&
+      committed_words == used_words + free_words + waste_words,
+         "Sanity: cap " SIZE_FORMAT ", committed " SIZE_FORMAT ", used " SIZE_FORMAT ", free " SIZE_FORMAT ", waste " SIZE_FORMAT ".",
+         word_size, committed_words, used_words, free_words, waste_words);
 }
 #endif
 
-// SpaceManagerStatistics methods
-
-SpaceManagerStatistics::SpaceManagerStatistics() { reset(); }
-
-void SpaceManagerStatistics::reset() {
-  for (int i = 0; i < NumberOfInUseLists; i ++) {
-    _chunk_stats[i].reset();
-    _free_blocks_num = 0; _free_blocks_cap_words = 0;
+void arena_stats_t::add(const arena_stats_t& other) {
+  for (chunklevel_t l = chunklevel::LOWEST_CHUNK_LEVEL; l <= chunklevel::HIGHEST_CHUNK_LEVEL; l ++) {
+    stats[l].add(other.stats[l]);
   }
+  free_blocks_num += other.free_blocks_num;
+  free_blocks_word_size += other.free_blocks_word_size;
 }
 
-void SpaceManagerStatistics::add_free_blocks_info(uintx num, size_t cap) {
-  _free_blocks_num += num;
-  _free_blocks_cap_words += cap;
-}
-
-void SpaceManagerStatistics::add(const SpaceManagerStatistics& other) {
-  for (ChunkIndex i = ZeroIndex; i < NumberOfInUseLists; i = next_chunk_index(i)) {
-    _chunk_stats[i].add(other._chunk_stats[i]);
-  }
-  _free_blocks_num += other._free_blocks_num;
-  _free_blocks_cap_words += other._free_blocks_cap_words;
-}
 
 // Returns total chunk statistics over all chunk types.
-UsedChunksStatistics SpaceManagerStatistics::totals() const {
-  UsedChunksStatistics stat;
-  for (ChunkIndex i = ZeroIndex; i < NumberOfInUseLists; i = next_chunk_index(i)) {
-    stat.add(_chunk_stats[i]);
+in_use_chunk_stats_t arena_stats_t::totals() const {
+  in_use_chunk_stats_t out;
+  for (chunklevel_t l = chunklevel::LOWEST_CHUNK_LEVEL; l <= chunklevel::HIGHEST_CHUNK_LEVEL; l ++) {
+    out.add(stats[l]);
   }
-  return stat;
+  return out;
 }
 
-void SpaceManagerStatistics::print_on(outputStream* st, size_t scale,  bool detailed) const {
+void arena_stats_t::print_on(outputStream* st, size_t scale,  bool detailed) const {
   streamIndentor sti(st);
   if (detailed) {
     st->cr_indent();
-    st->print("Usage by chunk type:");
+    st->print("Usage by chunk level:");
     {
       streamIndentor sti2(st);
-      for (ChunkIndex i = ZeroIndex; i < NumberOfInUseLists; i = next_chunk_index(i)) {
+      for (chunklevel_t l = chunklevel::LOWEST_CHUNK_LEVEL; l <= chunklevel::HIGHEST_CHUNK_LEVEL; l ++) {
         st->cr_indent();
-        st->print("%15s: ", chunk_size_name(i));
-        if (_chunk_stats[i].num() == 0) {
+        chunklevel::print_chunk_size(st, l);
+        st->print(" chunks: ");
+        if (stats[l].num == 0) {
           st->print(" (none)");
         } else {
-          _chunk_stats[i].print_on(st, scale);
+          stats[l].print_on(st, scale);
         }
       }
 
       st->cr_indent();
       st->print("%15s: ", "-total-");
       totals().print_on(st, scale);
     }
-    if (_free_blocks_num > 0) {
+    if (free_blocks_num > 0) {
       st->cr_indent();
-      st->print("deallocated: " UINTX_FORMAT " blocks with ", _free_blocks_num);
-      print_scaled_words(st, _free_blocks_cap_words, scale);
+      st->print("deallocated: " UINTX_FORMAT " blocks with ", free_blocks_num);
+      print_scaled_words(st, free_blocks_word_size, scale);
     }
   } else {
     totals().print_on(st, scale);
     st->print(", ");
-    st->print("deallocated: " UINTX_FORMAT " blocks with ", _free_blocks_num);
-    print_scaled_words(st, _free_blocks_cap_words, scale);
+    st->print("deallocated: " UINTX_FORMAT " blocks with ", free_blocks_num);
+    print_scaled_words(st, free_blocks_word_size, scale);
   }
 }
 
-// ClassLoaderMetaspaceStatistics methods
-
-ClassLoaderMetaspaceStatistics::ClassLoaderMetaspaceStatistics() { reset(); }
+#ifdef ASSERT
 
-void ClassLoaderMetaspaceStatistics::reset() {
-  nonclass_sm_stats().reset();
-  if (Metaspace::using_class_space()) {
-    class_sm_stats().reset();
-  }
+void arena_stats_t::verify() const {
+  size_t total_used = 0;
+  for (chunklevel_t l = chunklevel::LOWEST_CHUNK_LEVEL; l <= chunklevel::HIGHEST_CHUNK_LEVEL; l ++) {
+    stats[l].verify();
+    total_used += stats[l].used_words;
+  }
+  // Deallocated allocations still count as used
+  assert(total_used >= free_blocks_word_size,
+         "Sanity");
 }
+#endif
 
-// Returns total space manager statistics for both class and non-class metaspace
-SpaceManagerStatistics ClassLoaderMetaspaceStatistics::totals() const {
-  SpaceManagerStatistics stats;
-  stats.add(nonclass_sm_stats());
-  if (Metaspace::using_class_space()) {
-    stats.add(class_sm_stats());
-  }
-  return stats;
-}
 
-void ClassLoaderMetaspaceStatistics::add(const ClassLoaderMetaspaceStatistics& other) {
-  nonclass_sm_stats().add(other.nonclass_sm_stats());
-  if (Metaspace::using_class_space()) {
-    class_sm_stats().add(other.class_sm_stats());
-  }
+// Returns total arena statistics for both class and non-class metaspace
+arena_stats_t clms_stats_t::totals() const {
+  arena_stats_t out;
+  out.add(arena_stats_nonclass);
+  out.add(arena_stats_class);
+  return out;
 }
 
-void ClassLoaderMetaspaceStatistics::print_on(outputStream* st, size_t scale, bool detailed) const {
+void clms_stats_t::print_on(outputStream* st, size_t scale, bool detailed) const {
   streamIndentor sti(st);
   st->cr_indent();
   if (Metaspace::using_class_space()) {
     st->print("Non-Class: ");
   }
-  nonclass_sm_stats().print_on(st, scale, detailed);
+  arena_stats_nonclass.print_on(st, scale, detailed);
   if (detailed) {
     st->cr();
   }
   if (Metaspace::using_class_space()) {
     st->cr_indent();
     st->print("    Class: ");
-    class_sm_stats().print_on(st, scale, detailed);
+    arena_stats_class.print_on(st, scale, detailed);
     if (detailed) {
       st->cr();
     }
     st->cr_indent();
     st->print("     Both: ");

@@ -268,9 +241,17 @@
     }
   }
   st->cr();
 }
 
+
+#ifdef ASSERT
+void clms_stats_t::verify() const {
+  arena_stats_nonclass.verify();
+  arena_stats_class.verify();
+}
+#endif
+
 } // end namespace metaspace
 
 
 
< prev index next >