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

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

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

ysr@777 1 /*
trims@1907 2 * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved.
ysr@777 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
ysr@777 4 *
ysr@777 5 * This code is free software; you can redistribute it and/or modify it
ysr@777 6 * under the terms of the GNU General Public License version 2 only, as
ysr@777 7 * published by the Free Software Foundation.
ysr@777 8 *
ysr@777 9 * This code is distributed in the hope that it will be useful, but WITHOUT
ysr@777 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
ysr@777 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
ysr@777 12 * version 2 for more details (a copy is included in the LICENSE file that
ysr@777 13 * accompanied this code).
ysr@777 14 *
ysr@777 15 * You should have received a copy of the GNU General Public License version
ysr@777 16 * 2 along with this work; if not, write to the Free Software Foundation,
ysr@777 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
ysr@777 18 *
trims@1907 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
trims@1907 20 * or visit www.oracle.com if you need additional information or have any
trims@1907 21 * questions.
ysr@777 22 *
ysr@777 23 */
ysr@777 24
stefank@2314 25 #include "precompiled.hpp"
stefank@2314 26 #include "gc_implementation/g1/concurrentG1Refine.hpp"
stefank@2314 27 #include "gc_implementation/g1/concurrentG1RefineThread.hpp"
stefank@2314 28 #include "gc_implementation/g1/g1CollectedHeap.inline.hpp"
stefank@2314 29 #include "gc_implementation/g1/g1CollectorPolicy.hpp"
stefank@2314 30 #include "memory/resourceArea.hpp"
stefank@2314 31 #include "runtime/handles.inline.hpp"
stefank@2314 32 #include "runtime/mutexLocker.hpp"
ysr@777 33
ysr@777 34 ConcurrentG1RefineThread::
iveresov@1230 35 ConcurrentG1RefineThread(ConcurrentG1Refine* cg1r, ConcurrentG1RefineThread *next,
tschatzl@6930 36 CardTableEntryClosure* refine_closure,
vkempik@6552 37 uint worker_id_offset, uint worker_id) :
ysr@777 38 ConcurrentGCThread(),
tschatzl@6930 39 _refine_closure(refine_closure),
iveresov@1230 40 _worker_id_offset(worker_id_offset),
iveresov@1229 41 _worker_id(worker_id),
iveresov@1229 42 _active(false),
iveresov@1229 43 _next(next),
iveresov@1546 44 _monitor(NULL),
ysr@777 45 _cg1r(cg1r),
iveresov@1546 46 _vtime_accum(0.0)
ysr@777 47 {
iveresov@1546 48
iveresov@1546 49 // Each thread has its own monitor. The i-th thread is responsible for signalling
iveresov@1546 50 // to thread i+1 if the number of buffers in the queue exceeds a threashold for this
iveresov@1546 51 // thread. Monitors are also used to wake up the threads during termination.
iveresov@1546 52 // The 0th worker in notified by mutator threads and has a special monitor.
iveresov@1546 53 // The last worker is used for young gen rset size sampling.
iveresov@1546 54 if (worker_id > 0) {
iveresov@1546 55 _monitor = new Monitor(Mutex::nonleaf, "Refinement monitor", true);
iveresov@1546 56 } else {
iveresov@1546 57 _monitor = DirtyCardQ_CBL_mon;
iveresov@1546 58 }
iveresov@1546 59 initialize();
ysr@777 60 create_and_start();
ysr@777 61 }
ysr@777 62
iveresov@1546 63 void ConcurrentG1RefineThread::initialize() {
iveresov@1546 64 if (_worker_id < cg1r()->worker_thread_num()) {
iveresov@1546 65 // Current thread activation threshold
iveresov@1546 66 _threshold = MIN2<int>(cg1r()->thread_threshold_step() * (_worker_id + 1) + cg1r()->green_zone(),
iveresov@1546 67 cg1r()->yellow_zone());
iveresov@1546 68 // A thread deactivates once the number of buffer reached a deactivation threshold
iveresov@1546 69 _deactivation_threshold = MAX2<int>(_threshold - cg1r()->thread_threshold_step(), cg1r()->green_zone());
iveresov@1546 70 } else {
iveresov@1546 71 set_active(true);
iveresov@1546 72 }
iveresov@1546 73 }
iveresov@1546 74
ysr@777 75 void ConcurrentG1RefineThread::sample_young_list_rs_lengths() {
pliden@6906 76 SuspendibleThreadSetJoiner sts;
ysr@777 77 G1CollectedHeap* g1h = G1CollectedHeap::heap();
ysr@777 78 G1CollectorPolicy* g1p = g1h->g1_policy();
ysr@777 79 if (g1p->adaptive_young_list_length()) {
ysr@777 80 int regions_visited = 0;
johnc@1829 81 g1h->young_list()->rs_length_sampling_init();
johnc@1829 82 while (g1h->young_list()->rs_length_sampling_more()) {
johnc@1829 83 g1h->young_list()->rs_length_sampling_next();
ysr@777 84 ++regions_visited;
ysr@777 85
ysr@777 86 // we try to yield every time we visit 10 regions
ysr@777 87 if (regions_visited == 10) {
pliden@6906 88 if (sts.should_yield()) {
pliden@6906 89 sts.yield();
ysr@777 90 // we just abandon the iteration
ysr@777 91 break;
ysr@777 92 }
ysr@777 93 regions_visited = 0;
ysr@777 94 }
ysr@777 95 }
ysr@777 96
tonyp@3119 97 g1p->revise_young_list_target_length_if_necessary();
ysr@777 98 }
ysr@777 99 }
ysr@777 100
iveresov@1546 101 void ConcurrentG1RefineThread::run_young_rs_sampling() {
iveresov@1546 102 DirtyCardQueueSet& dcqs = JavaThread::dirty_card_queue_set();
iveresov@1546 103 _vtime_start = os::elapsedVTime();
iveresov@1546 104 while(!_should_terminate) {
iveresov@1546 105 sample_young_list_rs_lengths();
iveresov@1546 106
iveresov@1546 107 if (os::supports_vtime()) {
iveresov@1546 108 _vtime_accum = (os::elapsedVTime() - _vtime_start);
iveresov@1546 109 } else {
iveresov@1546 110 _vtime_accum = 0.0;
iveresov@1546 111 }
iveresov@1546 112
iveresov@1546 113 MutexLockerEx x(_monitor, Mutex::_no_safepoint_check_flag);
iveresov@1546 114 if (_should_terminate) {
iveresov@1546 115 break;
iveresov@1546 116 }
tonyp@1717 117 _monitor->wait(Mutex::_no_safepoint_check_flag, G1ConcRefinementServiceIntervalMillis);
iveresov@1546 118 }
iveresov@1546 119 }
iveresov@1546 120
iveresov@1546 121 void ConcurrentG1RefineThread::wait_for_completed_buffers() {
iveresov@1546 122 DirtyCardQueueSet& dcqs = JavaThread::dirty_card_queue_set();
iveresov@1546 123 MutexLockerEx x(_monitor, Mutex::_no_safepoint_check_flag);
iveresov@1546 124 while (!_should_terminate && !is_active()) {
iveresov@1546 125 _monitor->wait(Mutex::_no_safepoint_check_flag);
iveresov@1546 126 }
iveresov@1546 127 }
iveresov@1546 128
iveresov@1546 129 bool ConcurrentG1RefineThread::is_active() {
iveresov@1546 130 DirtyCardQueueSet& dcqs = JavaThread::dirty_card_queue_set();
iveresov@1546 131 return _worker_id > 0 ? _active : dcqs.process_completed_buffers();
iveresov@1546 132 }
iveresov@1546 133
iveresov@1546 134 void ConcurrentG1RefineThread::activate() {
iveresov@1546 135 MutexLockerEx x(_monitor, Mutex::_no_safepoint_check_flag);
iveresov@1546 136 if (_worker_id > 0) {
tonyp@1717 137 if (G1TraceConcRefinement) {
iveresov@1546 138 DirtyCardQueueSet& dcqs = JavaThread::dirty_card_queue_set();
iveresov@1546 139 gclog_or_tty->print_cr("G1-Refine-activated worker %d, on threshold %d, current %d",
iveresov@1546 140 _worker_id, _threshold, (int)dcqs.completed_buffers_num());
iveresov@1546 141 }
iveresov@1546 142 set_active(true);
iveresov@1546 143 } else {
iveresov@1546 144 DirtyCardQueueSet& dcqs = JavaThread::dirty_card_queue_set();
iveresov@1546 145 dcqs.set_process_completed(true);
iveresov@1546 146 }
iveresov@1546 147 _monitor->notify();
iveresov@1546 148 }
iveresov@1546 149
iveresov@1546 150 void ConcurrentG1RefineThread::deactivate() {
iveresov@1546 151 MutexLockerEx x(_monitor, Mutex::_no_safepoint_check_flag);
iveresov@1546 152 if (_worker_id > 0) {
tonyp@1717 153 if (G1TraceConcRefinement) {
iveresov@1546 154 DirtyCardQueueSet& dcqs = JavaThread::dirty_card_queue_set();
iveresov@1546 155 gclog_or_tty->print_cr("G1-Refine-deactivated worker %d, off threshold %d, current %d",
iveresov@1546 156 _worker_id, _deactivation_threshold, (int)dcqs.completed_buffers_num());
iveresov@1546 157 }
iveresov@1546 158 set_active(false);
iveresov@1546 159 } else {
iveresov@1546 160 DirtyCardQueueSet& dcqs = JavaThread::dirty_card_queue_set();
iveresov@1546 161 dcqs.set_process_completed(false);
iveresov@1546 162 }
iveresov@1546 163 }
iveresov@1546 164
ysr@777 165 void ConcurrentG1RefineThread::run() {
ysr@777 166 initialize_in_thread();
ysr@777 167 wait_for_universe_init();
ysr@777 168
iveresov@1546 169 if (_worker_id >= cg1r()->worker_thread_num()) {
iveresov@1546 170 run_young_rs_sampling();
iveresov@1546 171 terminate();
johnc@1829 172 return;
iveresov@1546 173 }
iveresov@1546 174
iveresov@1546 175 _vtime_start = os::elapsedVTime();
ysr@777 176 while (!_should_terminate) {
iveresov@1229 177 DirtyCardQueueSet& dcqs = JavaThread::dirty_card_queue_set();
iveresov@1546 178
iveresov@1546 179 // Wait for work
iveresov@1546 180 wait_for_completed_buffers();
iveresov@1546 181
iveresov@1546 182 if (_should_terminate) {
iveresov@1546 183 break;
iveresov@1229 184 }
iveresov@1229 185
pliden@6906 186 {
pliden@6906 187 SuspendibleThreadSetJoiner sts;
iveresov@1229 188
pliden@6906 189 do {
pliden@6906 190 int curr_buffer_num = (int)dcqs.completed_buffers_num();
pliden@6906 191 // If the number of the buffers falls down into the yellow zone,
pliden@6906 192 // that means that the transition period after the evacuation pause has ended.
pliden@6906 193 if (dcqs.completed_queue_padding() > 0 && curr_buffer_num <= cg1r()->yellow_zone()) {
pliden@6906 194 dcqs.set_completed_queue_padding(0);
pliden@6906 195 }
pliden@6906 196
pliden@6906 197 if (_worker_id > 0 && curr_buffer_num <= _deactivation_threshold) {
pliden@6906 198 // If the number of the buffer has fallen below our threshold
pliden@6906 199 // we should deactivate. The predecessor will reactivate this
pliden@6906 200 // thread should the number of the buffers cross the threshold again.
pliden@6906 201 deactivate();
pliden@6906 202 break;
pliden@6906 203 }
pliden@6906 204
pliden@6906 205 // Check if we need to activate the next thread.
pliden@6906 206 if (_next != NULL && !_next->is_active() && curr_buffer_num > _next->_threshold) {
pliden@6906 207 _next->activate();
pliden@6906 208 }
tschatzl@6930 209 } while (dcqs.apply_closure_to_completed_buffer(_refine_closure, _worker_id + _worker_id_offset, cg1r()->green_zone()));
pliden@6906 210
pliden@6906 211 // We can exit the loop above while being active if there was a yield request.
pliden@6906 212 if (is_active()) {
pliden@6906 213 deactivate();
iveresov@1546 214 }
iveresov@1229 215 }
iveresov@1546 216
ysr@777 217 if (os::supports_vtime()) {
ysr@777 218 _vtime_accum = (os::elapsedVTime() - _vtime_start);
ysr@777 219 } else {
ysr@777 220 _vtime_accum = 0.0;
ysr@777 221 }
ysr@777 222 }
ysr@777 223 assert(_should_terminate, "just checking");
ysr@777 224 terminate();
ysr@777 225 }
ysr@777 226
ysr@777 227 void ConcurrentG1RefineThread::stop() {
ysr@777 228 // it is ok to take late safepoints here, if needed
ysr@777 229 {
ysr@777 230 MutexLockerEx mu(Terminator_lock);
ysr@777 231 _should_terminate = true;
ysr@777 232 }
ysr@777 233
ysr@777 234 {
iveresov@1546 235 MutexLockerEx x(_monitor, Mutex::_no_safepoint_check_flag);
iveresov@1546 236 _monitor->notify();
ysr@777 237 }
ysr@777 238
ysr@777 239 {
ysr@777 240 MutexLockerEx mu(Terminator_lock);
ysr@777 241 while (!_has_terminated) {
ysr@777 242 Terminator_lock->wait();
ysr@777 243 }
ysr@777 244 }
tonyp@1717 245 if (G1TraceConcRefinement) {
tonyp@1717 246 gclog_or_tty->print_cr("G1-Refine-stop");
tonyp@1717 247 }
ysr@777 248 }
ysr@777 249
tonyp@1454 250 void ConcurrentG1RefineThread::print() const {
tonyp@1454 251 print_on(tty);
ysr@777 252 }
tonyp@1454 253
tonyp@1454 254 void ConcurrentG1RefineThread::print_on(outputStream* st) const {
tonyp@1454 255 st->print("\"G1 Concurrent Refinement Thread#%d\" ", _worker_id);
tonyp@1454 256 Thread::print_on(st);
tonyp@1454 257 st->cr();
tonyp@1454 258 }

mercurial