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