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 */ 35 int 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 46 int 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 58 int compare_malloc_site(const MallocSite& s1, const MallocSite& s2) { 59 return s1.call_stack()->compare(*s2.call_stack()); 60 } 61 62 63 int 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 */ 71 class 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 103 int 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 108 class 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 135 bool MemBaseline::baseline_summary() { 136 MallocMemorySummary::snapshot(&_malloc_memory_snapshot); 137 VirtualMemorySummary::snapshot(&_virtual_memory_snapshot); 138 return true; 139 } 140 141 bool 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 170 bool 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 191 int compare_allocation_site(const VirtualMemoryAllocationSite& s1, 192 const VirtualMemoryAllocationSite& s2) { 193 return s1.call_stack()->compare(*s2.call_stack()); 194 } 195 196 bool 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 219 MallocSiteIterator 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 235 VirtualMemorySiteIterator 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 253 void 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 265 void 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 276 void 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 288 void 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