Make waiting for blocking GC more intuitive
Now tells what GC cause blocked on what other GC cause.
Example output:
WaitForGcToComplete blocked HeapTrim on ProfileSaver for 396.361ms
Bug: 62941975
Test: test-art-host
(cherry picked from commit 87a619f43d4cb79b8723b42dc53cb10f7577f1de)
Change-Id: I1e3a35244db16974487dd8b82baae81669ae9aee
diff --git a/runtime/gc/heap.cc b/runtime/gc/heap.cc
index d944ce4..880b2d4 100644
--- a/runtime/gc/heap.cc
+++ b/runtime/gc/heap.cc
@@ -214,6 +214,7 @@
disable_thread_flip_count_(0),
thread_flip_running_(false),
collector_type_running_(kCollectorTypeNone),
+ last_gc_cause_(kGcCauseNone),
thread_running_gc_(nullptr),
last_gc_type_(collector::kGcTypeNone),
next_gc_type_(collector::kGcTypePartial),
@@ -1458,6 +1459,7 @@
// Ensure there is only one GC at a time.
WaitForGcToCompleteLocked(cause, self);
collector_type_running_ = collector_type;
+ last_gc_cause_ = cause;
thread_running_gc_ = self;
}
@@ -3537,6 +3539,7 @@
collector::GcType Heap::WaitForGcToCompleteLocked(GcCause cause, Thread* self) {
collector::GcType last_gc_type = collector::kGcTypeNone;
+ GcCause last_gc_cause = kGcCauseNone;
uint64_t wait_start = NanoTime();
while (collector_type_running_ != kCollectorTypeNone) {
if (self != task_processor_->GetRunningThread()) {
@@ -3551,12 +3554,13 @@
// We must wait, change thread state then sleep on gc_complete_cond_;
gc_complete_cond_->Wait(self);
last_gc_type = last_gc_type_;
+ last_gc_cause = last_gc_cause_;
}
uint64_t wait_time = NanoTime() - wait_start;
total_wait_time_ += wait_time;
if (wait_time > long_pause_log_threshold_) {
- LOG(INFO) << "WaitForGcToComplete blocked for " << PrettyDuration(wait_time)
- << " for cause " << cause;
+ LOG(INFO) << "WaitForGcToComplete blocked " << cause << " on " << last_gc_cause << " for "
+ << PrettyDuration(wait_time);
}
if (self != task_processor_->GetRunningThread()) {
// The current thread is about to run a collection. If the thread