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