garbage_collector.cc revision 6f365cc033654a5a3b45eaa1379d4b5f156b0cee
1/* 2 * Copyright (C) 2012 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17#include <stdio.h> 18 19#include "garbage_collector.h" 20 21#include "base/histogram-inl.h" 22#include "base/logging.h" 23#include "base/mutex-inl.h" 24#include "gc/accounting/heap_bitmap.h" 25#include "gc/space/large_object_space.h" 26#include "gc/space/space-inl.h" 27#include "thread-inl.h" 28#include "thread_list.h" 29 30namespace art { 31namespace gc { 32namespace collector { 33 34GarbageCollector::GarbageCollector(Heap* heap, const std::string& name) 35 : heap_(heap), 36 name_(name), 37 gc_cause_(kGcCauseForAlloc), 38 clear_soft_references_(false), 39 duration_ns_(0), 40 timings_(name_.c_str(), true, VLOG_IS_ON(heap)), 41 pause_histogram_((name_ + " paused").c_str(), kPauseBucketSize, kPauseBucketCount), 42 cumulative_timings_(name) { 43 ResetCumulativeStatistics(); 44} 45 46void GarbageCollector::RegisterPause(uint64_t nano_length) { 47 pause_times_.push_back(nano_length); 48} 49 50void GarbageCollector::ResetCumulativeStatistics() { 51 cumulative_timings_.Reset(); 52 pause_histogram_.Reset(); 53 total_time_ns_ = 0; 54 total_freed_objects_ = 0; 55 total_freed_bytes_ = 0; 56} 57 58void GarbageCollector::Run(GcCause gc_cause, bool clear_soft_references) { 59 Thread* self = Thread::Current(); 60 uint64_t start_time = NanoTime(); 61 timings_.Reset(); 62 pause_times_.clear(); 63 duration_ns_ = 0; 64 clear_soft_references_ = clear_soft_references; 65 gc_cause_ = gc_cause; 66 // Reset stats. 67 freed_bytes_ = 0; 68 freed_large_object_bytes_ = 0; 69 freed_objects_ = 0; 70 freed_large_objects_ = 0; 71 RunPhases(); // Run all the GC phases. 72 // Add the current timings to the cumulative timings. 73 cumulative_timings_.AddLogger(timings_); 74 // Update cumulative statistics with how many bytes the GC iteration freed. 75 total_freed_objects_ += GetFreedObjects() + GetFreedLargeObjects(); 76 total_freed_bytes_ += GetFreedBytes() + GetFreedLargeObjectBytes(); 77 uint64_t end_time = NanoTime(); 78 duration_ns_ = end_time - start_time; 79 if (Locks::mutator_lock_->IsExclusiveHeld(self)) { 80 // The entire GC was paused, clear the fake pauses which might be in the pause times and add 81 // the whole GC duration. 82 pause_times_.clear(); 83 RegisterPause(duration_ns_); 84 } 85 total_time_ns_ += GetDurationNs(); 86 for (uint64_t pause_time : pause_times_) { 87 pause_histogram_.AddValue(pause_time / 1000); 88 } 89} 90 91void GarbageCollector::SwapBitmaps() { 92 // Swap the live and mark bitmaps for each alloc space. This is needed since sweep re-swaps 93 // these bitmaps. The bitmap swapping is an optimization so that we do not need to clear the live 94 // bits of dead objects in the live bitmap. 95 const GcType gc_type = GetGcType(); 96 for (const auto& space : GetHeap()->GetContinuousSpaces()) { 97 // We never allocate into zygote spaces. 98 if (space->GetGcRetentionPolicy() == space::kGcRetentionPolicyAlwaysCollect || 99 (gc_type == kGcTypeFull && 100 space->GetGcRetentionPolicy() == space::kGcRetentionPolicyFullCollect)) { 101 accounting::ContinuousSpaceBitmap* live_bitmap = space->GetLiveBitmap(); 102 accounting::ContinuousSpaceBitmap* mark_bitmap = space->GetMarkBitmap(); 103 if (live_bitmap != nullptr && live_bitmap != mark_bitmap) { 104 heap_->GetLiveBitmap()->ReplaceBitmap(live_bitmap, mark_bitmap); 105 heap_->GetMarkBitmap()->ReplaceBitmap(mark_bitmap, live_bitmap); 106 CHECK(space->IsContinuousMemMapAllocSpace()); 107 space->AsContinuousMemMapAllocSpace()->SwapBitmaps(); 108 } 109 } 110 } 111 for (const auto& disc_space : GetHeap()->GetDiscontinuousSpaces()) { 112 space::LargeObjectSpace* space = disc_space->AsLargeObjectSpace(); 113 accounting::LargeObjectBitmap* live_set = space->GetLiveBitmap(); 114 accounting::LargeObjectBitmap* mark_set = space->GetMarkBitmap(); 115 heap_->GetLiveBitmap()->ReplaceLargeObjectBitmap(live_set, mark_set); 116 heap_->GetMarkBitmap()->ReplaceLargeObjectBitmap(mark_set, live_set); 117 space->SwapBitmaps(); 118 } 119} 120 121uint64_t GarbageCollector::GetEstimatedMeanThroughput() const { 122 // Add 1ms to prevent possible division by 0. 123 return (total_freed_bytes_ * 1000) / (NsToMs(GetCumulativeTimings().GetTotalNs()) + 1); 124} 125 126uint64_t GarbageCollector::GetEstimatedLastIterationThroughput() const { 127 // Add 1ms to prevent possible division by 0. 128 return (static_cast<uint64_t>(freed_bytes_) * 1000) / (NsToMs(GetDurationNs()) + 1); 129} 130 131void GarbageCollector::ResetMeasurements() { 132 cumulative_timings_.Reset(); 133 pause_histogram_.Reset(); 134 total_time_ns_ = 0; 135 total_freed_objects_ = 0; 136 total_freed_bytes_ = 0; 137} 138 139GarbageCollector::ScopedPause::ScopedPause(GarbageCollector* collector) 140 : start_time_(NanoTime()), collector_(collector) { 141 Runtime::Current()->GetThreadList()->SuspendAll(); 142} 143 144GarbageCollector::ScopedPause::~ScopedPause() { 145 collector_->RegisterPause(NanoTime() - start_time_); 146 Runtime::Current()->GetThreadList()->ResumeAll(); 147} 148 149} // namespace collector 150} // namespace gc 151} // namespace art 152