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

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

author
tschatzl
date
Fri, 10 Oct 2014 15:51:58 +0200
changeset 7257
e7d0505c8a30
parent 7195
c02ec279b062
child 7535
7ae4e26cb1e0
child 7652
ae374055ebce
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

johnc@5078 1 /*
johnc@5078 2 * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
johnc@5078 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
johnc@5078 4 *
johnc@5078 5 * This code is free software; you can redistribute it and/or modify it
johnc@5078 6 * under the terms of the GNU General Public License version 2 only, as
johnc@5078 7 * published by the Free Software Foundation.
johnc@5078 8 *
johnc@5078 9 * This code is distributed in the hope that it will be useful, but WITHOUT
johnc@5078 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
johnc@5078 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
johnc@5078 12 * version 2 for more details (a copy is included in the LICENSE file that
johnc@5078 13 * accompanied this code).
johnc@5078 14 *
johnc@5078 15 * You should have received a copy of the GNU General Public License version
johnc@5078 16 * 2 along with this work; if not, write to the Free Software Foundation,
johnc@5078 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
johnc@5078 18 *
johnc@5078 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
johnc@5078 20 * or visit www.oracle.com if you need additional information or have any
johnc@5078 21 * questions.
johnc@5078 22 *
johnc@5078 23 */
johnc@5078 24
johnc@5078 25 #include "precompiled.hpp"
johnc@5078 26 #include "gc_implementation/g1/dirtyCardQueue.hpp"
johnc@5078 27 #include "gc_implementation/g1/g1CollectedHeap.inline.hpp"
johnc@5078 28 #include "gc_implementation/g1/g1HotCardCache.hpp"
johnc@5078 29 #include "gc_implementation/g1/g1RemSet.hpp"
johnc@5078 30 #include "runtime/atomic.hpp"
johnc@5078 31
johnc@5078 32 G1HotCardCache::G1HotCardCache(G1CollectedHeap *g1h):
johnc@5078 33 _g1h(g1h), _hot_cache(NULL), _use_cache(false), _card_counts(g1h) {}
johnc@5078 34
tschatzl@7051 35 void G1HotCardCache::initialize(G1RegionToSpaceMapper* card_counts_storage) {
johnc@5078 36 if (default_use_cache()) {
johnc@5078 37 _use_cache = true;
johnc@5078 38
johnc@5078 39 _hot_cache_size = (1 << G1ConcRSLogCacheSize);
johnc@5078 40 _hot_cache = NEW_C_HEAP_ARRAY(jbyte*, _hot_cache_size, mtGC);
johnc@5078 41
johnc@5078 42 _n_hot = 0;
johnc@5078 43 _hot_cache_idx = 0;
johnc@5078 44
johnc@5078 45 // For refining the cards in the hot cache in parallel
vkempik@6552 46 uint n_workers = (ParallelGCThreads > 0 ?
johnc@5078 47 _g1h->workers()->total_workers() : 1);
vkempik@6552 48 _hot_cache_par_chunk_size = MAX2(1, _hot_cache_size / (int)n_workers);
johnc@5078 49 _hot_cache_par_claimed_idx = 0;
johnc@5078 50
tschatzl@7051 51 _card_counts.initialize(card_counts_storage);
johnc@5078 52 }
johnc@5078 53 }
johnc@5078 54
johnc@5078 55 G1HotCardCache::~G1HotCardCache() {
johnc@5078 56 if (default_use_cache()) {
johnc@5078 57 assert(_hot_cache != NULL, "Logic");
johnc@5078 58 FREE_C_HEAP_ARRAY(jbyte*, _hot_cache, mtGC);
johnc@5078 59 }
johnc@5078 60 }
johnc@5078 61
johnc@5078 62 jbyte* G1HotCardCache::insert(jbyte* card_ptr) {
johnc@5078 63 uint count = _card_counts.add_card_count(card_ptr);
johnc@5078 64 if (!_card_counts.is_hot(count)) {
johnc@5078 65 // The card is not hot so do not store it in the cache;
johnc@5078 66 // return it for immediate refining.
johnc@5078 67 return card_ptr;
johnc@5078 68 }
johnc@5078 69
johnc@5078 70 // Otherwise, the card is hot.
johnc@5078 71 jbyte* res = NULL;
johnc@5078 72 MutexLockerEx x(HotCardCache_lock, Mutex::_no_safepoint_check_flag);
johnc@5078 73 if (_n_hot == _hot_cache_size) {
johnc@5078 74 res = _hot_cache[_hot_cache_idx];
johnc@5078 75 _n_hot--;
johnc@5078 76 }
johnc@5078 77
johnc@5078 78 // Now _n_hot < _hot_cache_size, and we can insert at _hot_cache_idx.
johnc@5078 79 _hot_cache[_hot_cache_idx] = card_ptr;
johnc@5078 80 _hot_cache_idx++;
johnc@5078 81
johnc@5078 82 if (_hot_cache_idx == _hot_cache_size) {
johnc@5078 83 // Wrap around
johnc@5078 84 _hot_cache_idx = 0;
johnc@5078 85 }
johnc@5078 86 _n_hot++;
johnc@5078 87
johnc@5078 88 return res;
johnc@5078 89 }
johnc@5078 90
vkempik@6552 91 void G1HotCardCache::drain(uint worker_i,
johnc@5078 92 G1RemSet* g1rs,
johnc@5078 93 DirtyCardQueue* into_cset_dcq) {
johnc@5078 94 if (!default_use_cache()) {
johnc@5078 95 assert(_hot_cache == NULL, "Logic");
johnc@5078 96 return;
johnc@5078 97 }
johnc@5078 98
johnc@5078 99 assert(_hot_cache != NULL, "Logic");
johnc@5078 100 assert(!use_cache(), "cache should be disabled");
johnc@5078 101 int start_idx;
johnc@5078 102
johnc@5078 103 while ((start_idx = _hot_cache_par_claimed_idx) < _n_hot) { // read once
johnc@5078 104 int end_idx = start_idx + _hot_cache_par_chunk_size;
johnc@5078 105
johnc@5078 106 if (start_idx ==
johnc@5078 107 Atomic::cmpxchg(end_idx, &_hot_cache_par_claimed_idx, start_idx)) {
johnc@5078 108 // The current worker has successfully claimed the chunk [start_idx..end_idx)
johnc@5078 109 end_idx = MIN2(end_idx, _n_hot);
johnc@5078 110 for (int i = start_idx; i < end_idx; i++) {
johnc@5078 111 jbyte* card_ptr = _hot_cache[i];
johnc@5078 112 if (card_ptr != NULL) {
johnc@5078 113 if (g1rs->refine_card(card_ptr, worker_i, true)) {
johnc@5078 114 // The part of the heap spanned by the card contains references
johnc@5078 115 // that point into the current collection set.
johnc@5078 116 // We need to record the card pointer in the DirtyCardQueueSet
johnc@5078 117 // that we use for such cards.
johnc@5078 118 //
johnc@5078 119 // The only time we care about recording cards that contain
johnc@5078 120 // references that point into the collection set is during
johnc@5078 121 // RSet updating while within an evacuation pause.
johnc@5078 122 // In this case worker_i should be the id of a GC worker thread
johnc@5078 123 assert(SafepointSynchronize::is_at_safepoint(), "Should be at a safepoint");
vkempik@6552 124 assert(worker_i < (ParallelGCThreads == 0 ? 1 : ParallelGCThreads),
vkempik@6552 125 err_msg("incorrect worker id: "UINT32_FORMAT, worker_i));
johnc@5078 126
johnc@5078 127 into_cset_dcq->enqueue(card_ptr);
johnc@5078 128 }
johnc@5078 129 }
johnc@5078 130 }
johnc@5078 131 }
johnc@5078 132 }
johnc@5078 133 // The existing entries in the hot card cache, which were just refined
johnc@5078 134 // above, are discarded prior to re-enabling the cache near the end of the GC.
johnc@5078 135 }
johnc@5078 136
johnc@5078 137 void G1HotCardCache::reset_card_counts(HeapRegion* hr) {
johnc@5078 138 _card_counts.clear_region(hr);
johnc@5078 139 }
johnc@5078 140
johnc@5078 141 void G1HotCardCache::reset_card_counts() {
johnc@5078 142 _card_counts.clear_all();
johnc@5078 143 }

mercurial