23 */ |
23 */ |
24 |
24 |
25 #include "precompiled.hpp" |
25 #include "precompiled.hpp" |
26 #include "gc/g1/g1CollectedHeap.inline.hpp" |
26 #include "gc/g1/g1CollectedHeap.inline.hpp" |
27 #include "gc/g1/g1CollectionSet.hpp" |
27 #include "gc/g1/g1CollectionSet.hpp" |
|
28 #include "gc/g1/g1ConcurrentMark.inline.hpp" |
|
29 #include "gc/g1/g1ConcurrentMarkThread.inline.hpp" |
28 #include "gc/g1/g1Policy.hpp" |
30 #include "gc/g1/g1Policy.hpp" |
29 #include "gc/g1/g1YoungRemSetSamplingThread.hpp" |
31 #include "gc/g1/g1YoungRemSetSamplingThread.hpp" |
30 #include "gc/g1/heapRegion.inline.hpp" |
32 #include "gc/g1/heapRegion.inline.hpp" |
31 #include "gc/g1/heapRegionRemSet.hpp" |
33 #include "gc/g1/heapRegionRemSet.hpp" |
32 #include "gc/shared/suspendibleThreadSet.hpp" |
34 #include "gc/shared/suspendibleThreadSet.hpp" |
35 G1YoungRemSetSamplingThread::G1YoungRemSetSamplingThread() : |
37 G1YoungRemSetSamplingThread::G1YoungRemSetSamplingThread() : |
36 ConcurrentGCThread(), |
38 ConcurrentGCThread(), |
37 _monitor(Mutex::nonleaf, |
39 _monitor(Mutex::nonleaf, |
38 "G1YoungRemSetSamplingThread monitor", |
40 "G1YoungRemSetSamplingThread monitor", |
39 true, |
41 true, |
40 Monitor::_safepoint_check_never) { |
42 Monitor::_safepoint_check_never), |
|
43 _last_periodic_gc_attempt_s(os::elapsedTime()) { |
41 set_name("G1 Young RemSet Sampling"); |
44 set_name("G1 Young RemSet Sampling"); |
42 create_and_start(); |
45 create_and_start(); |
43 } |
46 } |
44 |
47 |
45 void G1YoungRemSetSamplingThread::sleep_before_next_cycle() { |
48 void G1YoungRemSetSamplingThread::sleep_before_next_cycle() { |
46 MutexLockerEx x(&_monitor, Mutex::_no_safepoint_check_flag); |
49 MutexLockerEx x(&_monitor, Mutex::_no_safepoint_check_flag); |
47 if (!should_terminate()) { |
50 if (!should_terminate()) { |
48 uintx waitms = G1ConcRefinementServiceIntervalMillis; // 300, really should be? |
51 uintx waitms = G1ConcRefinementServiceIntervalMillis; |
49 _monitor.wait(Mutex::_no_safepoint_check_flag, waitms); |
52 _monitor.wait(Mutex::_no_safepoint_check_flag, waitms); |
|
53 } |
|
54 } |
|
55 |
|
56 bool G1YoungRemSetSamplingThread::should_start_periodic_gc() { |
|
57 // If we are currently in a concurrent mark we are going to uncommit memory soon. |
|
58 if (G1CollectedHeap::heap()->concurrent_mark()->cm_thread()->during_cycle()) { |
|
59 log_debug(gc, periodic)("Concurrent cycle in progress. Skipping."); |
|
60 return false; |
|
61 } |
|
62 |
|
63 // Check if enough time has passed since the last GC. |
|
64 uintx time_since_last_gc; |
|
65 if ((G1PeriodicGCInterval == 0) || |
|
66 ((time_since_last_gc = (uintx)Universe::heap()->millis_since_last_gc()) < G1PeriodicGCInterval)) { |
|
67 log_debug(gc, periodic)("Last GC occurred " UINTX_FORMAT "ms before which is below threshold " UINTX_FORMAT "ms. Skipping.", |
|
68 time_since_last_gc, G1PeriodicGCInterval); |
|
69 return false; |
|
70 } |
|
71 |
|
72 // Check if load is lower than max. |
|
73 double recent_load; |
|
74 if ((G1PeriodicGCSystemLoadThreshold > 0) && |
|
75 (os::loadavg(&recent_load, 1) == -1 || recent_load > G1PeriodicGCSystemLoadThreshold)) { |
|
76 log_debug(gc, periodic)("Load %1.2f is higher than threshold " UINTX_FORMAT ". Skipping.", |
|
77 recent_load, G1PeriodicGCSystemLoadThreshold); |
|
78 return false; |
|
79 } |
|
80 |
|
81 return true; |
|
82 } |
|
83 |
|
84 void G1YoungRemSetSamplingThread::check_for_periodic_gc(){ |
|
85 if ((os::elapsedTime() - _last_periodic_gc_attempt_s) > (G1PeriodicGCInterval / 1000.0)) { |
|
86 log_debug(gc, periodic)("Checking for periodic GC."); |
|
87 if (should_start_periodic_gc()) { |
|
88 Universe::heap()->collect(GCCause::_g1_periodic_collection); |
|
89 } |
|
90 _last_periodic_gc_attempt_s = os::elapsedTime(); |
50 } |
91 } |
51 } |
92 } |
52 |
93 |
53 void G1YoungRemSetSamplingThread::run_service() { |
94 void G1YoungRemSetSamplingThread::run_service() { |
54 double vtime_start = os::elapsedVTime(); |
95 double vtime_start = os::elapsedVTime(); |