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 30 namespace art { 31 namespace gc { 32 namespace collector { 33 34 Iteration::Iteration() 35 : duration_ns_(0), timings_("GC iteration timing logger", true, VLOG_IS_ON(heap)) { 36 Reset(kGcCauseBackground, false); // Reset to some place holder values. 37 } 38 39 void Iteration::Reset(GcCause gc_cause, bool clear_soft_references) { 40 timings_.Reset(); 41 pause_times_.clear(); 42 duration_ns_ = 0; 43 clear_soft_references_ = clear_soft_references; 44 gc_cause_ = gc_cause; 45 freed_ = ObjectBytePair(); 46 freed_los_ = ObjectBytePair(); 47 } 48 49 uint64_t Iteration::GetEstimatedThroughput() const { 50 // Add 1ms to prevent possible division by 0. 51 return (static_cast<uint64_t>(freed_.bytes) * 1000) / (NsToMs(GetDurationNs()) + 1); 52 } 53 54 GarbageCollector::GarbageCollector(Heap* heap, const std::string& name) 55 : heap_(heap), 56 name_(name), 57 pause_histogram_((name_ + " paused").c_str(), kPauseBucketSize, kPauseBucketCount), 58 cumulative_timings_(name) { 59 ResetCumulativeStatistics(); 60 } 61 62 void GarbageCollector::RegisterPause(uint64_t nano_length) { 63 GetCurrentIteration()->pause_times_.push_back(nano_length); 64 } 65 66 void GarbageCollector::ResetCumulativeStatistics() { 67 cumulative_timings_.Reset(); 68 pause_histogram_.Reset(); 69 total_time_ns_ = 0; 70 total_freed_objects_ = 0; 71 total_freed_bytes_ = 0; 72 } 73 74 void GarbageCollector::Run(GcCause gc_cause, bool clear_soft_references) { 75 ATRACE_BEGIN(StringPrintf("%s %s GC", PrettyCause(gc_cause), GetName()).c_str()); 76 Thread* self = Thread::Current(); 77 uint64_t start_time = NanoTime(); 78 Iteration* current_iteration = GetCurrentIteration(); 79 current_iteration->Reset(gc_cause, clear_soft_references); 80 RunPhases(); // Run all the GC phases. 81 // Add the current timings to the cumulative timings. 82 cumulative_timings_.AddLogger(*GetTimings()); 83 // Update cumulative statistics with how many bytes the GC iteration freed. 84 total_freed_objects_ += current_iteration->GetFreedObjects() + 85 current_iteration->GetFreedLargeObjects(); 86 total_freed_bytes_ += current_iteration->GetFreedBytes() + 87 current_iteration->GetFreedLargeObjectBytes(); 88 uint64_t end_time = NanoTime(); 89 current_iteration->SetDurationNs(end_time - start_time); 90 if (Locks::mutator_lock_->IsExclusiveHeld(self)) { 91 // The entire GC was paused, clear the fake pauses which might be in the pause times and add 92 // the whole GC duration. 93 current_iteration->pause_times_.clear(); 94 RegisterPause(current_iteration->GetDurationNs()); 95 } 96 total_time_ns_ += current_iteration->GetDurationNs(); 97 for (uint64_t pause_time : current_iteration->GetPauseTimes()) { 98 pause_histogram_.AddValue(pause_time / 1000); 99 } 100 ATRACE_END(); 101 } 102 103 void GarbageCollector::SwapBitmaps() { 104 TimingLogger::ScopedTiming t(__FUNCTION__, GetTimings()); 105 // Swap the live and mark bitmaps for each alloc space. This is needed since sweep re-swaps 106 // these bitmaps. The bitmap swapping is an optimization so that we do not need to clear the live 107 // bits of dead objects in the live bitmap. 108 const GcType gc_type = GetGcType(); 109 for (const auto& space : GetHeap()->GetContinuousSpaces()) { 110 // We never allocate into zygote spaces. 111 if (space->GetGcRetentionPolicy() == space::kGcRetentionPolicyAlwaysCollect || 112 (gc_type == kGcTypeFull && 113 space->GetGcRetentionPolicy() == space::kGcRetentionPolicyFullCollect)) { 114 accounting::ContinuousSpaceBitmap* live_bitmap = space->GetLiveBitmap(); 115 accounting::ContinuousSpaceBitmap* mark_bitmap = space->GetMarkBitmap(); 116 if (live_bitmap != nullptr && live_bitmap != mark_bitmap) { 117 heap_->GetLiveBitmap()->ReplaceBitmap(live_bitmap, mark_bitmap); 118 heap_->GetMarkBitmap()->ReplaceBitmap(mark_bitmap, live_bitmap); 119 CHECK(space->IsContinuousMemMapAllocSpace()); 120 space->AsContinuousMemMapAllocSpace()->SwapBitmaps(); 121 } 122 } 123 } 124 for (const auto& disc_space : GetHeap()->GetDiscontinuousSpaces()) { 125 space::LargeObjectSpace* space = disc_space->AsLargeObjectSpace(); 126 accounting::LargeObjectBitmap* live_set = space->GetLiveBitmap(); 127 accounting::LargeObjectBitmap* mark_set = space->GetMarkBitmap(); 128 heap_->GetLiveBitmap()->ReplaceLargeObjectBitmap(live_set, mark_set); 129 heap_->GetMarkBitmap()->ReplaceLargeObjectBitmap(mark_set, live_set); 130 space->SwapBitmaps(); 131 } 132 } 133 134 uint64_t GarbageCollector::GetEstimatedMeanThroughput() const { 135 // Add 1ms to prevent possible division by 0. 136 return (total_freed_bytes_ * 1000) / (NsToMs(GetCumulativeTimings().GetTotalNs()) + 1); 137 } 138 139 void GarbageCollector::ResetMeasurements() { 140 cumulative_timings_.Reset(); 141 pause_histogram_.Reset(); 142 total_time_ns_ = 0; 143 total_freed_objects_ = 0; 144 total_freed_bytes_ = 0; 145 } 146 147 GarbageCollector::ScopedPause::ScopedPause(GarbageCollector* collector) 148 : start_time_(NanoTime()), collector_(collector) { 149 Runtime::Current()->GetThreadList()->SuspendAll(); 150 } 151 152 GarbageCollector::ScopedPause::~ScopedPause() { 153 collector_->RegisterPause(NanoTime() - start_time_); 154 Runtime::Current()->GetThreadList()->ResumeAll(); 155 } 156 157 // Returns the current GC iteration and assocated info. 158 Iteration* GarbageCollector::GetCurrentIteration() { 159 return heap_->GetCurrentGcIteration(); 160 } 161 const Iteration* GarbageCollector::GetCurrentIteration() const { 162 return heap_->GetCurrentGcIteration(); 163 } 164 165 void GarbageCollector::RecordFree(const ObjectBytePair& freed) { 166 GetCurrentIteration()->freed_.Add(freed); 167 heap_->RecordFree(freed.objects, freed.bytes); 168 } 169 void GarbageCollector::RecordFreeLOS(const ObjectBytePair& freed) { 170 GetCurrentIteration()->freed_los_.Add(freed); 171 heap_->RecordFree(freed.objects, freed.bytes); 172 } 173 174 } // namespace collector 175 } // namespace gc 176 } // namespace art 177