hotspot/src/share/vm/services/memReporter.hpp
changeset 25946 1572c9f03fb9
parent 22234 da823d78ad65
child 27162 0a4a7276949b
equal deleted inserted replaced
25902:7e9ffb1fe1df 25946:1572c9f03fb9
     1 /*
     1 /*
     2  * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
     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.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4  *
     4  *
     5  * This code is free software; you can redistribute it and/or modify it
     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
     6  * under the terms of the GNU General Public License version 2 only, as
     7  * published by the Free Software Foundation.
     7  * published by the Free Software Foundation.
    23  */
    23  */
    24 
    24 
    25 #ifndef SHARE_VM_SERVICES_MEM_REPORTER_HPP
    25 #ifndef SHARE_VM_SERVICES_MEM_REPORTER_HPP
    26 #define SHARE_VM_SERVICES_MEM_REPORTER_HPP
    26 #define SHARE_VM_SERVICES_MEM_REPORTER_HPP
    27 
    27 
    28 #include "runtime/mutexLocker.hpp"
    28 #if INCLUDE_NMT
       
    29 
       
    30 #include "oops/instanceKlass.hpp"
    29 #include "services/memBaseline.hpp"
    31 #include "services/memBaseline.hpp"
    30 #include "services/memTracker.hpp"
    32 #include "services/nmtCommon.hpp"
    31 #include "utilities/ostream.hpp"
    33 #include "services/mallocTracker.hpp"
    32 #include "utilities/macros.hpp"
    34 #include "services/virtualMemoryTracker.hpp"
    33 
    35 
    34 #if INCLUDE_NMT
    36 /*
    35 
    37  * Base class that provides helpers
    36 /*
    38 */
    37  * MemBaselineReporter reports data to this outputer class,
    39 class MemReporterBase : public StackObj {
    38  * ReportOutputer is responsible for format, store and redirect
    40  private:
    39  * the data to the final destination.
    41   size_t        _scale;  // report in this scale
    40  */
    42   outputStream* _output; // destination
    41 class BaselineOutputer : public StackObj {
    43 
    42  public:
    44  public:
    43   // start to report memory usage in specified scale.
    45   MemReporterBase(outputStream* out = NULL, size_t scale = K)
    44   // if report_diff = true, the reporter reports baseline comparison
    46     : _scale(scale) {
    45   // information.
    47     _output = (out == NULL) ? tty : out;
    46 
    48   }
    47   virtual void start(size_t scale, bool report_diff = false) = 0;
    49 
    48   // Done reporting
    50  protected:
    49   virtual void done() = 0;
    51   inline outputStream* output() const {
    50 
    52     return _output;
    51   /* report baseline summary information */
    53   }
    52   virtual void total_usage(size_t total_reserved,
    54   // Current reporting scale
    53                            size_t total_committed) = 0;
    55   inline const char* current_scale() const {
    54   virtual void num_of_classes(size_t classes) = 0;
    56     return NMTUtil::scale_name(_scale);
    55   virtual void num_of_threads(size_t threads) = 0;
    57   }
    56 
    58   // Convert memory amount in bytes to current reporting scale
    57   virtual void thread_info(size_t stack_reserved_amt, size_t stack_committed_amt) = 0;
    59   inline size_t amount_in_current_scale(size_t amount) const {
    58 
    60     return NMTUtil::amount_in_scale(amount, _scale);
    59   /* report baseline summary comparison */
    61   }
    60   virtual void diff_total_usage(size_t total_reserved,
    62 
    61                                 size_t total_committed,
    63   // Convert diff amount in bytes to current reporting scale
    62                                 int reserved_diff,
    64   inline long diff_in_current_scale(size_t s1, size_t s2) const {
    63                                 int committed_diff) = 0;
    65     long amount = (long)(s1 - s2);
    64   virtual void diff_num_of_classes(size_t classes, int diff) = 0;
    66     long scale = (long)_scale;
    65   virtual void diff_num_of_threads(size_t threads, int diff) = 0;
    67     amount = (amount > 0) ? (amount + scale / 2) : (amount - scale / 2);
    66 
    68     return amount / scale;
    67   virtual void diff_thread_info(size_t stack_reserved, size_t stack_committed,
    69   }
    68         int stack_reserved_diff, int stack_committed_diff) = 0;
    70 
    69 
    71   // Helper functions
    70 
    72   // Calculate total reserved and committed amount
    71   /*
    73   size_t reserved_total(const MallocMemory* malloc, const VirtualMemory* vm) const;
    72    * memory summary by memory types.
    74   size_t committed_total(const MallocMemory* malloc, const VirtualMemory* vm) const;
    73    * for each memory type, following summaries are reported:
    75 
    74    *  - reserved amount, committed amount
    76 
    75    *  - malloc'd amount, malloc count
    77   // Print summary total, malloc and virtual memory
    76    *  - arena amount, arena count
    78   void print_total(size_t reserved, size_t committed) const;
    77    */
    79   void print_malloc(size_t amount, size_t count) const;
    78 
    80   void print_virtual_memory(size_t reserved, size_t committed) const;
    79   // start reporting memory summary by memory type
    81 
    80   virtual void start_category_summary() = 0;
    82   void print_malloc_line(size_t amount, size_t count) const;
    81 
    83   void print_virtual_memory_line(size_t reserved, size_t committed) const;
    82   virtual void category_summary(MEMFLAGS type, size_t reserved_amt,
    84   void print_arena_line(size_t amount, size_t count) const;
    83                                 size_t committed_amt,
    85 
    84                                 size_t malloc_amt, size_t malloc_count,
    86   void print_virtual_memory_region(const char* type, address base, size_t size) const;
    85                                 size_t arena_amt, size_t arena_count) = 0;
    87 };
    86 
    88 
    87   virtual void diff_category_summary(MEMFLAGS type, size_t cur_reserved_amt,
    89 /*
    88                                 size_t cur_committed_amt,
    90  * The class is for generating summary tracking report.
    89                                 size_t cur_malloc_amt, size_t cur_malloc_count,
    91  */
    90                                 size_t cur_arena_amt, size_t cur_arena_count,
    92 class MemSummaryReporter : public MemReporterBase {
    91                                 int reserved_diff, int committed_diff, int malloc_diff,
    93  private:
    92                                 int malloc_count_diff, int arena_diff,
    94   MallocMemorySnapshot*   _malloc_snapshot;
    93                                 int arena_count_diff) = 0;
    95   VirtualMemorySnapshot*  _vm_snapshot;
    94 
    96   size_t                  _class_count;
    95   virtual void done_category_summary() = 0;
    97 
    96 
    98  public:
    97   virtual void start_virtual_memory_map() = 0;
    99   // Report summary tracking data from global snapshots directly.
    98   virtual void reserved_memory_region(MEMFLAGS type, address base, address end, size_t size, address pc) = 0;
   100   // This constructor is used for final reporting and hs_err reporting.
    99   virtual void committed_memory_region(address base, address end, size_t size, address pc) = 0;
   101   MemSummaryReporter(MallocMemorySnapshot* malloc_snapshot,
   100   virtual void done_virtual_memory_map() = 0;
   102     VirtualMemorySnapshot* vm_snapshot, outputStream* output,
   101 
   103     size_t class_count = 0, size_t scale = K) :
   102   /*
   104     MemReporterBase(output, scale),
   103    *  Report callsite information
   105     _malloc_snapshot(malloc_snapshot),
   104    */
   106     _vm_snapshot(vm_snapshot) {
   105   virtual void start_callsite() = 0;
   107     if (class_count == 0) {
   106   virtual void malloc_callsite(address pc, size_t malloc_amt, size_t malloc_count) = 0;
   108       _class_count = InstanceKlass::number_of_instance_classes();
   107   virtual void virtual_memory_callsite(address pc, size_t reserved_amt, size_t committed_amt) = 0;
   109     } else {
   108 
   110       _class_count = class_count;
   109   virtual void diff_malloc_callsite(address pc, size_t cur_malloc_amt, size_t cur_malloc_count,
   111     }
   110               int malloc_diff, int malloc_count_diff) = 0;
   112   }
   111   virtual void diff_virtual_memory_callsite(address pc, size_t cur_reserved_amt, size_t cur_committed_amt,
   113   // This constructor is for normal reporting from a recent baseline.
   112               int reserved_diff, int committed_diff) = 0;
   114   MemSummaryReporter(MemBaseline& baseline, outputStream* output,
   113 
   115     size_t scale = K) : MemReporterBase(output, scale),
   114   virtual void done_callsite() = 0;
   116     _malloc_snapshot(baseline.malloc_memory_snapshot()),
   115 
   117     _vm_snapshot(baseline.virtual_memory_snapshot()),
   116   // return current scale in "KB", "MB" or "GB"
   118     _class_count(baseline.class_count()) { }
   117   static const char* memory_unit(size_t scale);
   119 
   118 };
   120 
   119 
   121   // Generate summary report
   120 /*
   122   virtual void report();
   121  * This class reports processed data from a baseline or
   123  private:
   122  * the changes between the two baseline.
   124   // Report summary for each memory type
   123  */
   125   void report_summary_of_type(MEMFLAGS type, MallocMemory* malloc_memory,
   124 class BaselineReporter : public StackObj {
   126     VirtualMemory* virtual_memory);
   125  private:
   127 };
   126   BaselineOutputer&  _outputer;
   128 
   127   size_t             _scale;
   129 /*
   128 
   130  * The class is for generating detail tracking report.
   129  public:
   131  */
   130   // construct a reporter that reports memory usage
   132 class MemDetailReporter : public MemSummaryReporter {
   131   // in specified scale
   133  private:
   132   BaselineReporter(BaselineOutputer& outputer, size_t scale = K):
   134   MemBaseline&   _baseline;
   133     _outputer(outputer) {
   135 
   134     _scale = scale;
   136  public:
   135   }
   137   MemDetailReporter(MemBaseline& baseline, outputStream* output, size_t scale = K) :
   136   virtual void report_baseline(const MemBaseline& baseline, bool summary_only = false);
   138     MemSummaryReporter(baseline, output, scale),
   137   virtual void diff_baselines(const MemBaseline& cur, const MemBaseline& prev,
   139      _baseline(baseline) { }
   138                               bool summary_only = false);
   140 
   139 
   141   // Generate detail report.
   140   void set_scale(size_t scale);
   142   // The report contains summary and detail sections.
   141   size_t scale() const { return _scale; }
   143   virtual void report() {
   142 
   144     MemSummaryReporter::report();
   143  private:
   145     report_virtual_memory_map();
   144   void report_summaries(const MemBaseline& baseline);
   146     report_detail();
   145   void report_virtual_memory_map(const MemBaseline& baseline);
   147   }
   146   void report_callsites(const MemBaseline& baseline);
   148 
   147 
   149  private:
   148   void diff_summaries(const MemBaseline& cur, const MemBaseline& prev);
   150   // Report detail tracking data.
   149   void diff_callsites(const MemBaseline& cur, const MemBaseline& prev);
   151   void report_detail();
   150 
   152   // Report virtual memory map
   151   // calculate memory size in current memory scale
   153   void report_virtual_memory_map();
   152   size_t amount_in_current_scale(size_t amt) const;
   154   // Report malloc allocation sites
   153   // diff two unsigned values in current memory scale
   155   void report_malloc_sites();
   154   int    diff_in_current_scale(size_t value1, size_t value2) const;
   156   // Report virtual memory reservation sites
   155   // diff two unsigned value
   157   void report_virtual_memory_allocation_sites();
   156   int    diff(size_t value1, size_t value2) const;
   158 
   157 };
   159   // Report a virtual memory region
   158 
   160   void report_virtual_memory_region(const ReservedMemoryRegion* rgn);
   159 /*
   161 };
   160  * tty output implementation. Native memory tracking
   162 
   161  * DCmd uses this outputer.
   163 /*
   162  */
   164  * The class is for generating summary comparison report.
   163 class BaselineTTYOutputer : public BaselineOutputer {
   165  * It compares current memory baseline against an early baseline.
   164  private:
   166  */
   165   size_t         _scale;
   167 class MemSummaryDiffReporter : public MemReporterBase {
   166 
   168  protected:
   167   size_t         _num_of_classes;
   169   MemBaseline&      _early_baseline;
   168   size_t         _num_of_threads;
   170   MemBaseline&      _current_baseline;
   169   size_t         _thread_stack_reserved;
   171 
   170   size_t         _thread_stack_committed;
   172  public:
   171 
   173   MemSummaryDiffReporter(MemBaseline& early_baseline, MemBaseline& current_baseline,
   172   int            _num_of_classes_diff;
   174     outputStream* output, size_t scale = K) : MemReporterBase(output, scale),
   173   int            _num_of_threads_diff;
   175     _early_baseline(early_baseline), _current_baseline(current_baseline) {
   174   int            _thread_stack_reserved_diff;
   176     assert(early_baseline.baseline_type()   != MemBaseline::Not_baselined, "Not baselined");
   175   int            _thread_stack_committed_diff;
   177     assert(current_baseline.baseline_type() != MemBaseline::Not_baselined, "Not baselined");
   176 
   178   }
   177   outputStream*  _output;
   179 
   178 
   180   // Generate summary comparison report
   179  public:
   181   virtual void report_diff();
   180   BaselineTTYOutputer(outputStream* st) {
   182 
   181     _scale = K;
   183  private:
   182     _num_of_classes = 0;
   184   // report the comparison of each memory type
   183     _num_of_threads = 0;
   185   void diff_summary_of_type(MEMFLAGS type,
   184     _thread_stack_reserved = 0;
   186     const MallocMemory* early_malloc, const VirtualMemory* early_vm,
   185     _thread_stack_committed = 0;
   187     const MallocMemory* current_malloc, const VirtualMemory* current_vm) const;
   186     _num_of_classes_diff = 0;
   188 
   187     _num_of_threads_diff = 0;
   189  protected:
   188     _thread_stack_reserved_diff = 0;
   190   void print_malloc_diff(size_t current_amount, size_t current_count,
   189     _thread_stack_committed_diff = 0;
   191     size_t early_amount, size_t early_count) const;
   190     _output = st;
   192   void print_virtual_memory_diff(size_t current_reserved, size_t current_committed,
   191   }
   193     size_t early_reserved, size_t early_committed) const;
   192 
   194   void print_arena_diff(size_t current_amount, size_t current_count,
   193   // begin reporting memory usage in specified scale
   195     size_t early_amount, size_t early_count) const;
   194   void start(size_t scale, bool report_diff = false);
   196 };
   195   // done reporting
   197 
   196   void done();
   198 /*
   197 
   199  * The class is for generating detail comparison report.
   198   // total memory usage
   200  * It compares current memory baseline against an early baseline,
   199   void total_usage(size_t total_reserved,
   201  * both baselines have to be detail baseline.
   200                    size_t total_committed);
   202  */
   201   // report total loaded classes
   203 class MemDetailDiffReporter : public MemSummaryDiffReporter {
   202   void num_of_classes(size_t classes) {
   204  public:
   203     _num_of_classes = classes;
   205   MemDetailDiffReporter(MemBaseline& early_baseline, MemBaseline& current_baseline,
   204   }
   206     outputStream* output, size_t scale = K) :
   205 
   207     MemSummaryDiffReporter(early_baseline, current_baseline, output, scale) { }
   206   void num_of_threads(size_t threads) {
   208 
   207     _num_of_threads = threads;
   209   // Generate detail comparison report
   208   }
   210   virtual void report_diff();
   209 
   211 
   210   void thread_info(size_t stack_reserved_amt, size_t stack_committed_amt) {
   212   // Malloc allocation site comparison
   211     _thread_stack_reserved = stack_reserved_amt;
   213   void diff_malloc_sites() const;
   212     _thread_stack_committed = stack_committed_amt;
   214   // Virutal memory reservation site comparison
   213   }
   215   void diff_virtual_memory_sites() const;
   214 
   216 
   215   void diff_total_usage(size_t total_reserved,
   217   // New malloc allocation site in recent baseline
   216                         size_t total_committed,
   218   void new_malloc_site (const MallocSite* site) const;
   217                         int reserved_diff,
   219   // The malloc allocation site is not in recent baseline
   218                         int committed_diff);
   220   void old_malloc_site (const MallocSite* site) const;
   219 
   221   // Compare malloc allocation site, it is in both baselines
   220   void diff_num_of_classes(size_t classes, int diff) {
   222   void diff_malloc_site(const MallocSite* early, const MallocSite* current)  const;
   221     _num_of_classes = classes;
   223 
   222     _num_of_classes_diff = diff;
   224   // New virtual memory allocation site in recent baseline
   223   }
   225   void new_virtual_memory_site (const VirtualMemoryAllocationSite* callsite) const;
   224 
   226   // The virtual memory allocation site is not in recent baseline
   225   void diff_num_of_threads(size_t threads, int diff) {
   227   void old_virtual_memory_site (const VirtualMemoryAllocationSite* callsite) const;
   226     _num_of_threads = threads;
   228   // Compare virtual memory allocation site, it is in both baseline
   227     _num_of_threads_diff = diff;
   229   void diff_virtual_memory_site(const VirtualMemoryAllocationSite* early,
   228   }
   230                                 const VirtualMemoryAllocationSite* current)  const;
   229 
   231 
   230   void diff_thread_info(size_t stack_reserved_amt, size_t stack_committed_amt,
   232   void diff_malloc_site(const NativeCallStack* stack, size_t current_size,
   231                int stack_reserved_diff, int stack_committed_diff) {
   233     size_t currrent_count, size_t early_size, size_t early_count) const;
   232     _thread_stack_reserved = stack_reserved_amt;
   234   void diff_virtual_memory_site(const NativeCallStack* stack, size_t current_reserved,
   233     _thread_stack_committed = stack_committed_amt;
   235     size_t current_committed, size_t early_reserved, size_t early_committed) const;
   234     _thread_stack_reserved_diff = stack_reserved_diff;
   236 };
   235     _thread_stack_committed_diff = stack_committed_diff;
       
   236   }
       
   237 
       
   238   /*
       
   239    * Report memory summary categoriuzed by memory types.
       
   240    * For each memory type, following summaries are reported:
       
   241    *  - reserved amount, committed amount
       
   242    *  - malloc-ed amount, malloc count
       
   243    *  - arena amount, arena count
       
   244    */
       
   245   // start reporting memory summary by memory type
       
   246   void start_category_summary();
       
   247   void category_summary(MEMFLAGS type, size_t reserved_amt, size_t committed_amt,
       
   248                                size_t malloc_amt, size_t malloc_count,
       
   249                                size_t arena_amt, size_t arena_count);
       
   250 
       
   251   void diff_category_summary(MEMFLAGS type, size_t cur_reserved_amt,
       
   252                           size_t cur_committed_amt,
       
   253                           size_t cur_malloc_amt, size_t cur_malloc_count,
       
   254                           size_t cur_arena_amt, size_t cur_arena_count,
       
   255                           int reserved_diff, int committed_diff, int malloc_diff,
       
   256                           int malloc_count_diff, int arena_diff,
       
   257                           int arena_count_diff);
       
   258 
       
   259   void done_category_summary();
       
   260 
       
   261   // virtual memory map
       
   262   void start_virtual_memory_map();
       
   263   void reserved_memory_region(MEMFLAGS type, address base, address end, size_t size, address pc);
       
   264   void committed_memory_region(address base, address end, size_t size, address pc);
       
   265   void done_virtual_memory_map();
       
   266 
       
   267 
       
   268   /*
       
   269    *  Report callsite information
       
   270    */
       
   271   void start_callsite();
       
   272   void malloc_callsite(address pc, size_t malloc_amt, size_t malloc_count);
       
   273   void virtual_memory_callsite(address pc, size_t reserved_amt, size_t committed_amt);
       
   274 
       
   275   void diff_malloc_callsite(address pc, size_t cur_malloc_amt, size_t cur_malloc_count,
       
   276               int malloc_diff, int malloc_count_diff);
       
   277   void diff_virtual_memory_callsite(address pc, size_t cur_reserved_amt, size_t cur_committed_amt,
       
   278               int reserved_diff, int committed_diff);
       
   279 
       
   280   void done_callsite();
       
   281 };
       
   282 
       
   283 
   237 
   284 #endif // INCLUDE_NMT
   238 #endif // INCLUDE_NMT
   285 
   239 
   286 #endif // SHARE_VM_SERVICES_MEM_REPORTER_HPP
   240 #endif
       
   241