GarbageCollector是虚基类,它是ART中垃圾回收器的代表。GC工作就是从Garbage-Collector的Run函数开始的。
class GarbageCollector : public RootVisitor, public IsMarkedVisitor, public MarkObjectVisitor {
}
(1) GC的具体工作则由其子类实现的RunPhases函数来处理。
(2) 计算本次GC所用时间
void GarbageCollector::Run(GcCause gc_cause, bool clear_soft_references) {
ScopedTrace trace(android::base::StringPrintf("%s %s GC", PrettyCause(gc_cause), GetName()));
Thread* self = Thread::Current();
Runtime* runtime = Runtime::Current();
uint64_t start_time = NanoTime();
uint64_t thread_cpu_start_time = ThreadCpuNanoTime();
GetHeap()->CalculatePreGcWeightedAllocatedBytes();
Iteration* current_iteration = GetCurrentIteration();
current_iteration->Reset(gc_cause, clear_soft_references);
// Note transaction mode is single-threaded and there's no asynchronous GC and this flag doesn't
// change in the middle of a GC.
is_transaction_active_ = runtime->IsActiveTransaction();
//(1)
RunPhases(); // Run all the GC phases.
GetHeap()->CalculatePostGcWeightedAllocatedBytes();
// Add the current timings to the cumulative timings.
cumulative_timings_.AddLogger(*GetTimings());
// Update cumulative statistics with how many bytes the GC iteration freed.
total_freed_objects_ += current_iteration->GetFreedObjects() +
current_iteration->GetFreedLargeObjects();
total_scanned_bytes_ += current_iteration->GetScannedBytes();
int64_t freed_bytes = current_iteration->GetFreedBytes() +
current_iteration->GetFreedLargeObjectBytes();
total_freed_bytes_ += freed_bytes;
// Rounding negative freed bytes to 0 as we are not interested in such corner cases.
freed_bytes_histogram_.AddValue(std::max<int64_t>(freed_bytes / KB, 0));
uint64_t end_time = NanoTime();
uint64_t thread_cpu_end_time = ThreadCpuNanoTime();
total_thread_cpu_time_ns_ += thread_cpu_end_time - thread_cpu_start_time;
//(2)
uint64_t duration_ns = end_time - start_time;
current_iteration->SetDurationNs(duration_ns);
if (Locks::mutator_lock_->IsExclusiveHeld(self)) {
// The entire GC was paused, clear the fake pauses which might be in the pause times and add
// the whole GC duration.
current_iteration->pause_times_.clear();
RegisterPause(duration_ns);
}
total_time_ns_ += duration_ns;
uint64_t total_pause_time = 0;
for (uint64_t pause_time : current_iteration->GetPauseTimes()) {
MutexLock mu(self, pause_histogram_lock_);
pause_histogram_.AdjustAndAddValue(pause_time);
total_pause_time += pause_time;
}
metrics::ArtMetrics* metrics = runtime->GetMetrics();
// Report STW pause time in microseconds.
metrics->WorldStopTimeDuringGCAvg()->Add(total_pause_time / 1'000);
// Report total collection time of all GCs put together.
metrics->TotalGcCollectionTime()->Add(NsToMs(duration_ns));
if (are_metrics_initialized_) {
metrics_gc_count_->Add(1);
// Report GC time in milliseconds.
gc_time_histogram_->Add(NsToMs(duration_ns));
// Throughput in bytes/s. Add 1us to prevent possible division by 0.
uint64_t throughput = (current_iteration->GetScannedBytes() * 1'000'000)
/ (NsToUs(duration_ns) + 1);
// Report in MB/s.
throughput /= MB;
gc_tracing_throughput_hist_->Add(throughput);
gc_tracing_throughput_avg_->Add(throughput);
// Report GC throughput in MB/s.
throughput = current_iteration->GetEstimatedThroughput() / MB;
gc_throughput_histogram_->Add(throughput);
gc_throughput_avg_->Add(throughput);
}
is_transaction_active_ = false;
}