--- a/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp Tue Sep 20 15:42:17 2016 -0400
+++ b/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp Tue Sep 20 22:38:26 2016 +0000
@@ -2474,8 +2474,16 @@
}
jlong G1CollectedHeap::millis_since_last_gc() {
- // assert(false, "NYI");
- return 0;
+ // See the notes in GenCollectedHeap::millis_since_last_gc()
+ // for more information about the implementation.
+ jlong ret_val = (os::javaTimeNanos() / NANOSECS_PER_MILLISEC) -
+ _g1_policy->collection_pause_end_millis();
+ if (ret_val < 0) {
+ log_warning(gc)("millis_since_last_gc() would return : " JLONG_FORMAT
+ ". returning zero instead.", ret_val);
+ return 0;
+ }
+ return ret_val;
}
void G1CollectedHeap::prepare_for_verify() {
--- a/hotspot/src/share/vm/gc/g1/g1DefaultPolicy.cpp Tue Sep 20 15:42:17 2016 -0400
+++ b/hotspot/src/share/vm/gc/g1/g1DefaultPolicy.cpp Tue Sep 20 22:38:26 2016 +0000
@@ -66,7 +66,8 @@
_phase_times(new G1GCPhaseTimes(ParallelGCThreads)),
_tenuring_threshold(MaxTenuringThreshold),
_max_survivor_regions(0),
- _survivors_age_table(true) { }
+ _survivors_age_table(true),
+ _collection_pause_end_millis(os::javaTimeNanos() / NANOSECS_PER_MILLISEC) { }
G1DefaultPolicy::~G1DefaultPolicy() {
delete _ihop_control;
@@ -575,6 +576,8 @@
record_pause(young_gc_pause_kind(), end_time_sec - pause_time_ms / 1000.0, end_time_sec);
+ _collection_pause_end_millis = os::javaTimeNanos() / NANOSECS_PER_MILLISEC;
+
last_pause_included_initial_mark = collector_state()->during_initial_mark_pause();
if (last_pause_included_initial_mark) {
record_concurrent_mark_init_end(0.0);
--- a/hotspot/src/share/vm/gc/g1/g1DefaultPolicy.hpp Tue Sep 20 15:42:17 2016 -0400
+++ b/hotspot/src/share/vm/gc/g1/g1DefaultPolicy.hpp Tue Sep 20 22:38:26 2016 +0000
@@ -64,6 +64,8 @@
double _full_collection_start_sec;
+ jlong _collection_pause_end_millis;
+
uint _young_list_target_length;
uint _young_list_fixed_length;
@@ -237,6 +239,8 @@
double reclaimable_bytes_perc(size_t reclaimable_bytes) const;
+ jlong collection_pause_end_millis() { return _collection_pause_end_millis; }
+
private:
// Sets up marking if proper conditions are met.
void maybe_start_marking();
--- a/hotspot/src/share/vm/gc/g1/g1Policy.hpp Tue Sep 20 15:42:17 2016 -0400
+++ b/hotspot/src/share/vm/gc/g1/g1Policy.hpp Tue Sep 20 22:38:26 2016 +0000
@@ -119,6 +119,8 @@
virtual void record_full_collection_start() = 0;
virtual void record_full_collection_end() = 0;
+ virtual jlong collection_pause_end_millis() = 0;
+
// Must currently be called while the world is stopped.
virtual void record_concurrent_mark_init_end(double mark_init_elapsed_time_ms) = 0;
--- a/hotspot/src/share/vm/gc/shared/genCollectedHeap.cpp Tue Sep 20 15:42:17 2016 -0400
+++ b/hotspot/src/share/vm/gc/shared/genCollectedHeap.cpp Tue Sep 20 22:38:26 2016 +0000
@@ -1256,21 +1256,20 @@
};
jlong GenCollectedHeap::millis_since_last_gc() {
- // We need a monotonically non-decreasing time in ms but
- // os::javaTimeMillis() does not guarantee monotonicity.
+ // javaTimeNanos() is guaranteed to be monotonically non-decreasing
+ // provided the underlying platform provides such a time source
+ // (and it is bug free). So we still have to guard against getting
+ // back a time later than 'now'.
jlong now = os::javaTimeNanos() / NANOSECS_PER_MILLISEC;
GenTimeOfLastGCClosure tolgc_cl(now);
// iterate over generations getting the oldest
// time that a generation was collected
generation_iterate(&tolgc_cl, false);
- // javaTimeNanos() is guaranteed to be monotonically non-decreasing
- // provided the underlying platform provides such a time source
- // (and it is bug free). So we still have to guard against getting
- // back a time later than 'now'.
jlong retVal = now - tolgc_cl.time();
if (retVal < 0) {
- NOT_PRODUCT(log_warning(gc)("time warp: " JLONG_FORMAT, retVal);)
+ log_warning(gc)("millis_since_last_gc() would return : " JLONG_FORMAT
+ ". returning zero instead.", retVal);
return 0;
}
return retVal;