8186770: NMT: Report metadata information in NMT summary
authorzgu
Thu, 28 Sep 2017 09:56:54 -0400
changeset 47553 5d20359dd938
parent 47552 8a3599d60996
child 47555 9dfb5791d130
8186770: NMT: Report metadata information in NMT summary Summary: Added metadata statistics in NMT summary report Reviewed-by: adinn, coleenp
src/hotspot/share/memory/metaspace.cpp
src/hotspot/share/memory/metaspace.hpp
src/hotspot/share/services/memBaseline.cpp
src/hotspot/share/services/memBaseline.hpp
src/hotspot/share/services/memReporter.cpp
src/hotspot/share/services/memReporter.hpp
src/hotspot/share/services/virtualMemoryTracker.cpp
src/hotspot/share/services/virtualMemoryTracker.hpp
--- a/src/hotspot/share/memory/metaspace.cpp	Tue Sep 26 14:05:27 2017 +0200
+++ b/src/hotspot/share/memory/metaspace.cpp	Thu Sep 28 09:56:54 2017 -0400
@@ -2718,7 +2718,7 @@
 
 
 size_t MetaspaceAux::_capacity_words[] = {0, 0};
-size_t MetaspaceAux::_used_words[] = {0, 0};
+volatile size_t MetaspaceAux::_used_words[] = {0, 0};
 
 size_t MetaspaceAux::free_bytes(Metaspace::MetadataType mdtype) {
   VirtualSpaceList* list = Metaspace::get_space_list(mdtype);
--- a/src/hotspot/share/memory/metaspace.hpp	Tue Sep 26 14:05:27 2017 +0200
+++ b/src/hotspot/share/memory/metaspace.hpp	Thu Sep 28 09:56:54 2017 -0400
@@ -273,7 +273,7 @@
   // Running sum of space in all Metachunks that
   // are being used for metadata. One for each
   // type of Metadata.
-  static size_t _used_words[Metaspace:: MetadataTypeCount];
+  static volatile size_t _used_words[Metaspace:: MetadataTypeCount];
 
  public:
   // Decrement and increment _allocated_capacity_words
--- a/src/hotspot/share/services/memBaseline.cpp	Tue Sep 26 14:05:27 2017 +0200
+++ b/src/hotspot/share/services/memBaseline.cpp	Thu Sep 28 09:56:54 2017 -0400
@@ -144,6 +144,7 @@
 bool MemBaseline::baseline_summary() {
   MallocMemorySummary::snapshot(&_malloc_memory_snapshot);
   VirtualMemorySummary::snapshot(&_virtual_memory_snapshot);
+  MetaspaceSnapshot::snapshot(_metaspace_snapshot);
   return true;
 }
 
--- a/src/hotspot/share/services/memBaseline.hpp	Tue Sep 26 14:05:27 2017 +0200
+++ b/src/hotspot/share/services/memBaseline.hpp	Thu Sep 28 09:56:54 2017 -0400
@@ -65,6 +65,7 @@
   // Summary information
   MallocMemorySnapshot   _malloc_memory_snapshot;
   VirtualMemorySnapshot  _virtual_memory_snapshot;
+  MetaspaceSnapshot      _metaspace_snapshot;
 
   size_t               _class_count;
 
@@ -103,6 +104,10 @@
     return &_virtual_memory_snapshot;
   }
 
+  MetaspaceSnapshot* metaspace_snapshot() {
+    return &_metaspace_snapshot;
+  }
+
   MallocSiteIterator malloc_sites(SortingOrder order);
   VirtualMemorySiteIterator virtual_memory_sites(SortingOrder order);
 
--- a/src/hotspot/share/services/memReporter.cpp	Tue Sep 26 14:05:27 2017 +0200
+++ b/src/hotspot/share/services/memReporter.cpp	Thu Sep 28 09:56:54 2017 -0400
@@ -175,12 +175,44 @@
       amount_in_current_scale(_malloc_snapshot->malloc_overhead()->size()) > 0) {
       out->print_cr("%27s (tracking overhead=" SIZE_FORMAT "%s)", " ",
         amount_in_current_scale(_malloc_snapshot->malloc_overhead()->size()), scale);
+    } else if (flag == mtClass) {
+      // Metadata information
+      report_metadata(Metaspace::NonClassType);
+      if (Metaspace::using_class_space()) {
+        report_metadata(Metaspace::ClassType);
+      }
     }
