1 /*
   2  * Copyright (c) 2012, 2019, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  *
  23  */
  24 
  25 #ifndef SHARE_SERVICES_MEMREPORTER_HPP
  26 #define SHARE_SERVICES_MEMREPORTER_HPP
  27 
  28 #if INCLUDE_NMT
  29 
  30 #include "memory/metaspace/metaspaceEnums.hpp"
  31 #include "oops/instanceKlass.hpp"
  32 #include "services/memBaseline.hpp"
  33 #include "services/nmtCommon.hpp"
  34 #include "services/mallocTracker.hpp"
  35 #include "services/virtualMemoryTracker.hpp"
  36 
  37 /*
  38  * Base class that provides helpers
  39 */
  40 class MemReporterBase : public StackObj {
  41  private:
  42   size_t        _scale;  // report in this scale
  43   outputStream* _output; // destination
  44 
  45  public:
  46   MemReporterBase(outputStream* out = NULL, size_t scale = K)
  47     : _scale(scale) {
  48     _output = (out == NULL) ? tty : out;
  49   }
  50 
  51  protected:
  52   inline outputStream* output() const {
  53     return _output;
  54   }
  55   // Current reporting scale
  56   inline const char* current_scale() const {
  57     return NMTUtil::scale_name(_scale);
  58   }
  59   // Convert memory amount in bytes to current reporting scale
  60   inline size_t amount_in_current_scale(size_t amount) const {
  61     return NMTUtil::amount_in_scale(amount, _scale);
  62   }
  63 
  64   // Convert diff amount in bytes to current reporting scale
  65   inline long diff_in_current_scale(size_t s1, size_t s2) const {
  66     long amount = (long)(s1 - s2);
  67     long scale = (long)_scale;
  68     amount = (amount > 0) ? (amount + scale / 2) : (amount - scale / 2);
  69     return amount / scale;
  70   }
  71 
  72   // Helper functions
  73   // Calculate total reserved and committed amount
  74   size_t reserved_total(const MallocMemory* malloc, const VirtualMemory* vm) const;
  75   size_t committed_total(const MallocMemory* malloc, const VirtualMemory* vm) const;
  76 
  77 
  78   // Print summary total, malloc and virtual memory
  79   void print_total(size_t reserved, size_t committed) const;
  80   void print_malloc(size_t amount, size_t count, MEMFLAGS flag = mtNone) const;
  81   void print_virtual_memory(size_t reserved, size_t committed) const;
  82 
  83   void print_malloc_line(size_t amount, size_t count) const;
  84   void print_virtual_memory_line(size_t reserved, size_t committed) const;
  85   void print_arena_line(size_t amount, size_t count) const;
  86 
  87   void print_virtual_memory_region(const char* type, address base, size_t size) const;
  88 };
  89 
  90 /*
  91  * The class is for generating summary tracking report.
  92  */
  93 class MemSummaryReporter : public MemReporterBase {
  94  private:
  95   MallocMemorySnapshot*   _malloc_snapshot;
  96   VirtualMemorySnapshot*  _vm_snapshot;
  97   size_t                  _instance_class_count;
  98   size_t                  _array_class_count;
  99 
 100  public:
 101   // This constructor is for normal reporting from a recent baseline.
 102   MemSummaryReporter(MemBaseline& baseline, outputStream* output,
 103     size_t scale = K) : MemReporterBase(output, scale),
 104     _malloc_snapshot(baseline.malloc_memory_snapshot()),
 105     _vm_snapshot(baseline.virtual_memory_snapshot()),
 106     _instance_class_count(baseline.instance_class_count()),
 107     _array_class_count(baseline.array_class_count()) { }
 108 
 109 
 110   // Generate summary report
 111   virtual void report();
 112  private:
 113   // Report summary for each memory type
 114   void report_summary_of_type(MEMFLAGS type, MallocMemory* malloc_memory,
 115     VirtualMemory* virtual_memory);
 116 
 117   void report_metadata(metaspace::MetadataType type) const;
 118 };
 119 
 120 /*
 121  * The class is for generating detail tracking report.
 122  */
 123 class MemDetailReporter : public MemSummaryReporter {
 124  private:
 125   MemBaseline&   _baseline;
 126 
 127  public:
 128   MemDetailReporter(MemBaseline& baseline, outputStream* output, size_t scale = K) :
 129     MemSummaryReporter(baseline, output, scale),
 130      _baseline(baseline) { }
 131 
 132   // Generate detail report.
 133   // The report contains summary and detail sections.
 134   virtual void report() {
 135     MemSummaryReporter::report();
 136     report_virtual_memory_map();
 137     report_detail();
 138   }
 139 
 140  private:
 141   // Report detail tracking data.
 142   void report_detail();
 143   // Report virtual memory map
 144   void report_virtual_memory_map();
 145   // Report malloc allocation sites
 146   void report_malloc_sites();
 147   // Report virtual memory reservation sites
 148   void report_virtual_memory_allocation_sites();
 149 
 150   // Report a virtual memory region
 151   void report_virtual_memory_region(const ReservedMemoryRegion* rgn);
 152 };
 153 
 154 /*
 155  * The class is for generating summary comparison report.
 156  * It compares current memory baseline against an early baseline.
 157  */
 158 class MemSummaryDiffReporter : public MemReporterBase {
 159  protected:
 160   MemBaseline&      _early_baseline;
 161   MemBaseline&      _current_baseline;
 162 
 163  public:
 164   MemSummaryDiffReporter(MemBaseline& early_baseline, MemBaseline& current_baseline,
 165     outputStream* output, size_t scale = K) : MemReporterBase(output, scale),
 166     _early_baseline(early_baseline), _current_baseline(current_baseline) {
 167     assert(early_baseline.baseline_type()   != MemBaseline::Not_baselined, "Not baselined");
 168     assert(current_baseline.baseline_type() != MemBaseline::Not_baselined, "Not baselined");
 169   }
 170 
 171   // Generate summary comparison report
 172   virtual void report_diff();
 173 
 174  private:
 175   // report the comparison of each memory type
 176   void diff_summary_of_type(MEMFLAGS type,
 177     const MallocMemory* early_malloc, const VirtualMemory* early_vm,
 178     const MetaspaceSnapshot* early_ms,
 179     const MallocMemory* current_malloc, const VirtualMemory* current_vm,
 180     const MetaspaceSnapshot* current_ms) const;
 181 
 182  protected:
 183   void print_malloc_diff(size_t current_amount, size_t current_count,
 184     size_t early_amount, size_t early_count, MEMFLAGS flags) const;
 185   void print_virtual_memory_diff(size_t current_reserved, size_t current_committed,
 186     size_t early_reserved, size_t early_committed) const;
 187   void print_arena_diff(size_t current_amount, size_t current_count,
 188     size_t early_amount, size_t early_count) const;
 189 
 190   void print_metaspace_diff(const MetaspaceSnapshot* current_ms,
 191                             const MetaspaceSnapshot* early_ms) const;
 192   void print_metaspace_diff(metaspace::MetadataType type,
 193     const MetaspaceSnapshot* current_ms, const MetaspaceSnapshot* early_ms) const;
 194 };
 195 
 196 /*
 197  * The class is for generating detail comparison report.
 198  * It compares current memory baseline against an early baseline,
 199  * both baselines have to be detail baseline.
 200  */
 201 class MemDetailDiffReporter : public MemSummaryDiffReporter {
 202  public:
 203   MemDetailDiffReporter(MemBaseline& early_baseline, MemBaseline& current_baseline,
 204     outputStream* output, size_t scale = K) :
 205     MemSummaryDiffReporter(early_baseline, current_baseline, output, scale) { }
 206 
 207   // Generate detail comparison report
 208   virtual void report_diff();
 209 
 210   // Malloc allocation site comparison
 211   void diff_malloc_sites() const;
 212   // Virutal memory reservation site comparison
 213   void diff_virtual_memory_sites() const;
 214 
 215   // New malloc allocation site in recent baseline
 216   void new_malloc_site (const MallocSite* site) const;
 217   // The malloc allocation site is not in recent baseline
 218   void old_malloc_site (const MallocSite* site) const;
 219   // Compare malloc allocation site, it is in both baselines
 220   void diff_malloc_site(const MallocSite* early, const MallocSite* current)  const;
 221 
 222   // New virtual memory allocation site in recent baseline
 223   void new_virtual_memory_site (const VirtualMemoryAllocationSite* callsite) const;
 224   // The virtual memory allocation site is not in recent baseline
 225   void old_virtual_memory_site (const VirtualMemoryAllocationSite* callsite) const;
 226   // Compare virtual memory allocation site, it is in both baseline
 227   void diff_virtual_memory_site(const VirtualMemoryAllocationSite* early,
 228                                 const VirtualMemoryAllocationSite* current)  const;
 229 
 230   void diff_malloc_site(const NativeCallStack* stack, size_t current_size,
 231     size_t currrent_count, size_t early_size, size_t early_count, MEMFLAGS flags) const;
 232   void diff_virtual_memory_site(const NativeCallStack* stack, size_t current_reserved,
 233     size_t current_committed, size_t early_reserved, size_t early_committed, MEMFLAGS flag) const;
 234 };
 235 
 236 #endif // INCLUDE_NMT
 237 
 238 #endif // SHARE_SERVICES_MEMREPORTER_HPP