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 #include "precompiled.hpp"
25
26 #include "classfile/classLoaderDataGraph.inline.hpp"
27 #include "memory/allocation.hpp"
28 #include "memory/metaspaceUtils.hpp"
29 #include "runtime/safepoint.hpp"
30 #include "runtime/thread.inline.hpp"
31 #include "services/memBaseline.hpp"
32 #include "services/memTracker.hpp"
33
34 /*
35 * Sizes are sorted in descenting order for reporting
36 */
compare_malloc_size(const MallocSite & s1,const MallocSite & s2)37 int compare_malloc_size(const MallocSite& s1, const MallocSite& s2) {
38 if (s1.size() == s2.size()) {
39 return 0;
40 } else if (s1.size() > s2.size()) {
41 return -1;
42 } else {
43 return 1;
44 }
45 }
46
47
compare_virtual_memory_size(const VirtualMemoryAllocationSite & s1,const VirtualMemoryAllocationSite & s2)48 int compare_virtual_memory_size(const VirtualMemoryAllocationSite& s1,
49 const VirtualMemoryAllocationSite& s2) {
50 if (s1.reserved() == s2.reserved()) {
51 return 0;
52 } else if (s1.reserved() > s2.reserved()) {
53 return -1;
54 } else {
55 return 1;
56 }
57 }
58
59 // Sort into allocation site addresses order for baseline comparison
compare_malloc_site(const MallocSite & s1,const MallocSite & s2)60 int compare_malloc_site(const MallocSite& s1, const MallocSite& s2) {
61 return s1.call_stack()->compare(*s2.call_stack());
62 }
63
64 // Sort into allocation site addresses and memory type order for baseline comparison
compare_malloc_site_and_type(const MallocSite & s1,const MallocSite & s2)65 int compare_malloc_site_and_type(const MallocSite& s1, const MallocSite& s2) {
66 int res = compare_malloc_site(s1, s2);
67 if (res == 0) {
68 res = (int)(NMTUtil::flag_to_index(s1.flag()) - NMTUtil::flag_to_index(s2.flag()));
69 }
70
71 return res;
72 }
73
compare_virtual_memory_site(const VirtualMemoryAllocationSite & s1,const VirtualMemoryAllocationSite & s2)74 int compare_virtual_memory_site(const VirtualMemoryAllocationSite& s1,
75 const VirtualMemoryAllocationSite& s2) {
76 return s1.call_stack()->compare(*s2.call_stack());
77 }
78
79 /*
80 * Walker to walk malloc allocation site table
81 */
82 class MallocAllocationSiteWalker : public MallocSiteWalker {
83 private:
84 SortedLinkedList<MallocSite, compare_malloc_size> _malloc_sites;
85 size_t _count;
86
87 // Entries in MallocSiteTable with size = 0 and count = 0,
88 // when the malloc site is not longer there.
89 public:
MallocAllocationSiteWalker()90 MallocAllocationSiteWalker() : _count(0) { }
91
count() const92 inline size_t count() const { return _count; }
93
malloc_sites()94 LinkedList<MallocSite>* malloc_sites() {
95 return &_malloc_sites;
96 }
97
do_malloc_site(const MallocSite * site)98 bool do_malloc_site(const MallocSite* site) {
99 if (site->size() > 0) {
100 if (_malloc_sites.add(*site) != NULL) {
101 _count++;
102 return true;
103 } else {
104 return false; // OOM
105 }
106 } else {
107 // Ignore empty sites.
108 return true;
109 }
110 }
111 };
112
113 // Compare virtual memory region's base address
compare_virtual_memory_base(const ReservedMemoryRegion & r1,const ReservedMemoryRegion & r2)114 int compare_virtual_memory_base(const ReservedMemoryRegion& r1, const ReservedMemoryRegion& r2) {
115 return r1.compare(r2);
116 }
117
118 // Walk all virtual memory regions for baselining
119 class VirtualMemoryAllocationWalker : public VirtualMemoryWalker {
120 private:
121 SortedLinkedList<ReservedMemoryRegion, compare_virtual_memory_base>
122 _virtual_memory_regions;
123 size_t _count;
124
125 public:
VirtualMemoryAllocationWalker()126 VirtualMemoryAllocationWalker() : _count(0) { }
127
do_allocation_site(const ReservedMemoryRegion * rgn)128 bool do_allocation_site(const ReservedMemoryRegion* rgn) {
129 if (rgn->size() > 0) {
130 if (_virtual_memory_regions.add(*rgn) != NULL) {
131 _count ++;
132 return true;
133 } else {
134 return false;
135 }
136 } else {
137 // Ignore empty sites.
138 return true;
139 }
140 }
141
virtual_memory_allocations()142 LinkedList<ReservedMemoryRegion>* virtual_memory_allocations() {
143 return &_virtual_memory_regions;
144 }
145 };
146
147
baseline_summary()148 bool MemBaseline::baseline_summary() {
149 MallocMemorySummary::snapshot(&_malloc_memory_snapshot);
150 VirtualMemorySummary::snapshot(&_virtual_memory_snapshot);
151 _metaspace_stats = MetaspaceUtils::get_combined_statistics();
152 return true;
153 }
154
baseline_allocation_sites()155 bool MemBaseline::baseline_allocation_sites() {
156 // Malloc allocation sites
157 MallocAllocationSiteWalker malloc_walker;
158 if (!MallocSiteTable::walk_malloc_site(&malloc_walker)) {
159 return false;
160 }
161
162 // Walk simple thread stacks
163 if (!ThreadStackTracker::walk_simple_thread_stack_site(&malloc_walker)) {
164 return false;
165 }
166
167 _malloc_sites.move(malloc_walker.malloc_sites());
168 // The malloc sites are collected in size order
169 _malloc_sites_order = by_size;
170
171 // Virtual memory allocation sites
172 VirtualMemoryAllocationWalker virtual_memory_walker;
173 if (!VirtualMemoryTracker::walk_virtual_memory(&virtual_memory_walker)) {
174 return false;
175 }
176
177 // Virtual memory allocations are collected in call stack order
178 _virtual_memory_allocations.move(virtual_memory_walker.virtual_memory_allocations());
179
180 if (!aggregate_virtual_memory_allocation_sites()) {
181 return false;
182 }
183 // Virtual memory allocation sites are aggregrated in call stack order
184 _virtual_memory_sites_order = by_address;
185
186 return true;
187 }
188
baseline(bool summaryOnly)189 bool MemBaseline::baseline(bool summaryOnly) {
190 reset();
191
192 _instance_class_count = ClassLoaderDataGraph::num_instance_classes();
193 _array_class_count = ClassLoaderDataGraph::num_array_classes();
194
195 if (!baseline_summary()) {
196 return false;
197 }
198
199 _baseline_type = Summary_baselined;
200
201 // baseline details
202 if (!summaryOnly &&
203 MemTracker::tracking_level() == NMT_detail) {
204 baseline_allocation_sites();
205 _baseline_type = Detail_baselined;
206 }
207
208 return true;
209 }
210
compare_allocation_site(const VirtualMemoryAllocationSite & s1,const VirtualMemoryAllocationSite & s2)211 int compare_allocation_site(const VirtualMemoryAllocationSite& s1,
212 const VirtualMemoryAllocationSite& s2) {
213 return s1.call_stack()->compare(*s2.call_stack());
214 }
215
aggregate_virtual_memory_allocation_sites()216 bool MemBaseline::aggregate_virtual_memory_allocation_sites() {
217 SortedLinkedList<VirtualMemoryAllocationSite, compare_allocation_site> allocation_sites;
218
219 VirtualMemoryAllocationIterator itr = virtual_memory_allocations();
220 const ReservedMemoryRegion* rgn;
221 VirtualMemoryAllocationSite* site;
222 while ((rgn = itr.next()) != NULL) {
223 VirtualMemoryAllocationSite tmp(*rgn->call_stack(), rgn->flag());
224 site = allocation_sites.find(tmp);
225 if (site == NULL) {
226 LinkedListNode<VirtualMemoryAllocationSite>* node =
227 allocation_sites.add(tmp);
228 if (node == NULL) return false;
229 site = node->data();
230 }
231 site->reserve_memory(rgn->size());
232 site->commit_memory(rgn->committed_size());
233 }
234
235 _virtual_memory_sites.move(&allocation_sites);
236 return true;
237 }
238
malloc_sites(SortingOrder order)239 MallocSiteIterator MemBaseline::malloc_sites(SortingOrder order) {
240 assert(!_malloc_sites.is_empty(), "Not detail baseline");
241 switch(order) {
242 case by_size:
243 malloc_sites_to_size_order();
244 break;
245 case by_site:
246 malloc_sites_to_allocation_site_order();
247 break;
248 case by_site_and_type:
249 malloc_sites_to_allocation_site_and_type_order();
250 break;
251 case by_address:
252 default:
253 ShouldNotReachHere();
254 }
255 return MallocSiteIterator(_malloc_sites.head());
256 }
257
virtual_memory_sites(SortingOrder order)258 VirtualMemorySiteIterator MemBaseline::virtual_memory_sites(SortingOrder order) {
259 assert(!_virtual_memory_sites.is_empty(), "Not detail baseline");
260 switch(order) {
261 case by_size:
262 virtual_memory_sites_to_size_order();
263 break;
264 case by_site:
265 virtual_memory_sites_to_reservation_site_order();
266 break;
267 case by_address:
268 default:
269 ShouldNotReachHere();
270 }
271 return VirtualMemorySiteIterator(_virtual_memory_sites.head());
272 }
273
274
275 // Sorting allocations sites in different orders
malloc_sites_to_size_order()276 void MemBaseline::malloc_sites_to_size_order() {
277 if (_malloc_sites_order != by_size) {
278 SortedLinkedList<MallocSite, compare_malloc_size> tmp;
279
280 // Add malloc sites to sorted linked list to sort into size order
281 tmp.move(&_malloc_sites);
282 _malloc_sites.set_head(tmp.head());
283 tmp.set_head(NULL);
284 _malloc_sites_order = by_size;
285 }
286 }
287
malloc_sites_to_allocation_site_order()288 void MemBaseline::malloc_sites_to_allocation_site_order() {
289 if (_malloc_sites_order != by_site && _malloc_sites_order != by_site_and_type) {
290 SortedLinkedList<MallocSite, compare_malloc_site> tmp;
291 // Add malloc sites to sorted linked list to sort into site (address) order
292 tmp.move(&_malloc_sites);
293 _malloc_sites.set_head(tmp.head());
294 tmp.set_head(NULL);
295 _malloc_sites_order = by_site;
296 }
297 }
298
malloc_sites_to_allocation_site_and_type_order()299 void MemBaseline::malloc_sites_to_allocation_site_and_type_order() {
300 if (_malloc_sites_order != by_site_and_type) {
301 SortedLinkedList<MallocSite, compare_malloc_site_and_type> tmp;
302 // Add malloc sites to sorted linked list to sort into site (address) order
303 tmp.move(&_malloc_sites);
304 _malloc_sites.set_head(tmp.head());
305 tmp.set_head(NULL);
306 _malloc_sites_order = by_site_and_type;
307 }
308 }
309
virtual_memory_sites_to_size_order()310 void MemBaseline::virtual_memory_sites_to_size_order() {
311 if (_virtual_memory_sites_order != by_size) {
312 SortedLinkedList<VirtualMemoryAllocationSite, compare_virtual_memory_size> tmp;
313
314 tmp.move(&_virtual_memory_sites);
315
316 _virtual_memory_sites.set_head(tmp.head());
317 tmp.set_head(NULL);
318 _virtual_memory_sites_order = by_size;
319 }
320 }
321
virtual_memory_sites_to_reservation_site_order()322 void MemBaseline::virtual_memory_sites_to_reservation_site_order() {
323 if (_virtual_memory_sites_order != by_size) {
324 SortedLinkedList<VirtualMemoryAllocationSite, compare_virtual_memory_site> tmp;
325
326 tmp.move(&_virtual_memory_sites);
327
328 _virtual_memory_sites.set_head(tmp.head());
329 tmp.set_head(NULL);
330
331 _virtual_memory_sites_order = by_size;
332 }
333 }
334
335