-
     out->print_cr(" ");
   }
 }
 
+void MemSummaryReporter::report_metadata(Metaspace::MetadataType type) const {
+  assert(type == Metaspace::NonClassType || type == Metaspace::ClassType,
+    "Invalid metadata type");
+  const char* name = (type == Metaspace::NonClassType) ?
+    "Metadata:   " : "Class space:";
+
+  outputStream* out = output();
+  const char* scale = current_scale();
+  size_t committed   = MetaspaceAux::committed_bytes(type);
+  size_t used = MetaspaceAux::used_bytes(type);
+  size_t free = (MetaspaceAux::capacity_bytes(type) - used)
+              + MetaspaceAux::free_chunks_total_bytes(type)
+              + MetaspaceAux::free_bytes(type);
+
+  assert(committed >= used + free, "Sanity");
+  size_t waste = committed - (used + free);
+
+  out->print_cr("%27s (  %s)", " ", name);
+  out->print("%27s (    ", " ");
+  print_total(MetaspaceAux::reserved_bytes(type), committed);
+  out->print_cr(")");
+  out->print_cr("%27s (    used=" SIZE_FORMAT "%s)", " ", amount_in_current_scale(used), scale);
+  out->print_cr("%27s (    free=" SIZE_FORMAT "%s)", " ", amount_in_current_scale(free), scale);
+  out->print_cr("%27s (    waste=" SIZE_FORMAT "%s =%2.2f%%)", " ", amount_in_current_scale(waste),
+    scale, ((float)waste * 100)/committed);
+}
+
 void MemDetailReporter::report_detail() {
   // Start detail report
   outputStream* out = output();
@@ -305,9 +337,13 @@
     MEMFLAGS flag = NMTUtil::index_to_flag(index);
     // thread stack is reported as part of thread category
     if (flag == mtThreadStack) continue;
-    diff_summary_of_type(flag, _early_baseline.malloc_memory(flag),
-      _early_baseline.virtual_memory(flag), _current_baseline.malloc_memory(flag),
-      _current_baseline.virtual_memory(flag));
+    diff_summary_of_type(flag,
+      _early_baseline.malloc_memory(flag),
+      _early_baseline.virtual_memory(flag),
+      _early_baseline.metaspace_snapshot(),
+      _current_baseline.malloc_memory(flag),
+      _current_baseline.virtual_memory(flag),
+      _current_baseline.metaspace_snapshot());
   }
 }
 
@@ -367,9 +403,11 @@
 }
 
 
-void MemSummaryDiffReporter::diff_summary_of_type(MEMFLAGS flag, const MallocMemory* early_malloc,
-  const VirtualMemory* early_vm, const MallocMemory* current_malloc,
-  const VirtualMemory* current_vm) const {
+void MemSummaryDiffReporter::diff_summary_of_type(MEMFLAGS flag,
+  const MallocMemory* early_malloc, const VirtualMemory* early_vm,
+  const MetaspaceSnapshot* early_ms,
+  const MallocMemory* current_malloc, const VirtualMemory* current_vm,
+  const MetaspaceSnapshot* current_ms) const {
 
   outputStream* out = output();
   const char* scale = current_scale();
@@ -486,11 +524,77 @@
         out->print(" %+ld%s", overhead_diff, scale);
       }
       out->print_cr(")");
+    } else if (flag == mtClass) {
+      assert(current_ms != NULL && early_ms != NULL, "Sanity");
+      print_metaspace_diff(current_ms, early_ms);
     }
     out->print_cr(" ");
   }
 }
 
