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