Wed, 23 Dec 2009 09:23:54 -0800
6631166: CMS: better heuristics when combatting fragmentation
Summary: Autonomic per-worker free block cache sizing, tunable coalition policies, fixes to per-size block statistics, retuned gain and bandwidth of some feedback loop filters to allow quicker reactivity to abrupt changes in ambient demand, and other heuristics to reduce fragmentation of the CMS old gen. Also tightened some assertions, including those related to locking.
Reviewed-by: jmasa
1 /*
2 * Copyright 2005-2006 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
20 * CA 95054 USA or visit www.sun.com if you need additional information or
21 * have any questions.
22 *
23 */
24 # include "incls/_precompiled.incl"
25 # include "incls/_vmCMSOperations.cpp.incl"
27 HS_DTRACE_PROBE_DECL(hs_private, cms__initmark__begin);
28 HS_DTRACE_PROBE_DECL(hs_private, cms__initmark__end);
30 HS_DTRACE_PROBE_DECL(hs_private, cms__remark__begin);
31 HS_DTRACE_PROBE_DECL(hs_private, cms__remark__end);
33 //////////////////////////////////////////////////////////
34 // Methods in abstract class VM_CMS_Operation
35 //////////////////////////////////////////////////////////
36 void VM_CMS_Operation::acquire_pending_list_lock() {
37 // The caller may block while communicating
38 // with the SLT thread in order to acquire/release the PLL.
39 ConcurrentMarkSweepThread::slt()->
40 manipulatePLL(SurrogateLockerThread::acquirePLL);
41 }
43 void VM_CMS_Operation::release_and_notify_pending_list_lock() {
44 // The caller may block while communicating
45 // with the SLT thread in order to acquire/release the PLL.
46 ConcurrentMarkSweepThread::slt()->
47 manipulatePLL(SurrogateLockerThread::releaseAndNotifyPLL);
48 }
50 void VM_CMS_Operation::verify_before_gc() {
51 if (VerifyBeforeGC &&
52 GenCollectedHeap::heap()->total_collections() >= VerifyGCStartAt) {
53 HandleMark hm;
54 FreelistLocker x(_collector);
55 MutexLockerEx y(_collector->bitMapLock(), Mutex::_no_safepoint_check_flag);
56 Universe::heap()->prepare_for_verify();
57 Universe::verify(true);
58 }
59 }
61 void VM_CMS_Operation::verify_after_gc() {
62 if (VerifyAfterGC &&
63 GenCollectedHeap::heap()->total_collections() >= VerifyGCStartAt) {
64 HandleMark hm;
65 FreelistLocker x(_collector);
66 MutexLockerEx y(_collector->bitMapLock(), Mutex::_no_safepoint_check_flag);
67 Universe::verify(true);
68 }
69 }
71 bool VM_CMS_Operation::lost_race() const {
72 if (CMSCollector::abstract_state() == CMSCollector::Idling) {
73 // We lost a race to a foreground collection
74 // -- there's nothing to do
75 return true;
76 }
77 assert(CMSCollector::abstract_state() == legal_state(),
78 "Inconsistent collector state?");
79 return false;
80 }
82 bool VM_CMS_Operation::doit_prologue() {
83 assert(Thread::current()->is_ConcurrentGC_thread(), "just checking");
84 assert(!CMSCollector::foregroundGCShouldWait(), "Possible deadlock");
85 assert(!ConcurrentMarkSweepThread::cms_thread_has_cms_token(),
86 "Possible deadlock");
88 if (needs_pll()) {
89 acquire_pending_list_lock();
90 }
91 // Get the Heap_lock after the pending_list_lock.
92 Heap_lock->lock();
93 if (lost_race()) {
94 assert(_prologue_succeeded == false, "Initialized in c'tor");
95 Heap_lock->unlock();
96 if (needs_pll()) {
97 release_and_notify_pending_list_lock();
98 }
99 } else {
100 _prologue_succeeded = true;
101 }
102 return _prologue_succeeded;
103 }
105 void VM_CMS_Operation::doit_epilogue() {
106 assert(Thread::current()->is_ConcurrentGC_thread(), "just checking");
107 assert(!CMSCollector::foregroundGCShouldWait(), "Possible deadlock");
108 assert(!ConcurrentMarkSweepThread::cms_thread_has_cms_token(),
109 "Possible deadlock");
111 // Release the Heap_lock first.
112 Heap_lock->unlock();
113 if (needs_pll()) {
114 release_and_notify_pending_list_lock();
115 }
116 }
118 //////////////////////////////////////////////////////////
119 // Methods in class VM_CMS_Initial_Mark
120 //////////////////////////////////////////////////////////
121 void VM_CMS_Initial_Mark::doit() {
122 if (lost_race()) {
123 // Nothing to do.
124 return;
125 }
126 HS_DTRACE_PROBE(hs_private, cms__initmark__begin);
128 GenCollectedHeap* gch = GenCollectedHeap::heap();
129 GCCauseSetter gccs(gch, GCCause::_cms_initial_mark);
131 VM_CMS_Operation::verify_before_gc();
133 IsGCActiveMark x; // stop-world GC active
134 _collector->do_CMS_operation(CMSCollector::CMS_op_checkpointRootsInitial);
136 VM_CMS_Operation::verify_after_gc();
137 HS_DTRACE_PROBE(hs_private, cms__initmark__end);
138 }
140 //////////////////////////////////////////////////////////
141 // Methods in class VM_CMS_Final_Remark_Operation
142 //////////////////////////////////////////////////////////
143 void VM_CMS_Final_Remark::doit() {
144 if (lost_race()) {
145 // Nothing to do.
146 return;
147 }
148 HS_DTRACE_PROBE(hs_private, cms__remark__begin);
150 GenCollectedHeap* gch = GenCollectedHeap::heap();
151 GCCauseSetter gccs(gch, GCCause::_cms_final_remark);
153 VM_CMS_Operation::verify_before_gc();
155 IsGCActiveMark x; // stop-world GC active
156 _collector->do_CMS_operation(CMSCollector::CMS_op_checkpointRootsFinal);
158 VM_CMS_Operation::verify_after_gc();
159 HS_DTRACE_PROBE(hs_private, cms__remark__end);
160 }
162 // VM operation to invoke a concurrent collection of a
163 // GenCollectedHeap heap.
164 void VM_GenCollectFullConcurrent::doit() {
165 assert(Thread::current()->is_VM_thread(), "Should be VM thread");
167 GenCollectedHeap* gch = GenCollectedHeap::heap();
168 if (_gc_count_before == gch->total_collections()) {
169 // The "full" of do_full_collection call below "forces"
170 // a collection; the second arg, 0, below ensures that
171 // only the young gen is collected. XXX In the future,
172 // we'll probably need to have something in this interface
173 // to say do this only if we are sure we will not bail
174 // out to a full collection in this attempt, but that's
175 // for the future.
176 assert(SafepointSynchronize::is_at_safepoint(),
177 "We can only be executing this arm of if at a safepoint");
178 GCCauseSetter gccs(gch, _gc_cause);
179 gch->do_full_collection(gch->must_clear_all_soft_refs(),
180 0 /* collect only youngest gen */);
181 } // Else no need for a foreground young gc
182 assert((_gc_count_before < gch->total_collections()) ||
183 (GC_locker::is_active() /* gc may have been skipped */
184 && (_gc_count_before == gch->total_collections())),
185 "total_collections() should be monotonically increasing");
187 MutexLockerEx x(FullGCCount_lock, Mutex::_no_safepoint_check_flag);
188 if (gch->total_full_collections() == _full_gc_count_before) {
189 // Disable iCMS until the full collection is done.
190 CMSCollector::disable_icms();
191 // In case CMS thread was in icms_wait(), wake it up.
192 CMSCollector::start_icms();
193 // Nudge the CMS thread to start a concurrent collection
194 CMSCollector::request_full_gc(_full_gc_count_before);
195 } else {
196 FullGCCount_lock->notify_all(); // Inform the Java thread its work is done
197 }
198 }
200 bool VM_GenCollectFullConcurrent::evaluate_at_safepoint() const {
201 Thread* thr = Thread::current();
202 assert(thr != NULL, "Unexpected tid");
203 if (!thr->is_Java_thread()) {
204 assert(thr->is_VM_thread(), "Expected to be evaluated by VM thread");
205 GenCollectedHeap* gch = GenCollectedHeap::heap();
206 if (_gc_count_before != gch->total_collections()) {
207 // No need to do a young gc, we'll just nudge the CMS thread
208 // in the doit() method above, to be executed soon.
209 assert(_gc_count_before < gch->total_collections(),
210 "total_collections() should be monotnically increasing");
211 return false; // no need for foreground young gc
212 }
213 }
214 return true; // may still need foreground young gc
215 }
218 void VM_GenCollectFullConcurrent::doit_epilogue() {
219 Thread* thr = Thread::current();
220 assert(thr->is_Java_thread(), "just checking");
221 JavaThread* jt = (JavaThread*)thr;
222 // Release the Heap_lock first.
223 Heap_lock->unlock();
224 release_and_notify_pending_list_lock();
226 // It is fine to test whether completed collections has
227 // exceeded our request count without locking because
228 // the completion count is monotonically increasing;
229 // this will break for very long-running apps when the
230 // count overflows and wraps around. XXX fix me !!!
231 // e.g. at the rate of 1 full gc per ms, this could
232 // overflow in about 1000 years.
233 GenCollectedHeap* gch = GenCollectedHeap::heap();
234 if (gch->total_full_collections_completed() <= _full_gc_count_before) {
235 // Now, wait for witnessing concurrent gc cycle to complete,
236 // but do so in native mode, because we want to lock the
237 // FullGCEvent_lock, which may be needed by the VM thread
238 // or by the CMS thread, so we do not want to be suspended
239 // while holding that lock.
240 ThreadToNativeFromVM native(jt);
241 MutexLockerEx ml(FullGCCount_lock, Mutex::_no_safepoint_check_flag);
242 // Either a concurrent or a stop-world full gc is sufficient
243 // witness to our request.
244 while (gch->total_full_collections_completed() <= _full_gc_count_before) {
245 FullGCCount_lock->wait(Mutex::_no_safepoint_check_flag);
246 }
247 }
248 // Enable iCMS back.
249 CMSCollector::enable_icms();
250 }