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

Fri, 29 Aug 2014 13:12:21 +0200

author
mgerdin
date
Fri, 29 Aug 2014 13:12:21 +0200
changeset 7208
7baf47cb97cb
parent 7195
c02ec279b062
child 7535
7ae4e26cb1e0
child 8439
b857e4abb00c
permissions
-rw-r--r--

8048268: G1 Code Root Migration performs poorly
Summary: Replace G1CodeRootSet with a Hashtable based implementation, merge Code Root Migration phase into Code Root Scanning
Reviewed-by: jmasa, brutisso, tschatzl

tschatzl@5204 1 /*
tschatzl@5204 2 * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
tschatzl@5204 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
tschatzl@5204 4 *
tschatzl@5204 5 * This code is free software; you can redistribute it and/or modify it
tschatzl@5204 6 * under the terms of the GNU General Public License version 2 only, as
tschatzl@5204 7 * published by the Free Software Foundation.
tschatzl@5204 8 *
tschatzl@5204 9 * This code is distributed in the hope that it will be useful, but WITHOUT
tschatzl@5204 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
tschatzl@5204 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
tschatzl@5204 12 * version 2 for more details (a copy is included in the LICENSE file that
tschatzl@5204 13 * accompanied this code).
tschatzl@5204 14 *
tschatzl@5204 15 * You should have received a copy of the GNU General Public License version
tschatzl@5204 16 * 2 along with this work; if not, write to the Free Software Foundation,
tschatzl@5204 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
tschatzl@5204 18 *
tschatzl@5204 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
tschatzl@5204 20 * or visit www.oracle.com if you need additional information or have any
tschatzl@5204 21 * questions.
tschatzl@5204 22 *
tschatzl@5204 23 */
tschatzl@5204 24
tschatzl@5204 25 #include "precompiled.hpp"
tschatzl@5204 26 #include "gc_implementation/g1/concurrentG1Refine.hpp"
tschatzl@5204 27 #include "gc_implementation/g1/concurrentG1RefineThread.hpp"
tschatzl@5204 28 #include "gc_implementation/g1/heapRegion.hpp"
tschatzl@5204 29 #include "gc_implementation/g1/g1CollectedHeap.inline.hpp"
tschatzl@5204 30 #include "gc_implementation/g1/g1RemSet.inline.hpp"
tschatzl@5204 31 #include "gc_implementation/g1/g1RemSetSummary.hpp"
tschatzl@5204 32 #include "gc_implementation/g1/heapRegionRemSet.hpp"
tschatzl@5204 33 #include "runtime/thread.inline.hpp"
tschatzl@5204 34
tschatzl@5204 35 class GetRSThreadVTimeClosure : public ThreadClosure {
tschatzl@5204 36 private:
tschatzl@5204 37 G1RemSetSummary* _summary;
tschatzl@5204 38 uint _counter;
tschatzl@5204 39
tschatzl@5204 40 public:
tschatzl@5204 41 GetRSThreadVTimeClosure(G1RemSetSummary * summary) : ThreadClosure(), _summary(summary), _counter(0) {
tschatzl@5204 42 assert(_summary != NULL, "just checking");
tschatzl@5204 43 }
tschatzl@5204 44
tschatzl@5204 45 virtual void do_thread(Thread* t) {
tschatzl@5204 46 ConcurrentG1RefineThread* crt = (ConcurrentG1RefineThread*) t;
tschatzl@5204 47 _summary->set_rs_thread_vtime(_counter, crt->vtime_accum());
tschatzl@5204 48 _counter++;
tschatzl@5204 49 }
tschatzl@5204 50 };
tschatzl@5204 51
tschatzl@5204 52 void G1RemSetSummary::update() {
tschatzl@5204 53 _num_refined_cards = remset()->conc_refine_cards();
tschatzl@5204 54 DirtyCardQueueSet& dcqs = JavaThread::dirty_card_queue_set();
tschatzl@5204 55 _num_processed_buf_mutator = dcqs.processed_buffers_mut();
tschatzl@5204 56 _num_processed_buf_rs_threads = dcqs.processed_buffers_rs_thread();
tschatzl@5204 57
tschatzl@5204 58 _num_coarsenings = HeapRegionRemSet::n_coarsenings();
tschatzl@5204 59
tschatzl@5204 60 ConcurrentG1Refine * cg1r = G1CollectedHeap::heap()->concurrent_g1_refine();
tschatzl@5204 61 if (_rs_threads_vtimes != NULL) {
tschatzl@5204 62 GetRSThreadVTimeClosure p(this);
tschatzl@5204 63 cg1r->worker_threads_do(&p);
tschatzl@5204 64 }
tschatzl@5204 65 set_sampling_thread_vtime(cg1r->sampling_thread()->vtime_accum());
tschatzl@5204 66 }
tschatzl@5204 67
tschatzl@5204 68 void G1RemSetSummary::set_rs_thread_vtime(uint thread, double value) {
tschatzl@5204 69 assert(_rs_threads_vtimes != NULL, "just checking");
tschatzl@5204 70 assert(thread < _num_vtimes, "just checking");
tschatzl@5204 71 _rs_threads_vtimes[thread] = value;
tschatzl@5204 72 }
tschatzl@5204 73
tschatzl@5204 74 double G1RemSetSummary::rs_thread_vtime(uint thread) const {
tschatzl@5204 75 assert(_rs_threads_vtimes != NULL, "just checking");
tschatzl@5204 76 assert(thread < _num_vtimes, "just checking");
tschatzl@5204 77 return _rs_threads_vtimes[thread];
tschatzl@5204 78 }
tschatzl@5204 79
tschatzl@5812 80 void G1RemSetSummary::initialize(G1RemSet* remset) {
tschatzl@5204 81 assert(_rs_threads_vtimes == NULL, "just checking");
tschatzl@5204 82 assert(remset != NULL, "just checking");
tschatzl@5204 83
tschatzl@5204 84 _remset = remset;
tschatzl@5812 85 _num_vtimes = ConcurrentG1Refine::thread_num();
tschatzl@5204 86 _rs_threads_vtimes = NEW_C_HEAP_ARRAY(double, _num_vtimes, mtGC);
tschatzl@5204 87 memset(_rs_threads_vtimes, 0, sizeof(double) * _num_vtimes);
tschatzl@5204 88
tschatzl@5204 89 update();
tschatzl@5204 90 }
tschatzl@5204 91
tschatzl@5204 92 void G1RemSetSummary::set(G1RemSetSummary* other) {
tschatzl@5204 93 assert(other != NULL, "just checking");
tschatzl@5204 94 assert(remset() == other->remset(), "just checking");
tschatzl@5204 95 assert(_num_vtimes == other->_num_vtimes, "just checking");
tschatzl@5204 96
tschatzl@5204 97 _num_refined_cards = other->num_concurrent_refined_cards();
tschatzl@5204 98
tschatzl@5204 99 _num_processed_buf_mutator = other->num_processed_buf_mutator();
tschatzl@5204 100 _num_processed_buf_rs_threads = other->num_processed_buf_rs_threads();
tschatzl@5204 101
tschatzl@5204 102 _num_coarsenings = other->_num_coarsenings;
tschatzl@5204 103
tschatzl@5204 104 memcpy(_rs_threads_vtimes, other->_rs_threads_vtimes, sizeof(double) * _num_vtimes);
tschatzl@5204 105
tschatzl@5204 106 set_sampling_thread_vtime(other->sampling_thread_vtime());
tschatzl@5204 107 }
tschatzl@5204 108
tschatzl@5204 109 void G1RemSetSummary::subtract_from(G1RemSetSummary* other) {
tschatzl@5204 110 assert(other != NULL, "just checking");
tschatzl@5204 111 assert(remset() == other->remset(), "just checking");
tschatzl@5204 112 assert(_num_vtimes == other->_num_vtimes, "just checking");
tschatzl@5204 113
tschatzl@5204 114 _num_refined_cards = other->num_concurrent_refined_cards() - _num_refined_cards;
tschatzl@5204 115
tschatzl@5204 116 _num_processed_buf_mutator = other->num_processed_buf_mutator() - _num_processed_buf_mutator;
tschatzl@5204 117 _num_processed_buf_rs_threads = other->num_processed_buf_rs_threads() - _num_processed_buf_rs_threads;
tschatzl@5204 118
tschatzl@5204 119 _num_coarsenings = other->num_coarsenings() - _num_coarsenings;
tschatzl@5204 120
tschatzl@5204 121 for (uint i = 0; i < _num_vtimes; i++) {
tschatzl@5204 122 set_rs_thread_vtime(i, other->rs_thread_vtime(i) - rs_thread_vtime(i));
tschatzl@5204 123 }
tschatzl@5204 124
tschatzl@5204 125 _sampling_thread_vtime = other->sampling_thread_vtime() - _sampling_thread_vtime;
tschatzl@5204 126 }
tschatzl@5204 127
tschatzl@5807 128 static double percent_of(size_t numerator, size_t denominator) {
tschatzl@5807 129 if (denominator != 0) {
tschatzl@5807 130 return (double)numerator / denominator * 100.0f;
tschatzl@5807 131 } else {
tschatzl@5807 132 return 0.0f;
tschatzl@5807 133 }
tschatzl@5807 134 }
tschatzl@5807 135
tschatzl@5807 136 static size_t round_to_K(size_t value) {
tschatzl@5807 137 return value / K;
tschatzl@5807 138 }
tschatzl@5807 139
tschatzl@5807 140 class RegionTypeCounter VALUE_OBJ_CLASS_SPEC {
tschatzl@5807 141 private:
tschatzl@5807 142 const char* _name;
tschatzl@5807 143
tschatzl@5807 144 size_t _rs_mem_size;
tschatzl@5807 145 size_t _cards_occupied;
tschatzl@5807 146 size_t _amount;
tschatzl@5807 147
tschatzl@5807 148 size_t _code_root_mem_size;
tschatzl@5807 149 size_t _code_root_elems;
tschatzl@5807 150
tschatzl@5807 151 double rs_mem_size_percent_of(size_t total) {
tschatzl@5807 152 return percent_of(_rs_mem_size, total);
tschatzl@5807 153 }
tschatzl@5807 154
tschatzl@5807 155 double cards_occupied_percent_of(size_t total) {
tschatzl@5807 156 return percent_of(_cards_occupied, total);
tschatzl@5807 157 }
tschatzl@5807 158
tschatzl@5807 159 double code_root_mem_size_percent_of(size_t total) {
tschatzl@5807 160 return percent_of(_code_root_mem_size, total);
tschatzl@5807 161 }
tschatzl@5807 162
tschatzl@5807 163 double code_root_elems_percent_of(size_t total) {
tschatzl@5807 164 return percent_of(_code_root_elems, total);
tschatzl@5807 165 }
tschatzl@5807 166
tschatzl@5807 167 size_t amount() const { return _amount; }
tschatzl@5807 168
tschatzl@5807 169 public:
tschatzl@5807 170
tschatzl@5807 171 RegionTypeCounter(const char* name) : _name(name), _rs_mem_size(0), _cards_occupied(0),
tschatzl@5807 172 _amount(0), _code_root_mem_size(0), _code_root_elems(0) { }
tschatzl@5807 173
tschatzl@5807 174 void add(size_t rs_mem_size, size_t cards_occupied, size_t code_root_mem_size,
tschatzl@5807 175 size_t code_root_elems) {
tschatzl@5807 176 _rs_mem_size += rs_mem_size;
tschatzl@5807 177 _cards_occupied += cards_occupied;
tschatzl@5807 178 _code_root_mem_size += code_root_mem_size;
tschatzl@5807 179 _code_root_elems += code_root_elems;
tschatzl@5807 180 _amount++;
tschatzl@5807 181 }
tschatzl@5807 182
tschatzl@5807 183 size_t rs_mem_size() const { return _rs_mem_size; }
tschatzl@5807 184 size_t cards_occupied() const { return _cards_occupied; }
tschatzl@5807 185
tschatzl@5807 186 size_t code_root_mem_size() const { return _code_root_mem_size; }
tschatzl@5807 187 size_t code_root_elems() const { return _code_root_elems; }
tschatzl@5807 188
tschatzl@5807 189 void print_rs_mem_info_on(outputStream * out, size_t total) {
sjohanss@6009 190 out->print_cr(" "SIZE_FORMAT_W(8)"K (%5.1f%%) by "SIZE_FORMAT" %s regions",
sjohanss@6009 191 round_to_K(rs_mem_size()), rs_mem_size_percent_of(total), amount(), _name);
tschatzl@5807 192 }
tschatzl@5807 193
tschatzl@5807 194 void print_cards_occupied_info_on(outputStream * out, size_t total) {
sjohanss@6009 195 out->print_cr(" "SIZE_FORMAT_W(8)" (%5.1f%%) entries by "SIZE_FORMAT" %s regions",
sjohanss@6009 196 cards_occupied(), cards_occupied_percent_of(total), amount(), _name);
tschatzl@5807 197 }
tschatzl@5807 198
tschatzl@5807 199 void print_code_root_mem_info_on(outputStream * out, size_t total) {
sjohanss@6009 200 out->print_cr(" "SIZE_FORMAT_W(8)"K (%5.1f%%) by "SIZE_FORMAT" %s regions",
sjohanss@6009 201 round_to_K(code_root_mem_size()), code_root_mem_size_percent_of(total), amount(), _name);
tschatzl@5807 202 }
tschatzl@5807 203
tschatzl@5807 204 void print_code_root_elems_info_on(outputStream * out, size_t total) {
sjohanss@6009 205 out->print_cr(" "SIZE_FORMAT_W(8)" (%5.1f%%) elements by "SIZE_FORMAT" %s regions",
sjohanss@6009 206 code_root_elems(), code_root_elems_percent_of(total), amount(), _name);
tschatzl@5807 207 }
tschatzl@5807 208 };
tschatzl@5807 209
tschatzl@5807 210
tschatzl@5204 211 class HRRSStatsIter: public HeapRegionClosure {
tschatzl@5807 212 private:
tschatzl@5807 213 RegionTypeCounter _young;
tschatzl@5807 214 RegionTypeCounter _humonguous;
tschatzl@5807 215 RegionTypeCounter _free;
tschatzl@5807 216 RegionTypeCounter _old;
tschatzl@5807 217 RegionTypeCounter _all;
johnc@5548 218
johnc@5548 219 size_t _max_rs_mem_sz;
johnc@5548 220 HeapRegion* _max_rs_mem_sz_region;
johnc@5548 221
tschatzl@5807 222 size_t total_rs_mem_sz() const { return _all.rs_mem_size(); }
tschatzl@5807 223 size_t total_cards_occupied() const { return _all.cards_occupied(); }
tschatzl@5807 224
tschatzl@5807 225 size_t max_rs_mem_sz() const { return _max_rs_mem_sz; }
tschatzl@5807 226 HeapRegion* max_rs_mem_sz_region() const { return _max_rs_mem_sz_region; }
tschatzl@5807 227
johnc@5548 228 size_t _max_code_root_mem_sz;
johnc@5548 229 HeapRegion* _max_code_root_mem_sz_region;
tschatzl@5807 230
tschatzl@5807 231 size_t total_code_root_mem_sz() const { return _all.code_root_mem_size(); }
tschatzl@5807 232 size_t total_code_root_elems() const { return _all.code_root_elems(); }
tschatzl@5807 233
tschatzl@5807 234 size_t max_code_root_mem_sz() const { return _max_code_root_mem_sz; }
tschatzl@5807 235 HeapRegion* max_code_root_mem_sz_region() const { return _max_code_root_mem_sz_region; }
tschatzl@5807 236
tschatzl@5204 237 public:
tschatzl@5807 238 HRRSStatsIter() : _all("All"), _young("Young"), _humonguous("Humonguous"),
tschatzl@5807 239 _free("Free"), _old("Old"), _max_code_root_mem_sz_region(NULL), _max_rs_mem_sz_region(NULL),
tschatzl@5807 240 _max_rs_mem_sz(0), _max_code_root_mem_sz(0)
tschatzl@5204 241 {}
tschatzl@5204 242
tschatzl@5204 243 bool doHeapRegion(HeapRegion* r) {
johnc@5548 244 HeapRegionRemSet* hrrs = r->rem_set();
johnc@5548 245
johnc@5548 246 // HeapRegionRemSet::mem_size() includes the
johnc@5548 247 // size of the strong code roots
johnc@5548 248 size_t rs_mem_sz = hrrs->mem_size();
johnc@5548 249 if (rs_mem_sz > _max_rs_mem_sz) {
johnc@5548 250 _max_rs_mem_sz = rs_mem_sz;
johnc@5548 251 _max_rs_mem_sz_region = r;
tschatzl@5204 252 }
tschatzl@5807 253 size_t occupied_cards = hrrs->occupied();
johnc@5548 254 size_t code_root_mem_sz = hrrs->strong_code_roots_mem_size();
tschatzl@5807 255 if (code_root_mem_sz > max_code_root_mem_sz()) {
mgerdin@7208 256 _max_code_root_mem_sz = code_root_mem_sz;
johnc@5548 257 _max_code_root_mem_sz_region = r;
johnc@5548 258 }
tschatzl@5807 259 size_t code_root_elems = hrrs->strong_code_roots_list_length();
johnc@5548 260
tschatzl@5807 261 RegionTypeCounter* current = NULL;
brutisso@7195 262 if (r->is_free()) {
brutisso@7195 263 current = &_free;
brutisso@7195 264 } else if (r->is_young()) {
tschatzl@5807 265 current = &_young;
tschatzl@5807 266 } else if (r->isHumongous()) {
tschatzl@5807 267 current = &_humonguous;
brutisso@7195 268 } else if (r->is_old()) {
brutisso@7195 269 current = &_old;
tschatzl@5807 270 } else {
brutisso@7195 271 ShouldNotReachHere();
tschatzl@5807 272 }
tschatzl@5807 273 current->add(rs_mem_sz, occupied_cards, code_root_mem_sz, code_root_elems);
tschatzl@5807 274 _all.add(rs_mem_sz, occupied_cards, code_root_mem_sz, code_root_elems);
tschatzl@5807 275
tschatzl@5204 276 return false;
tschatzl@5204 277 }
tschatzl@5807 278
tschatzl@5807 279 void print_summary_on(outputStream* out) {
tschatzl@5807 280 RegionTypeCounter* counters[] = { &_young, &_humonguous, &_free, &_old, NULL };
tschatzl@5807 281
tschatzl@5807 282 out->print_cr("\n Current rem set statistics");
tschatzl@5807 283 out->print_cr(" Total per region rem sets sizes = "SIZE_FORMAT"K."
tschatzl@5807 284 " Max = "SIZE_FORMAT"K.",
tschatzl@5807 285 round_to_K(total_rs_mem_sz()), round_to_K(max_rs_mem_sz()));
tschatzl@5807 286 for (RegionTypeCounter** current = &counters[0]; *current != NULL; current++) {
tschatzl@5807 287 (*current)->print_rs_mem_info_on(out, total_rs_mem_sz());
tschatzl@5807 288 }
tschatzl@5807 289
tschatzl@5807 290 out->print_cr(" Static structures = "SIZE_FORMAT"K,"
tschatzl@5807 291 " free_lists = "SIZE_FORMAT"K.",
tschatzl@5807 292 round_to_K(HeapRegionRemSet::static_mem_size()),
tschatzl@5807 293 round_to_K(HeapRegionRemSet::fl_mem_size()));
tschatzl@5807 294
tschatzl@5807 295 out->print_cr(" "SIZE_FORMAT" occupied cards represented.",
tschatzl@5807 296 total_cards_occupied());
tschatzl@5807 297 for (RegionTypeCounter** current = &counters[0]; *current != NULL; current++) {
tschatzl@5807 298 (*current)->print_cards_occupied_info_on(out, total_cards_occupied());
tschatzl@5807 299 }
tschatzl@5807 300
tschatzl@5807 301 // Largest sized rem set region statistics
tschatzl@5807 302 HeapRegionRemSet* rem_set = max_rs_mem_sz_region()->rem_set();
tschatzl@5807 303 out->print_cr(" Region with largest rem set = "HR_FORMAT", "
tschatzl@5807 304 "size = "SIZE_FORMAT "K, occupied = "SIZE_FORMAT"K.",
tschatzl@5807 305 HR_FORMAT_PARAMS(max_rs_mem_sz_region()),
tschatzl@5807 306 round_to_K(rem_set->mem_size()),
tschatzl@5807 307 round_to_K(rem_set->occupied()));
tschatzl@5807 308
tschatzl@5807 309 // Strong code root statistics
tschatzl@5807 310 HeapRegionRemSet* max_code_root_rem_set = max_code_root_mem_sz_region()->rem_set();
tschatzl@5807 311 out->print_cr(" Total heap region code root sets sizes = "SIZE_FORMAT"K."
tschatzl@5807 312 " Max = "SIZE_FORMAT"K.",
tschatzl@5807 313 round_to_K(total_code_root_mem_sz()),
tschatzl@5807 314 round_to_K(max_code_root_rem_set->strong_code_roots_mem_size()));
tschatzl@5807 315 for (RegionTypeCounter** current = &counters[0]; *current != NULL; current++) {
tschatzl@5807 316 (*current)->print_code_root_mem_info_on(out, total_code_root_mem_sz());
tschatzl@5807 317 }
tschatzl@5807 318
tschatzl@5807 319 out->print_cr(" "SIZE_FORMAT" code roots represented.",
tschatzl@5807 320 total_code_root_elems());
tschatzl@5807 321 for (RegionTypeCounter** current = &counters[0]; *current != NULL; current++) {
tschatzl@5807 322 (*current)->print_code_root_elems_info_on(out, total_code_root_elems());
tschatzl@5807 323 }
tschatzl@5807 324
tschatzl@5807 325 out->print_cr(" Region with largest amount of code roots = "HR_FORMAT", "
tschatzl@5807 326 "size = "SIZE_FORMAT "K, num_elems = "SIZE_FORMAT".",
tschatzl@5807 327 HR_FORMAT_PARAMS(max_code_root_mem_sz_region()),
tschatzl@5807 328 round_to_K(max_code_root_rem_set->strong_code_roots_mem_size()),
tschatzl@5807 329 round_to_K(max_code_root_rem_set->strong_code_roots_list_length()));
tschatzl@5807 330 }
tschatzl@5204 331 };
tschatzl@5204 332
tschatzl@5204 333 void G1RemSetSummary::print_on(outputStream* out) {
tschatzl@5807 334 out->print_cr("\n Recent concurrent refinement statistics");
tschatzl@5807 335 out->print_cr(" Processed "SIZE_FORMAT" cards",
tschatzl@5204 336 num_concurrent_refined_cards());
sjohanss@6009 337 out->print_cr(" Of "SIZE_FORMAT" completed buffers:", num_processed_buf_total());
sjohanss@6009 338 out->print_cr(" "SIZE_FORMAT_W(8)" (%5.1f%%) by concurrent RS threads.",
tschatzl@5204 339 num_processed_buf_total(),
tschatzl@5807 340 percent_of(num_processed_buf_rs_threads(), num_processed_buf_total()));
sjohanss@6009 341 out->print_cr(" "SIZE_FORMAT_W(8)" (%5.1f%%) by mutator threads.",
tschatzl@5204 342 num_processed_buf_mutator(),
tschatzl@5807 343 percent_of(num_processed_buf_mutator(), num_processed_buf_total()));
sjohanss@6009 344 out->print_cr(" Did "SIZE_FORMAT" coarsenings.", num_coarsenings());
tschatzl@5204 345 out->print_cr(" Concurrent RS threads times (s)");
tschatzl@5204 346 out->print(" ");
tschatzl@5204 347 for (uint i = 0; i < _num_vtimes; i++) {
tschatzl@5204 348 out->print(" %5.2f", rs_thread_vtime(i));
tschatzl@5204 349 }
tschatzl@5204 350 out->cr();
tschatzl@5204 351 out->print_cr(" Concurrent sampling threads times (s)");
tschatzl@5204 352 out->print_cr(" %5.2f", sampling_thread_vtime());
tschatzl@5204 353
tschatzl@5204 354 HRRSStatsIter blk;
tschatzl@5204 355 G1CollectedHeap::heap()->heap_region_iterate(&blk);
tschatzl@5807 356 blk.print_summary_on(out);
tschatzl@5204 357 }

mercurial