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, ResourceObj::ARENA> 74 _malloc_sites; 75 size_t _count; 76 77 // Entries in MallocSiteTable with size = 0 and count = 0, 78 // when the malloc site is not longer there. 79 public: 80 MallocAllocationSiteWalker(Arena* arena) : _count(0), _malloc_sites(arena) { 81 } 82 83 inline size_t count() const { return _count; } 84 85 LinkedList<MallocSite>* malloc_sites() { 86 return &_malloc_sites; 87 } 88 89 bool do_malloc_site(const MallocSite* site) { 90 if (site->size() >= MemBaseline::SIZE_THRESHOLD) { 91 if (_malloc_sites.add(*site) != NULL) { 92 _count++; 93 return true; 94 } else { 95 return false; // OOM 96 } 97 } else { 98 // malloc site does not meet threshold, ignore and continue 99 return true; 100 } 101 } 102 }; 103 104 // Compare virtual memory region's base address 105 int compare_virtual_memory_base(const ReservedMemoryRegion& r1, const ReservedMemoryRegion& r2) { 106 return r1.compare(r2); 107 } 108 109 // Walk all virtual memory regions for baselining 110 class VirtualMemoryAllocationWalker : public VirtualMemoryWalker { 111 private: 112 SortedLinkedList<ReservedMemoryRegion, compare_virtual_memory_base, ResourceObj::ARENA> 113 _virtual_memory_regions; 114 size_t _count; 115 116 public: 117 VirtualMemoryAllocationWalker(Arena* a) : _count(0), _virtual_memory_regions(a) { 118 } 119 120 bool do_allocation_site(const ReservedMemoryRegion* rgn) { 121 if (rgn->size() >= MemBaseline::SIZE_THRESHOLD) { 122 if (_virtual_memory_regions.add(*rgn) != NULL) { 123 _count ++; 124 return true; 125 } else { 126 return false; 127 } 128 } 129 return true; 130 } 131 132 LinkedList<ReservedMemoryRegion>* virtual_memory_allocations() { 133 return &_virtual_memory_regions; 134 } 135 }; 136 137 138 bool MemBaseline::baseline_summary() { 139 assert(_malloc_memory_snapshot == NULL, "Malloc baseline not yet reset"); 140 assert(_virtual_memory_snapshot == NULL, "Virtual baseline not yet reset"); 141 142 _malloc_memory_snapshot = new (arena()) MallocMemorySnapshot(); 143 _virtual_memory_snapshot = new (arena()) VirtualMemorySnapshot(); 144 if (_malloc_memory_snapshot == NULL || _virtual_memory_snapshot == NULL) { 145 return false; 146 } 147 MallocMemorySummary::snapshot(_malloc_memory_snapshot); 148 VirtualMemorySummary::snapshot(_virtual_memory_snapshot); 149 return true; 150 } 151 152 bool MemBaseline::baseline_allocation_sites() { 153 assert(arena() != NULL, "Just check"); 154 // Malloc allocation sites 155 MallocAllocationSiteWalker malloc_walker(arena()); 156 if (!MallocSiteTable::walk_malloc_site(&malloc_walker)) { 157 return false; 158 } 159 160 _malloc_sites.set_head(malloc_walker.malloc_sites()->head()); 161 // The malloc sites are collected in size order 162 _malloc_sites_order = by_size; 163 164 // Virtual memory allocation sites 165 VirtualMemoryAllocationWalker virtual_memory_walker(arena()); 166 if (!VirtualMemoryTracker::walk_virtual_memory(&virtual_memory_walker)) { 167 return false; 168 } 169 170 // Virtual memory allocations are collected in call stack order 171 _virtual_memory_allocations.set_head(virtual_memory_walker.virtual_memory_allocations()->head()); 172 173 if (!aggregate_virtual_memory_allocation_sites()) { 174 return false; 175 } 176 // Virtual memory allocation sites are aggregrated in call stack order 177 _virtual_memory_sites_order = by_address; 178 179 return true; 180 } 181 182 bool MemBaseline::baseline(bool summaryOnly) { 183 if (arena() == NULL) { 184 _arena = new (std::nothrow, mtNMT) Arena(mtNMT); 185 if (arena() == NULL) return false; 186 } 187 188 reset(); 189 190 _class_count = InstanceKlass::number_of_instance_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 208 int compare_allocation_site(const VirtualMemoryAllocationSite& s1, 209 const VirtualMemoryAllocationSite& s2) { 210 return s1.call_stack()->compare(*s2.call_stack()); 211 } 212 213 bool MemBaseline::aggregate_virtual_memory_allocation_sites() { 214 SortedLinkedList<VirtualMemoryAllocationSite, compare_allocation_site, ResourceObj::ARENA> 215 allocation_sites(arena()); 216 217 VirtualMemoryAllocationIterator itr = virtual_memory_allocations(); 218 const ReservedMemoryRegion* rgn; 219 VirtualMemoryAllocationSite* site; 220 while ((rgn = itr.next()) != NULL) { 221 VirtualMemoryAllocationSite tmp(*rgn->call_stack()); 222 site = allocation_sites.find(tmp); 223 if (site == NULL) { 224 LinkedListNode<VirtualMemoryAllocationSite>* node = 225 allocation_sites.add(tmp); 226 if (node == NULL) return false; 227 site = node->data(); 228 } 229 site->reserve_memory(rgn->size()); 230 site->commit_memory(rgn->committed_size()); 231 } 232 233 _virtual_memory_sites.set_head(allocation_sites.head()); 234 return true; 235 } 236 237 MallocSiteIterator MemBaseline::malloc_sites(SortingOrder order) { 238 assert(!_malloc_sites.is_empty(), "Detail baseline?"); 239 switch(order) { 240 case by_size: 241 malloc_sites_to_size_order(); 242 break; 243 case by_site: 244 malloc_sites_to_allocation_site_order(); 245 break; 246 case by_address: 247 default: 248 ShouldNotReachHere(); 249 } 250 return MallocSiteIterator(_malloc_sites.head()); 251 } 252 253 VirtualMemorySiteIterator MemBaseline::virtual_memory_sites(SortingOrder order) { 254 assert(!_virtual_memory_sites.is_empty(), "Detail baseline?"); 255 switch(order) { 256 case by_size: 257 virtual_memory_sites_to_size_order(); 258 break; 259 case by_site: 260 virtual_memory_sites_to_reservation_site_order(); 261 break; 262 case by_address: 263 default: 264 ShouldNotReachHere(); 265 } 266 return VirtualMemorySiteIterator(_virtual_memory_sites.head()); 267 } 268 269 270 // Sorting allocations sites in different orders 271 void MemBaseline::malloc_sites_to_size_order() { 272 if (_malloc_sites_order != by_size) { 273 SortedLinkedList<MallocSite, compare_malloc_size, ResourceObj::ARENA> 274 tmp(arena()); 275 276 // Add malloc sites to sorted linked list to sort into size order 277 tmp.move(&_malloc_sites); 278 _malloc_sites.set_head(tmp.head()); 279 tmp.set_head(NULL); 280 _malloc_sites_order = by_size; 281 } 282 } 283 284 void MemBaseline::malloc_sites_to_allocation_site_order() { 285 if (_malloc_sites_order != by_site) { 286 SortedLinkedList<MallocSite, compare_malloc_site, ResourceObj::ARENA> 287 tmp(arena()); 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 296 void MemBaseline::virtual_memory_sites_to_size_order() { 297 if (_virtual_memory_sites_order != by_size) { 298 SortedLinkedList<VirtualMemoryAllocationSite, compare_virtual_memory_size, ResourceObj::ARENA> 299 tmp(arena()); 300 301 tmp.move(&_virtual_memory_sites); 302 303 _virtual_memory_sites.set_head(tmp.head()); 304 tmp.set_head(NULL); 305 _virtual_memory_sites_order = by_size; 306 } 307 } 308 309 void MemBaseline::virtual_memory_sites_to_reservation_site_order() { 310 if (_virtual_memory_sites_order != by_size) { 311 SortedLinkedList<VirtualMemoryAllocationSite, compare_virtual_memory_site, ResourceObj::ARENA> 312 tmp(arena()); 313 314 tmp.add(&_virtual_memory_sites); 315 316 _virtual_memory_sites.set_head(tmp.head()); 317 tmp.set_head(NULL); 318 319 _virtual_memory_sites_order = by_size; 320 } 321 } 322