Reducing CPU impact of non-monotonic clocks on Gc.
Adding a ceiling for the Gc's histogram's num_of_windows count, ensuring the
number of data points to insert does not become extremely large when time
changes unexpectedly. This may happen when the time source is not monotonic.
Bug: 123365804
Test: confirmed the fix behaves as intended on a system with an erratic clock
Change-Id: Idd3560204d3392fe247b65d383c41de2eaf8d35c
Signed-off-by: Vincent Palomares <paillon@google.com>
diff --git a/runtime/gc/heap.cc b/runtime/gc/heap.cc
index 5f62d75..8020f86 100644
--- a/runtime/gc/heap.cc
+++ b/runtime/gc/heap.cc
@@ -2878,6 +2878,15 @@
DCHECK_GE(now, last_update_time_gc_count_rate_histograms_);
uint64_t time_since_last_update = now - last_update_time_gc_count_rate_histograms_;
uint64_t num_of_windows = time_since_last_update / kGcCountRateHistogramWindowDuration;
+
+ // The computed number of windows can be incoherently high if NanoTime() is not monotonic.
+ // Setting a limit on its maximum value reduces the impact on CPU time in such cases.
+ if (num_of_windows > kGcCountRateHistogramMaxNumMissedWindows) {
+ LOG(WARNING) << "Reducing the number of considered missed Gc histogram windows from "
+ << num_of_windows << " to " << kGcCountRateHistogramMaxNumMissedWindows;
+ num_of_windows = kGcCountRateHistogramMaxNumMissedWindows;
+ }
+
if (time_since_last_update >= kGcCountRateHistogramWindowDuration) {
// Record the first window.
gc_count_rate_histogram_.AddValue(gc_count_last_window_ - 1); // Exclude the current run.
diff --git a/runtime/gc/heap.h b/runtime/gc/heap.h
index 4c5d896..6bdba12 100644
--- a/runtime/gc/heap.h
+++ b/runtime/gc/heap.h
@@ -1495,6 +1495,8 @@
uint64_t blocking_gc_time_;
// The duration of the window for the GC count rate histograms.
static constexpr uint64_t kGcCountRateHistogramWindowDuration = MsToNs(10 * 1000); // 10s.
+ // Maximum number of missed histogram windows for which statistics will be collected.
+ static constexpr uint64_t kGcCountRateHistogramMaxNumMissedWindows = 100;
// The last time when the GC count rate histograms were updated.
// This is rounded by kGcCountRateHistogramWindowDuration (a multiple of 10s).
uint64_t last_update_time_gc_count_rate_histograms_;