+void MemSummaryDiffReporter::print_metaspace_diff(const MetaspaceSnapshot* current_ms,
+                                                  const MetaspaceSnapshot* early_ms) const {
+  print_metaspace_diff(Metaspace::NonClassType, current_ms, early_ms);
+  if (Metaspace::using_class_space()) {
+    print_metaspace_diff(Metaspace::ClassType, current_ms, early_ms);
+  }
+}
+
+void MemSummaryDiffReporter::print_metaspace_diff(Metaspace::MetadataType type,
+                                                  const MetaspaceSnapshot* current_ms,
+                                                  const MetaspaceSnapshot* early_ms) const {
+  const char* name = (type == Metaspace::NonClassType) ?
+    "Metadata:   " : "Class space:";
+
+  outputStream* out = output();
+  const char* scale = current_scale();
+
+  out->print_cr("%27s (  %s)", " ", name);
+  out->print("%27s (    ", " ");
+  print_virtual_memory_diff(current_ms->reserved_in_bytes(type),
+                            current_ms->committed_in_bytes(type),
+                            early_ms->reserved_in_bytes(type),
+                            early_ms->committed_in_bytes(type));
+  out->print_cr(")");
+
+  long diff_used = diff_in_current_scale(current_ms->used_in_bytes(type),
+                                         early_ms->used_in_bytes(type));
+  long diff_free = diff_in_current_scale(current_ms->free_in_bytes(type),
+                                         early_ms->free_in_bytes(type));
+
+  size_t current_waste = current_ms->committed_in_bytes(type)
+    - (current_ms->used_in_bytes(type) + current_ms->free_in_bytes(type));
+  size_t early_waste = early_ms->committed_in_bytes(type)
+    - (early_ms->used_in_bytes(type) + early_ms->free_in_bytes(type));
+  long diff_waste = diff_in_current_scale(current_waste, early_waste);
+
+  // Diff used
+  out->print("%27s (    used=" SIZE_FORMAT "%s", " ",
+    amount_in_current_scale(current_ms->used_in_bytes(type)), scale);
+  if (diff_used != 0) {
+    out->print(" %+ld%s", diff_used, scale);
+  }
+  out->print_cr(")");
+
+  // Diff free
+  out->print("%27s (    free=" SIZE_FORMAT "%s", " ",
+    amount_in_current_scale(current_ms->free_in_bytes(type)), scale);
+  if (diff_free != 0) {
+    out->print(" %+ld%s", diff_free, scale);
+  }
+  out->print_cr(")");
+
+
+  // Diff waste
+  out->print("%27s (    waste=" SIZE_FORMAT "%s =%2.2f%%", " ",
+    amount_in_current_scale(current_waste), scale,
+    ((float)current_waste * 100) / current_ms->committed_in_bytes(type));
+  if (diff_waste != 0) {
+    out->print(" %+ld%s", diff_waste, scale);
+  }
+  out->print_cr(")");
+}
+
 void MemDetailDiffReporter::report_diff() {
   MemSummaryDiffReporter::report_diff();
   diff_malloc_sites();
--- a/src/hotspot/share/services/memReporter.hpp	Tue Sep 26 14:05:27 2017 +0200
+++ b/src/hotspot/share/services/memReporter.hpp	Thu Sep 28 09:56:54 2017 -0400
@@ -27,6 +27,7 @@
 
 #if INCLUDE_NMT
 
+#include "memory/metaspace.hpp"
 #include "oops/instanceKlass.hpp"
 #include "services/memBaseline.hpp"
 #include "services/nmtCommon.hpp"
@@ -110,6 +111,8 @@
   // Report summary for each memory type
   void report_summary_of_type(MEMFLAGS type, MallocMemory* malloc_memory,
     VirtualMemory* virtual_memory);
+
+  void report_metadata(Metaspace::MetadataType type) const;
 };
 
 /*
@@ -170,7 +173,9 @@
   // report the comparison of each memory type
   void diff_summary_of_type(MEMFLAGS type,
     const MallocMemory* early_malloc, const VirtualMemory* early_vm,
-    const MallocMemory* current_malloc, const VirtualMemory* current_vm) const;
+    const MetaspaceSnapshot* early_ms,
+    const MallocMemory* current_malloc, const VirtualMemory* current_vm,
+    const MetaspaceSnapshot* current_ms) const;
 
  protected:
   void print_malloc_diff(size_t current_amount, size_t current_count,
@@ -179,6 +184,11 @@
     size_t early_reserved, size_t early_committed) const;
   void print_arena_diff(size_t current_amount, size_t current_count,
     size_t early_amount, size_t early_count) const;
+
+  void print_metaspace_diff(const MetaspaceSnapshot* current_ms,
+                            const MetaspaceSnapshot* early_ms) const;
+  void print_metaspace_diff(Metaspace::MetadataType type,
+    const MetaspaceSnapshot* current_ms, const MetaspaceSnapshot* early_ms) const;
 };
 
 /*
--- a/src/hotspot/share/services/virtualMemoryTracker.cpp	Tue Sep 26 14:05:27 2017 +0200
+++ b/src/hotspot/share/services/virtualMemoryTracker.cpp	Thu Sep 28 09:56:54 2017 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2017, Oracle and/or its affiliates. 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
@@ -23,6 +23,7 @@
  */
 #include "precompiled.hpp"
 
