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