1 /*
   2  * Copyright (c) 2012, 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 
  25 #ifndef SHARE_VM_SERVICES_MEM_BASELINE_HPP
  26 #define SHARE_VM_SERVICES_MEM_BASELINE_HPP
  27 
  28 #include "memory/allocation.hpp"
  29 #include "runtime/mutex.hpp"
  30 #include "services/memPtr.hpp"
  31 #include "services/memSnapshot.hpp"
  32 
  33 // compare unsigned number
  34 #define UNSIGNED_COMPARE(a, b)  ((a > b) ? 1 : ((a == b) ? 0 : -1))
  35 
  36 /*
  37  * MallocCallsitePointer and VMCallsitePointer are used
  38  * to baseline memory blocks with their callsite information.
  39  * They are only available when detail tracking is turned
  40  * on.
  41  */
  42 
  43 /* baselined malloc record aggregated by callsite */
  44 class MallocCallsitePointer : public MemPointer {
  45  private:
  46   size_t    _count;   // number of malloc invocation from this callsite
  47   size_t    _amount;  // total amount of memory malloc-ed from this callsite
  48 
  49  public:
  50   MallocCallsitePointer() {
  51     _count = 0;
  52     _amount = 0;
  53   }
  54 
  55   MallocCallsitePointer(address pc) : MemPointer(pc) {
  56     _count = 0;
  57     _amount = 0;
  58   }
  59 
  60   MallocCallsitePointer& operator=(const MallocCallsitePointer& p) {
  61     MemPointer::operator=(p);
  62     _count = p.count();
  63     _amount = p.amount();
  64     return *this;
  65   }
  66 
  67   inline void inc(size_t size) {
  68     _count ++;
  69     _amount += size;
  70   };
  71 
  72   inline size_t count() const {
  73     return _count;
  74   }
  75 
  76   inline size_t amount() const {
  77     return _amount;
  78   }
  79 };
  80 
  81 // baselined virtual memory record aggregated by callsite
  82 class VMCallsitePointer : public MemPointer {
  83  private:
  84   size_t     _count;              // number of invocation from this callsite
  85   size_t     _reserved_amount;    // total reserved amount
  86   size_t     _committed_amount;   // total committed amount
  87 
  88  public:
  89   VMCallsitePointer() {
  90     _count = 0;
  91     _reserved_amount = 0;
  92     _committed_amount = 0;
  93   }
  94 
  95   VMCallsitePointer(address pc) : MemPointer(pc) {
  96     _count = 0;
  97     _reserved_amount = 0;
  98     _committed_amount = 0;
  99   }
 100 
 101   VMCallsitePointer& operator=(const VMCallsitePointer& p) {
 102     MemPointer::operator=(p);
 103     _count = p.count();
 104     _reserved_amount = p.reserved_amount();
 105     _committed_amount = p.committed_amount();
 106     return *this;
 107   }
 108 
 109   inline void inc(size_t reserved, size_t committed) {
 110     _count ++;
 111     _reserved_amount += reserved;
 112     _committed_amount += committed;
 113   }
 114 
 115   inline size_t count() const {
 116     return _count;
 117   }
 118 
 119   inline size_t reserved_amount() const {
 120     return _reserved_amount;
 121   }
 122 
 123   inline size_t committed_amount() const {
 124     return _committed_amount;
 125   }
 126 };
 127 
 128 // maps a memory type flag to readable name
 129 typedef struct _memType2Name {
 130   MEMFLAGS     _flag;
 131   const char*  _name;
 132 } MemType2Name;
 133 
 134 
 135 // This class aggregates malloc'd records by memory type
 136 class MallocMem : public _ValueObj {
 137  private:
 138   MEMFLAGS       _type;
 139 
 140   size_t         _count;
 141   size_t         _amount;
 142 
 143  public:
 144   MallocMem() {
 145     _type = mtNone;
 146     _count = 0;
 147     _amount = 0;
 148   }
 149 
 150   MallocMem(MEMFLAGS flags) {
 151     assert(HAS_VALID_MEMORY_TYPE(flags), "no type");
 152     _type = FLAGS_TO_MEMORY_TYPE(flags);
 153     _count = 0;
 154     _amount = 0;
 155   }
 156 
 157   inline void set_type(MEMFLAGS flag) {
 158     _type = flag;
 159   }
 160 
 161   inline void clear() {
 162     _count = 0;
 163     _amount = 0;
 164     _type = mtNone;
 165   }
 166 
 167   MallocMem& operator=(const MallocMem& m) {
 168     assert(_type == m.type(), "different type");
 169     _count = m.count();
 170     _amount = m.amount();
 171     return *this;
 172   }
 173 
 174   inline void inc(size_t amt) {
 175     _amount += amt;
 176     _count ++;
 177   }
 178 
 179   inline void reduce(size_t amt) {
 180     assert(_amount >= amt, "Just check");
 181     _amount -= amt;
 182   }
 183 
 184   inline void overwrite_counter(size_t count) {
 185     _count = count;
 186   }
 187 
 188   inline MEMFLAGS type() const {
 189     return _type;
 190   }
 191 
 192   inline bool is_type(MEMFLAGS flags) const {
 193     return FLAGS_TO_MEMORY_TYPE(flags) == _type;
 194   }
 195 
 196   inline size_t count() const {
 197     return _count;
 198   }
 199 
 200   inline size_t amount() const {
 201     return _amount;
 202   }
 203 };
 204 
 205 // This class records live arena's memory usage
 206 class ArenaMem : public MallocMem {
 207  public:
 208   ArenaMem(MEMFLAGS typeflag): MallocMem(typeflag) {
 209   }
 210   ArenaMem() { }
 211 };
 212 
 213 // This class aggregates virtual memory by its memory type
 214 class VMMem : public _ValueObj {
 215  private:
 216   MEMFLAGS       _type;
 217 
 218   size_t         _count;
 219   size_t         _reserved_amount;
 220   size_t         _committed_amount;
 221 
 222  public:
 223   VMMem() {
 224     _type = mtNone;
 225     _count = 0;
 226     _reserved_amount = 0;
 227     _committed_amount = 0;
 228   }
 229 
 230   VMMem(MEMFLAGS flags) {
 231     assert(HAS_VALID_MEMORY_TYPE(flags), "no type");
 232     _type = FLAGS_TO_MEMORY_TYPE(flags);
 233     _count = 0;
 234     _reserved_amount = 0;
 235     _committed_amount = 0;
 236   }
 237 
 238   inline void clear() {
 239     _type = mtNone;
 240     _count = 0;
 241     _reserved_amount = 0;
 242     _committed_amount = 0;
 243   }
 244 
 245   inline void set_type(MEMFLAGS flags) {
 246     _type = FLAGS_TO_MEMORY_TYPE(flags);
 247   }
 248 
 249   VMMem& operator=(const VMMem& m) {
 250     assert(_type == m.type(), "different type");
 251 
 252     _count = m.count();
 253     _reserved_amount = m.reserved_amount();
 254     _committed_amount = m.committed_amount();
 255     return *this;
 256   }
 257 
 258 
 259   inline MEMFLAGS type() const {
 260     return _type;
 261   }
 262 
 263   inline bool is_type(MEMFLAGS flags) const {
 264     return FLAGS_TO_MEMORY_TYPE(flags) == _type;
 265   }
 266 
 267   inline void inc(size_t reserved_amt, size_t committed_amt) {
 268     _reserved_amount += reserved_amt;
 269     _committed_amount += committed_amt;
 270     _count ++;
 271   }
 272 
 273   inline size_t count() const {
 274     return _count;
 275   }
 276 
 277   inline size_t reserved_amount() const {
 278     return _reserved_amount;
 279   }
 280 
 281   inline size_t committed_amount() const {
 282     return _committed_amount;
 283   }
 284 };
 285 
 286 
 287 
 288 #define NUMBER_OF_MEMORY_TYPE    (mt_number_of_types + 1)
 289 
 290 class BaselineReporter;
 291 class BaselineComparisonReporter;
 292 
 293 /*
 294  * This class baselines current memory snapshot.
 295  * A memory baseline summarizes memory usage by memory type,
 296  * aggregates memory usage by callsites when detail tracking
 297  * is on.
 298  */
 299 class MemBaseline : public _ValueObj {
 300   friend class BaselineReporter;
 301   friend class BaselineComparisonReporter;
 302 
 303  private:
 304   // overall summaries
 305   size_t        _total_malloced;
 306   size_t        _total_vm_reserved;
 307   size_t        _total_vm_committed;
 308   size_t        _number_of_classes;
 309   size_t        _number_of_threads;
 310 
 311   // if it has properly baselined
 312   bool          _baselined;
 313 
 314   // we categorize memory into three categories within the memory type
 315   MallocMem     _malloc_data[NUMBER_OF_MEMORY_TYPE];
 316   VMMem         _vm_data[NUMBER_OF_MEMORY_TYPE];
 317   ArenaMem      _arena_data[NUMBER_OF_MEMORY_TYPE];
 318 
 319   // memory records that aggregate memory usage by callsites.
 320   // only available when detail tracking is on.
 321   MemPointerArray*  _malloc_cs;
 322   MemPointerArray*  _vm_cs;
 323   // virtual memory map
 324   MemPointerArray*  _vm_map;
 325 
 326  private:
 327   static MemType2Name  MemType2NameMap[NUMBER_OF_MEMORY_TYPE];
 328 
 329  private:
 330   // should not use copy constructor
 331   MemBaseline(MemBaseline& copy) { ShouldNotReachHere(); }
 332 
 333  public:
 334   // create a memory baseline
 335   MemBaseline();
 336 
 337   virtual ~MemBaseline();
 338 
 339   inline bool baselined() const {
 340     return _baselined;
 341   }
 342 
 343   MemBaseline& operator=(const MemBaseline& other);
 344 
 345   // reset the baseline for reuse
 346   void clear();
 347 
 348   // baseline the snapshot
 349   bool baseline(MemSnapshot& snapshot, bool summary_only = true);
 350 
 351   bool baseline(const MemPointerArray* malloc_records,
 352                 const MemPointerArray* vm_records,
 353                 bool summary_only = true);
 354 
 355   // total malloc'd memory of specified memory type
 356   inline size_t malloc_amount(MEMFLAGS flag) const {
 357     return _malloc_data[flag2index(flag)].amount();
 358   }
 359   // number of malloc'd memory blocks of specified memory type
 360   inline size_t malloc_count(MEMFLAGS flag) const {
 361     return _malloc_data[flag2index(flag)].count();
 362   }
 363   // total memory used by arenas of specified memory type
 364   inline size_t arena_amount(MEMFLAGS flag) const {
 365     return _arena_data[flag2index(flag)].amount();
 366   }
 367   // number of arenas of specified memory type
 368   inline size_t arena_count(MEMFLAGS flag) const {
 369     return _arena_data[flag2index(flag)].count();
 370   }
 371   // total reserved memory of specified memory type
 372   inline size_t reserved_amount(MEMFLAGS flag) const {
 373     return _vm_data[flag2index(flag)].reserved_amount();
 374   }
 375   // total committed memory of specified memory type
 376   inline size_t committed_amount(MEMFLAGS flag) const {
 377     return _vm_data[flag2index(flag)].committed_amount();
 378   }
 379   // total memory (malloc'd + mmap'd + arena) of specified
 380   // memory type
 381   inline size_t total_amount(MEMFLAGS flag) const {
 382     int index = flag2index(flag);
 383     return _malloc_data[index].amount() +
 384            _vm_data[index].reserved_amount() +
 385            _arena_data[index].amount();
 386   }
 387 
 388   /* overall summaries */
 389 
 390   // total malloc'd memory in snapshot
 391   inline size_t total_malloc_amount() const {
 392     return _total_malloced;
 393   }
 394   // total mmap'd memory in snapshot
 395   inline size_t total_reserved_amount() const {
 396     return _total_vm_reserved;
 397   }
 398   // total committed memory in snapshot
 399   inline size_t total_committed_amount() const {
 400     return _total_vm_committed;
 401   }
 402   // number of loaded classes
 403   inline size_t number_of_classes() const {
 404     return _number_of_classes;
 405   }
 406   // number of running threads
 407   inline size_t number_of_threads() const {
 408     return _number_of_threads;
 409   }
 410   // lookup human readable name of a memory type
 411   static const char* type2name(MEMFLAGS type);
 412 
 413  private:
 414   // convert memory flag to the index to mapping table
 415   int         flag2index(MEMFLAGS flag) const;
 416 
 417   // reset baseline values
 418   void reset();
 419 
 420   // summarize the records in global snapshot
 421   bool baseline_malloc_summary(const MemPointerArray* malloc_records);
 422   bool baseline_vm_summary(const MemPointerArray* vm_records);
 423   bool baseline_malloc_details(const MemPointerArray* malloc_records);
 424   bool baseline_vm_details(const MemPointerArray* vm_records);
 425 
 426   // print a line of malloc'd memory aggregated by callsite
 427   void print_malloc_callsite(outputStream* st, address pc, size_t size,
 428     size_t count, int diff_amt, int diff_count) const;
 429   // print a line of mmap'd memory aggregated by callsite
 430   void print_vm_callsite(outputStream* st, address pc, size_t rsz,
 431     size_t csz, int diff_rsz, int diff_csz) const;
 432 
 433   // sorting functions for raw records
 434   static int malloc_sort_by_pc(const void* p1, const void* p2);
 435   static int malloc_sort_by_addr(const void* p1, const void* p2);
 436 
 437  private:
 438   // sorting functions for baselined records
 439   static int bl_malloc_sort_by_size(const void* p1, const void* p2);
 440   static int bl_vm_sort_by_size(const void* p1, const void* p2);
 441   static int bl_malloc_sort_by_pc(const void* p1, const void* p2);
 442   static int bl_vm_sort_by_pc(const void* p1, const void* p2);
 443 };
 444 
 445 
 446 #endif // SHARE_VM_SERVICES_MEM_BASELINE_HPP