+#include "memory/metaspace.hpp"
 #include "runtime/atomic.hpp"
 #include "runtime/os.hpp"
 #include "runtime/threadCritical.hpp"
@@ -492,3 +493,35 @@
 
   return true;
 }
+
+// Metaspace Support
+MetaspaceSnapshot::MetaspaceSnapshot() {
+  for (int index = (int)Metaspace::ClassType; index < (int)Metaspace::MetadataTypeCount; index ++) {
+    Metaspace::MetadataType type = (Metaspace::MetadataType)index;
+    assert_valid_metadata_type(type);
+    _reserved_in_bytes[type]  = 0;
+    _committed_in_bytes[type] = 0;
+    _used_in_bytes[type]      = 0;
+    _free_in_bytes[type]      = 0;
+  }
+}
+
+void MetaspaceSnapshot::snapshot(Metaspace::MetadataType type, MetaspaceSnapshot& mss) {
+  assert_valid_metadata_type(type);
+
+  mss._reserved_in_bytes[type]   = MetaspaceAux::reserved_bytes(type);
+  mss._committed_in_bytes[type]  = MetaspaceAux::committed_bytes(type);
+  mss._used_in_bytes[type]       = MetaspaceAux::used_bytes(type);
+
+  size_t free_in_bytes = (MetaspaceAux::capacity_bytes(type) - MetaspaceAux::used_bytes(type))
+                       + MetaspaceAux::free_chunks_total_bytes(type)
+                       + MetaspaceAux::free_bytes(type);
+  mss._free_in_bytes[type] = free_in_bytes;
+}
+
+void MetaspaceSnapshot::snapshot(MetaspaceSnapshot& mss) {
+  snapshot(Metaspace::ClassType, mss);
+  if (Metaspace::using_class_space()) {
+    snapshot(Metaspace::NonClassType, mss);
+  }
+}
--- a/src/hotspot/share/services/virtualMemoryTracker.hpp	Tue Sep 26 14:05:27 2017 +0200
+++ b/src/hotspot/share/services/virtualMemoryTracker.hpp	Thu Sep 28 09:56:54 2017 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2017, Oracle and/or its affiliates. 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
@@ -28,6 +28,7 @@
 #if INCLUDE_NMT
 
 #include "memory/allocation.hpp"
+#include "memory/metaspace.hpp"
 #include "services/allocationSite.hpp"
 #include "services/nmtCommon.hpp"
 #include "utilities/linkedlist.hpp"
@@ -419,6 +420,31 @@
 };
 
 
+class MetaspaceSnapshot : public ResourceObj {
+private:
+  size_t  _reserved_in_bytes[Metaspace::MetadataTypeCount];
+  size_t  _committed_in_bytes[Metaspace::MetadataTypeCount];
+  size_t  _used_in_bytes[Metaspace::MetadataTypeCount];
+  size_t  _free_in_bytes[Metaspace::MetadataTypeCount];
+
+public:
+  MetaspaceSnapshot();
+  size_t reserved_in_bytes(Metaspace::MetadataType type)   const { assert_valid_metadata_type(type); return _reserved_in_bytes[type]; }
+  size_t committed_in_bytes(Metaspace::MetadataType type)  const { assert_valid_metadata_type(type); return _committed_in_bytes[type]; }
+  size_t used_in_bytes(Metaspace::MetadataType type)       const { assert_valid_metadata_type(type); return _used_in_bytes[type]; }
+  size_t free_in_bytes(Metaspace::MetadataType type)       const { assert_valid_metadata_type(type); return _free_in_bytes[type]; }
+
+  static void snapshot(MetaspaceSnapshot& s);
+
+private:
+  static void snapshot(Metaspace::MetadataType type, MetaspaceSnapshot& s);
+
+  static void assert_valid_metadata_type(Metaspace::MetadataType type) {
+    assert(type == Metaspace::ClassType || type == Metaspace::NonClassType,
+      "Invalid metadata type");
+  }
+};
+
 #endif // INCLUDE_NMT
 
 #endif // SHARE_VM_SERVICES_VIRTUAL_MEMORY_TRACKER_HPP