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