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.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*/
40class 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 */
93class 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 */
123class 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 */
158class 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 */
201class 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
239