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 */
24
25 #include "precompiled.hpp"
26 #include "gc/g1/g1CollectedHeap.inline.hpp"
27 #include "gc/g1/g1CollectionSet.hpp"
28 #include "gc/g1/g1ConcurrentMark.inline.hpp"
29 #include "gc/g1/g1ConcurrentMarkThread.inline.hpp"
30 #include "gc/g1/g1Policy.hpp"
31 #include "gc/g1/g1YoungRemSetSamplingThread.hpp"
32 #include "gc/g1/heapRegion.inline.hpp"
33 #include "gc/g1/heapRegionRemSet.hpp"
34 #include "gc/shared/suspendibleThreadSet.hpp"
35 #include "memory/universe.hpp"
36 #include "runtime/mutexLocker.hpp"
37
38 G1YoungRemSetSamplingThread::G1YoungRemSetSamplingThread() :
39 ConcurrentGCThread(),
40 _monitor(Mutex::nonleaf,
41 "G1YoungRemSetSamplingThread monitor",
42 true,
43 Monitor::_safepoint_check_never),
44 _last_periodic_gc_attempt_s(os::elapsedTime()),
45 _vtime_accum(0) {
46 set_name("G1 Young RemSet Sampling");
47 create_and_start();
48 }
49
50 void G1YoungRemSetSamplingThread::sleep_before_next_cycle() {
51 MonitorLocker ml(&_monitor, Mutex::_no_safepoint_check_flag);
52 if (!should_terminate()) {
53 uintx waitms = G1ConcRefinementServiceIntervalMillis;
54 ml.wait(waitms);
55 }
56 }
57
58 bool G1YoungRemSetSamplingThread::should_start_periodic_gc() {
59 G1CollectedHeap* g1h = G1CollectedHeap::heap();
60 // If we are currently in a concurrent mark we are going to uncommit memory soon.
61 if (g1h->concurrent_mark()->cm_thread()->during_cycle()) {
62 log_debug(gc, periodic)("Concurrent cycle in progress. Skipping.");
63 return false;
64 }
65
66 // Check if enough time has passed since the last GC.
67 uintx time_since_last_gc = (uintx)g1h->time_since_last_collection().milliseconds();
68 if ((time_since_last_gc < G1PeriodicGCInterval)) {
69 log_debug(gc, periodic)("Last GC occurred " UINTX_FORMAT "ms before which is below threshold " UINTX_FORMAT "ms. Skipping.",
70 time_since_last_gc, G1PeriodicGCInterval);
71 return false;
72 }
73
74 // Check if load is lower than max.
75 double recent_load;
76 if ((G1PeriodicGCSystemLoadThreshold > 0.0f) &&
77 (os::loadavg(&recent_load, 1) == -1 || recent_load > G1PeriodicGCSystemLoadThreshold)) {
78 log_debug(gc, periodic)("Load %1.2f is higher than threshold %1.2f. Skipping.",
79 recent_load, G1PeriodicGCSystemLoadThreshold);
80 return false;
81 }
82
83 return true;
84 }
85
86 void G1YoungRemSetSamplingThread::check_for_periodic_gc(){
87 // If disabled, just return.
88 if (G1PeriodicGCInterval == 0) {
89 return;
90 }
91 if ((os::elapsedTime() - _last_periodic_gc_attempt_s) > (G1PeriodicGCInterval / 1000.0)) {
92 log_debug(gc, periodic)("Checking for periodic GC.");
93 if (should_start_periodic_gc()) {
94 if (!G1CollectedHeap::heap()->try_collect(GCCause::_g1_periodic_collection)) {
95 log_debug(gc, periodic)("GC request denied. Skipping.");
96 }
97 }
98 _last_periodic_gc_attempt_s = os::elapsedTime();
99 }
100 }
101
102 void G1YoungRemSetSamplingThread::run_service() {
103 double vtime_start = os::elapsedVTime();
104
105 while (!should_terminate()) {
106 sample_young_list_rs_length();
107
108 if (os::supports_vtime()) {
109 _vtime_accum = (os::elapsedVTime() - vtime_start);
110 } else {
111 _vtime_accum = 0.0;
112 }
113
114 check_for_periodic_gc();
115
116 sleep_before_next_cycle();
117 }
118 }
119
120 void G1YoungRemSetSamplingThread::stop_service() {
121 MutexLocker x(&_monitor, Mutex::_no_safepoint_check_flag);
122 _monitor.notify();
123 }
124
125 class G1YoungRemSetSamplingClosure : public HeapRegionClosure {
126 SuspendibleThreadSetJoiner* _sts;
127 size_t _regions_visited;
128 size_t _sampled_rs_length;
129 public:
130 G1YoungRemSetSamplingClosure(SuspendibleThreadSetJoiner* sts) :
131 HeapRegionClosure(), _sts(sts), _regions_visited(0), _sampled_rs_length(0) { }
132
133 virtual bool do_heap_region(HeapRegion* r) {
134 size_t rs_length = r->rem_set()->occupied();
135 _sampled_rs_length += rs_length;
136
137 // Update the collection set policy information for this region
138 G1CollectedHeap::heap()->collection_set()->update_young_region_prediction(r, rs_length);
139
140 _regions_visited++;
141
142 if (_regions_visited == 10) {
143 if (_sts->should_yield()) {
144 _sts->yield();
145 // A gc may have occurred and our sampling data is stale and further
146 // traversal of the collection set is unsafe
147 return true;
148 }
149 _regions_visited = 0;
150 }
151 return false;
152 }
153
154 size_t sampled_rs_length() const { return _sampled_rs_length; }
155 };
156
157 void G1YoungRemSetSamplingThread::sample_young_list_rs_length() {
158 SuspendibleThreadSetJoiner sts;
159 G1CollectedHeap* g1h = G1CollectedHeap::heap();
160 G1Policy* policy = g1h->policy();
161
162 if (policy->use_adaptive_young_list_length()) {
163 G1YoungRemSetSamplingClosure cl(&sts);
164
165 G1CollectionSet* g1cs = g1h->collection_set();
166 g1cs->iterate(&cl);
167
168 if (cl.is_complete()) {
169 policy->revise_young_list_target_length_if_necessary(cl.sampled_rs_length());
170 }
171 }
172 }
|
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 */
24
25 #include "precompiled.hpp"
26 #include "gc/g1/g1CollectedHeap.inline.hpp"
27 #include "gc/g1/g1CollectionSet.hpp"
28 #include "gc/g1/g1ConcurrentMark.inline.hpp"
29 #include "gc/g1/g1ConcurrentMarkThread.inline.hpp"
30 #include "gc/g1/g1Policy.hpp"
31 #include "gc/g1/g1ServiceThread.hpp"
32 #include "gc/g1/heapRegion.inline.hpp"
33 #include "gc/g1/heapRegionRemSet.hpp"
34 #include "gc/shared/suspendibleThreadSet.hpp"
35 #include "memory/universe.hpp"
36 #include "runtime/mutexLocker.hpp"
37
38 G1ServiceThread::G1ServiceThread() :
39 ConcurrentGCThread(),
40 _monitor(Mutex::nonleaf,
41 "G1ServiceThread monitor",
42 true,
43 Monitor::_safepoint_check_never),
44 _last_periodic_gc_attempt_s(os::elapsedTime()),
45 _vtime_accum(0) {
46 set_name("G1 Service");
47 create_and_start();
48 }
49
50 void G1ServiceThread::sleep_before_next_cycle() {
51 MonitorLocker ml(&_monitor, Mutex::_no_safepoint_check_flag);
52 if (!should_terminate()) {
53 uintx waitms = G1ConcRefinementServiceIntervalMillis;
54 ml.wait(waitms);
55 }
56 }
57
58 bool G1ServiceThread::should_start_periodic_gc() {
59 G1CollectedHeap* g1h = G1CollectedHeap::heap();
60 // If we are currently in a concurrent mark we are going to uncommit memory soon.
61 if (g1h->concurrent_mark()->cm_thread()->during_cycle()) {
62 log_debug(gc, periodic)("Concurrent cycle in progress. Skipping.");
63 return false;
64 }
65
66 // Check if enough time has passed since the last GC.
67 uintx time_since_last_gc = (uintx)g1h->time_since_last_collection().milliseconds();
68 if ((time_since_last_gc < G1PeriodicGCInterval)) {
69 log_debug(gc, periodic)("Last GC occurred " UINTX_FORMAT "ms before which is below threshold " UINTX_FORMAT "ms. Skipping.",
70 time_since_last_gc, G1PeriodicGCInterval);
71 return false;
72 }
73
74 // Check if load is lower than max.
75 double recent_load;
76 if ((G1PeriodicGCSystemLoadThreshold > 0.0f) &&
77 (os::loadavg(&recent_load, 1) == -1 || recent_load > G1PeriodicGCSystemLoadThreshold)) {
78 log_debug(gc, periodic)("Load %1.2f is higher than threshold %1.2f. Skipping.",
79 recent_load, G1PeriodicGCSystemLoadThreshold);
80 return false;
81 }
82
83 return true;
84 }
85
86 void G1ServiceThread::check_for_periodic_gc(){
87 // If disabled, just return.
88 if (G1PeriodicGCInterval == 0) {
89 return;
90 }
91 if ((os::elapsedTime() - _last_periodic_gc_attempt_s) > (G1PeriodicGCInterval / 1000.0)) {
92 log_debug(gc, periodic)("Checking for periodic GC.");
93 if (should_start_periodic_gc()) {
94 if (!G1CollectedHeap::heap()->try_collect(GCCause::_g1_periodic_collection)) {
95 log_debug(gc, periodic)("GC request denied. Skipping.");
96 }
97 }
98 _last_periodic_gc_attempt_s = os::elapsedTime();
99 }
100 }
101
102 void G1ServiceThread::run_service() {
103 double vtime_start = os::elapsedVTime();
104
105 while (!should_terminate()) {
106 sample_young_list_rs_length();
107
108 if (os::supports_vtime()) {
109 _vtime_accum = (os::elapsedVTime() - vtime_start);
110 } else {
111 _vtime_accum = 0.0;
112 }
113
114 check_for_periodic_gc();
115
116 sleep_before_next_cycle();
117 }
118 }
119
120 void G1ServiceThread::stop_service() {
121 MutexLocker x(&_monitor, Mutex::_no_safepoint_check_flag);
122 _monitor.notify();
123 }
124
125 class G1YoungRemSetSamplingClosure : public HeapRegionClosure {
126 SuspendibleThreadSetJoiner* _sts;
127 size_t _regions_visited;
128 size_t _sampled_rs_length;
129 public:
130 G1YoungRemSetSamplingClosure(SuspendibleThreadSetJoiner* sts) :
131 HeapRegionClosure(), _sts(sts), _regions_visited(0), _sampled_rs_length(0) { }
132
133 virtual bool do_heap_region(HeapRegion* r) {
134 size_t rs_length = r->rem_set()->occupied();
135 _sampled_rs_length += rs_length;
136
137 // Update the collection set policy information for this region
138 G1CollectedHeap::heap()->collection_set()->update_young_region_prediction(r, rs_length);
139
140 _regions_visited++;
141
142 if (_regions_visited == 10) {
143 if (_sts->should_yield()) {
144 _sts->yield();
145 // A gc may have occurred and our sampling data is stale and further
146 // traversal of the collection set is unsafe
147 return true;
148 }
149 _regions_visited = 0;
150 }
151 return false;
152 }
153
154 size_t sampled_rs_length() const { return _sampled_rs_length; }
155 };
156
157 void G1ServiceThread::sample_young_list_rs_length() {
158 SuspendibleThreadSetJoiner sts;
159 G1CollectedHeap* g1h = G1CollectedHeap::heap();
160 G1Policy* policy = g1h->policy();
161
162 if (policy->use_adaptive_young_list_length()) {
163 G1YoungRemSetSamplingClosure cl(&sts);
164
165 G1CollectionSet* g1cs = g1h->collection_set();
166 g1cs->iterate(&cl);
167
168 if (cl.is_complete()) {
169 policy->revise_young_list_target_length_if_necessary(cl.sampled_rs_length());
170 }
171 }
172 }
|