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