src/share/vm/gc_implementation/g1/g1RemSetSummary.cpp

Fri, 10 Oct 2014 15:51:58 +0200

author
tschatzl
date
Fri, 10 Oct 2014 15:51:58 +0200
changeset 7257
e7d0505c8a30
parent 7208
7baf47cb97cb
child 7535
7ae4e26cb1e0
child 8439
b857e4abb00c
permissions
-rw-r--r--

8059758: Footprint regressions with JDK-8038423
Summary: Changes in JDK-8038423 always initialize (zero out) virtual memory used for auxiliary data structures. This causes a footprint regression for G1 in startup benchmarks. This is because they do not touch that memory at all, so the operating system does not actually commit these pages. The fix is to, if the initialization value of the data structures matches the default value of just committed memory (=0), do not do anything.
Reviewed-by: jwilhelm, brutisso

     1 /*
     2  * Copyright (c) 2013, 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  */
    25 #include "precompiled.hpp"
    26 #include "gc_implementation/g1/concurrentG1Refine.hpp"
    27 #include "gc_implementation/g1/concurrentG1RefineThread.hpp"
    28 #include "gc_implementation/g1/heapRegion.hpp"
    29 #include "gc_implementation/g1/g1CollectedHeap.inline.hpp"
    30 #include "gc_implementation/g1/g1RemSet.inline.hpp"
    31 #include "gc_implementation/g1/g1RemSetSummary.hpp"
    32 #include "gc_implementation/g1/heapRegionRemSet.hpp"
    33 #include "runtime/thread.inline.hpp"
    35 class GetRSThreadVTimeClosure : public ThreadClosure {
    36 private:
    37   G1RemSetSummary* _summary;
    38   uint _counter;
    40 public:
    41   GetRSThreadVTimeClosure(G1RemSetSummary * summary) : ThreadClosure(), _summary(summary), _counter(0) {
    42     assert(_summary != NULL, "just checking");
    43   }
    45   virtual void do_thread(Thread* t) {
    46     ConcurrentG1RefineThread* crt = (ConcurrentG1RefineThread*) t;
    47     _summary->set_rs_thread_vtime(_counter, crt->vtime_accum());
    48     _counter++;
    49   }
    50 };
    52 void G1RemSetSummary::update() {
    53   _num_refined_cards = remset()->conc_refine_cards();
    54   DirtyCardQueueSet& dcqs = JavaThread::dirty_card_queue_set();
    55   _num_processed_buf_mutator = dcqs.processed_buffers_mut();
    56   _num_processed_buf_rs_threads = dcqs.processed_buffers_rs_thread();
    58   _num_coarsenings = HeapRegionRemSet::n_coarsenings();
    60   ConcurrentG1Refine * cg1r = G1CollectedHeap::heap()->concurrent_g1_refine();
    61   if (_rs_threads_vtimes != NULL) {
    62     GetRSThreadVTimeClosure p(this);
    63     cg1r->worker_threads_do(&p);
    64   }
    65   set_sampling_thread_vtime(cg1r->sampling_thread()->vtime_accum());
    66 }
    68 void G1RemSetSummary::set_rs_thread_vtime(uint thread, double value) {
    69   assert(_rs_threads_vtimes != NULL, "just checking");
    70   assert(thread < _num_vtimes, "just checking");
    71   _rs_threads_vtimes[thread] = value;
    72 }
    74 double G1RemSetSummary::rs_thread_vtime(uint thread) const {
    75   assert(_rs_threads_vtimes != NULL, "just checking");
    76   assert(thread < _num_vtimes, "just checking");
    77   return _rs_threads_vtimes[thread];
    78 }
    80 void G1RemSetSummary::initialize(G1RemSet* remset) {
    81   assert(_rs_threads_vtimes == NULL, "just checking");
    82   assert(remset != NULL, "just checking");
    84   _remset = remset;
    85   _num_vtimes = ConcurrentG1Refine::thread_num();
    86   _rs_threads_vtimes = NEW_C_HEAP_ARRAY(double, _num_vtimes, mtGC);
    87   memset(_rs_threads_vtimes, 0, sizeof(double) * _num_vtimes);
    89   update();
    90 }
    92 void G1RemSetSummary::set(G1RemSetSummary* other) {
    93   assert(other != NULL, "just checking");
    94   assert(remset() == other->remset(), "just checking");
    95   assert(_num_vtimes == other->_num_vtimes, "just checking");
    97   _num_refined_cards = other->num_concurrent_refined_cards();
    99   _num_processed_buf_mutator = other->num_processed_buf_mutator();
   100   _num_processed_buf_rs_threads = other->num_processed_buf_rs_threads();
   102   _num_coarsenings = other->_num_coarsenings;
   104   memcpy(_rs_threads_vtimes, other->_rs_threads_vtimes, sizeof(double) * _num_vtimes);
   106   set_sampling_thread_vtime(other->sampling_thread_vtime());
   107 }
   109 void G1RemSetSummary::subtract_from(G1RemSetSummary* other) {
   110   assert(other != NULL, "just checking");
   111   assert(remset() == other->remset(), "just checking");
   112   assert(_num_vtimes == other->_num_vtimes, "just checking");
   114   _num_refined_cards = other->num_concurrent_refined_cards() - _num_refined_cards;
   116   _num_processed_buf_mutator = other->num_processed_buf_mutator() - _num_processed_buf_mutator;
   117   _num_processed_buf_rs_threads = other->num_processed_buf_rs_threads() - _num_processed_buf_rs_threads;
   119   _num_coarsenings = other->num_coarsenings() - _num_coarsenings;
   121   for (uint i = 0; i < _num_vtimes; i++) {
   122     set_rs_thread_vtime(i, other->rs_thread_vtime(i) - rs_thread_vtime(i));
   123   }
   125   _sampling_thread_vtime = other->sampling_thread_vtime() - _sampling_thread_vtime;
   126 }
   128 static double percent_of(size_t numerator, size_t denominator) {
   129   if (denominator != 0) {
   130     return (double)numerator / denominator * 100.0f;
   131   } else {
   132     return 0.0f;
   133   }
   134 }
   136 static size_t round_to_K(size_t value) {
   137   return value / K;
   138 }
   140 class RegionTypeCounter VALUE_OBJ_CLASS_SPEC {
   141 private:
   142   const char* _name;
   144   size_t _rs_mem_size;
   145   size_t _cards_occupied;
   146   size_t _amount;
   148   size_t _code_root_mem_size;
   149   size_t _code_root_elems;
   151   double rs_mem_size_percent_of(size_t total) {
   152     return percent_of(_rs_mem_size, total);
   153   }
   155   double cards_occupied_percent_of(size_t total) {
   156     return percent_of(_cards_occupied, total);
   157   }
   159   double code_root_mem_size_percent_of(size_t total) {
   160     return percent_of(_code_root_mem_size, total);
   161   }
   163   double code_root_elems_percent_of(size_t total) {
   164     return percent_of(_code_root_elems, total);
   165   }
   167   size_t amount() const { return _amount; }
   169 public:
   171   RegionTypeCounter(const char* name) : _name(name), _rs_mem_size(0), _cards_occupied(0),
   172     _amount(0), _code_root_mem_size(0), _code_root_elems(0) { }
   174   void add(size_t rs_mem_size, size_t cards_occupied, size_t code_root_mem_size,
   175     size_t code_root_elems) {
   176     _rs_mem_size += rs_mem_size;
   177     _cards_occupied += cards_occupied;
   178     _code_root_mem_size += code_root_mem_size;
   179     _code_root_elems += code_root_elems;
   180     _amount++;
   181   }
   183   size_t rs_mem_size() const { return _rs_mem_size; }
   184   size_t cards_occupied() const { return _cards_occupied; }
   186   size_t code_root_mem_size() const { return _code_root_mem_size; }
   187   size_t code_root_elems() const { return _code_root_elems; }
   189   void print_rs_mem_info_on(outputStream * out, size_t total) {
   190     out->print_cr("    "SIZE_FORMAT_W(8)"K (%5.1f%%) by "SIZE_FORMAT" %s regions",
   191         round_to_K(rs_mem_size()), rs_mem_size_percent_of(total), amount(), _name);
   192   }
   194   void print_cards_occupied_info_on(outputStream * out, size_t total) {
   195     out->print_cr("     "SIZE_FORMAT_W(8)" (%5.1f%%) entries by "SIZE_FORMAT" %s regions",
   196         cards_occupied(), cards_occupied_percent_of(total), amount(), _name);
   197   }
   199   void print_code_root_mem_info_on(outputStream * out, size_t total) {
   200     out->print_cr("    "SIZE_FORMAT_W(8)"K (%5.1f%%) by "SIZE_FORMAT" %s regions",
   201         round_to_K(code_root_mem_size()), code_root_mem_size_percent_of(total), amount(), _name);
   202   }
   204   void print_code_root_elems_info_on(outputStream * out, size_t total) {
   205     out->print_cr("     "SIZE_FORMAT_W(8)" (%5.1f%%) elements by "SIZE_FORMAT" %s regions",
   206         code_root_elems(), code_root_elems_percent_of(total), amount(), _name);
   207   }
   208 };
   211 class HRRSStatsIter: public HeapRegionClosure {
   212 private:
   213   RegionTypeCounter _young;
   214   RegionTypeCounter _humonguous;
   215   RegionTypeCounter _free;
   216   RegionTypeCounter _old;
   217   RegionTypeCounter _all;
   219   size_t _max_rs_mem_sz;
   220   HeapRegion* _max_rs_mem_sz_region;
   222   size_t total_rs_mem_sz() const            { return _all.rs_mem_size(); }
   223   size_t total_cards_occupied() const       { return _all.cards_occupied(); }
   225   size_t max_rs_mem_sz() const              { return _max_rs_mem_sz; }
   226   HeapRegion* max_rs_mem_sz_region() const  { return _max_rs_mem_sz_region; }
   228   size_t _max_code_root_mem_sz;
   229   HeapRegion* _max_code_root_mem_sz_region;
   231   size_t total_code_root_mem_sz() const     { return _all.code_root_mem_size(); }
   232   size_t total_code_root_elems() const      { return _all.code_root_elems(); }
   234   size_t max_code_root_mem_sz() const       { return _max_code_root_mem_sz; }
   235   HeapRegion* max_code_root_mem_sz_region() const { return _max_code_root_mem_sz_region; }
   237 public:
   238   HRRSStatsIter() : _all("All"), _young("Young"), _humonguous("Humonguous"),
   239     _free("Free"), _old("Old"), _max_code_root_mem_sz_region(NULL), _max_rs_mem_sz_region(NULL),
   240     _max_rs_mem_sz(0), _max_code_root_mem_sz(0)
   241   {}
   243   bool doHeapRegion(HeapRegion* r) {
   244     HeapRegionRemSet* hrrs = r->rem_set();
   246     // HeapRegionRemSet::mem_size() includes the
   247     // size of the strong code roots
   248     size_t rs_mem_sz = hrrs->mem_size();
   249     if (rs_mem_sz > _max_rs_mem_sz) {
   250       _max_rs_mem_sz = rs_mem_sz;
   251       _max_rs_mem_sz_region = r;
   252     }
   253     size_t occupied_cards = hrrs->occupied();
   254     size_t code_root_mem_sz = hrrs->strong_code_roots_mem_size();
   255     if (code_root_mem_sz > max_code_root_mem_sz()) {
   256       _max_code_root_mem_sz = code_root_mem_sz;
   257       _max_code_root_mem_sz_region = r;
   258     }
   259     size_t code_root_elems = hrrs->strong_code_roots_list_length();
   261     RegionTypeCounter* current = NULL;
   262     if (r->is_free()) {
   263       current = &_free;
   264     } else if (r->is_young()) {
   265       current = &_young;
   266     } else if (r->isHumongous()) {
   267       current = &_humonguous;
   268     } else if (r->is_old()) {
   269       current = &_old;
   270     } else {
   271       ShouldNotReachHere();
   272     }
   273     current->add(rs_mem_sz, occupied_cards, code_root_mem_sz, code_root_elems);
   274     _all.add(rs_mem_sz, occupied_cards, code_root_mem_sz, code_root_elems);
   276     return false;
   277   }
   279   void print_summary_on(outputStream* out) {
   280     RegionTypeCounter* counters[] = { &_young, &_humonguous, &_free, &_old, NULL };
   282     out->print_cr("\n Current rem set statistics");
   283     out->print_cr("  Total per region rem sets sizes = "SIZE_FORMAT"K."
   284                   " Max = "SIZE_FORMAT"K.",
   285                   round_to_K(total_rs_mem_sz()), round_to_K(max_rs_mem_sz()));
   286     for (RegionTypeCounter** current = &counters[0]; *current != NULL; current++) {
   287       (*current)->print_rs_mem_info_on(out, total_rs_mem_sz());
   288     }
   290     out->print_cr("   Static structures = "SIZE_FORMAT"K,"
   291                   " free_lists = "SIZE_FORMAT"K.",
   292                   round_to_K(HeapRegionRemSet::static_mem_size()),
   293                   round_to_K(HeapRegionRemSet::fl_mem_size()));
   295     out->print_cr("    "SIZE_FORMAT" occupied cards represented.",
   296                   total_cards_occupied());
   297     for (RegionTypeCounter** current = &counters[0]; *current != NULL; current++) {
   298       (*current)->print_cards_occupied_info_on(out, total_cards_occupied());
   299     }
   301     // Largest sized rem set region statistics
   302     HeapRegionRemSet* rem_set = max_rs_mem_sz_region()->rem_set();
   303     out->print_cr("    Region with largest rem set = "HR_FORMAT", "
   304                   "size = "SIZE_FORMAT "K, occupied = "SIZE_FORMAT"K.",
   305                   HR_FORMAT_PARAMS(max_rs_mem_sz_region()),
   306                   round_to_K(rem_set->mem_size()),
   307                   round_to_K(rem_set->occupied()));
   309     // Strong code root statistics
   310     HeapRegionRemSet* max_code_root_rem_set = max_code_root_mem_sz_region()->rem_set();
   311     out->print_cr("  Total heap region code root sets sizes = "SIZE_FORMAT"K."
   312                   "  Max = "SIZE_FORMAT"K.",
   313                   round_to_K(total_code_root_mem_sz()),
   314                   round_to_K(max_code_root_rem_set->strong_code_roots_mem_size()));
   315     for (RegionTypeCounter** current = &counters[0]; *current != NULL; current++) {
   316       (*current)->print_code_root_mem_info_on(out, total_code_root_mem_sz());
   317     }
   319     out->print_cr("    "SIZE_FORMAT" code roots represented.",
   320                   total_code_root_elems());
   321     for (RegionTypeCounter** current = &counters[0]; *current != NULL; current++) {
   322       (*current)->print_code_root_elems_info_on(out, total_code_root_elems());
   323     }
   325     out->print_cr("    Region with largest amount of code roots = "HR_FORMAT", "
   326                   "size = "SIZE_FORMAT "K, num_elems = "SIZE_FORMAT".",
   327                   HR_FORMAT_PARAMS(max_code_root_mem_sz_region()),
   328                   round_to_K(max_code_root_rem_set->strong_code_roots_mem_size()),
   329                   round_to_K(max_code_root_rem_set->strong_code_roots_list_length()));
   330   }
   331 };
   333 void G1RemSetSummary::print_on(outputStream* out) {
   334   out->print_cr("\n Recent concurrent refinement statistics");
   335   out->print_cr("  Processed "SIZE_FORMAT" cards",
   336                 num_concurrent_refined_cards());
   337   out->print_cr("  Of "SIZE_FORMAT" completed buffers:", num_processed_buf_total());
   338   out->print_cr("     "SIZE_FORMAT_W(8)" (%5.1f%%) by concurrent RS threads.",
   339                 num_processed_buf_total(),
   340                 percent_of(num_processed_buf_rs_threads(), num_processed_buf_total()));
   341   out->print_cr("     "SIZE_FORMAT_W(8)" (%5.1f%%) by mutator threads.",
   342                 num_processed_buf_mutator(),
   343                 percent_of(num_processed_buf_mutator(), num_processed_buf_total()));
   344   out->print_cr("  Did "SIZE_FORMAT" coarsenings.", num_coarsenings());
   345   out->print_cr("  Concurrent RS threads times (s)");
   346   out->print("     ");
   347   for (uint i = 0; i < _num_vtimes; i++) {
   348     out->print("    %5.2f", rs_thread_vtime(i));
   349   }
   350   out->cr();
   351   out->print_cr("  Concurrent sampling threads times (s)");
   352   out->print_cr("         %5.2f", sampling_thread_vtime());
   354   HRRSStatsIter blk;
   355   G1CollectedHeap::heap()->heap_region_iterate(&blk);
   356   blk.print_summary_on(out);
   357 }

mercurial