garbage_collector.cc revision 4aeec176eaf11fe03f342aadcbb79142230270ed
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#define ATRACE_TAG ATRACE_TAG_DALVIK
18
19#include <stdio.h>
20#include <cutils/trace.h>
21
22#include "garbage_collector.h"
23
24#include "base/histogram-inl.h"
25#include "base/logging.h"
26#include "base/mutex-inl.h"
27#include "gc/accounting/heap_bitmap.h"
28#include "gc/space/large_object_space.h"
29#include "gc/space/space-inl.h"
30#include "thread-inl.h"
31#include "thread_list.h"
32
33namespace art {
34namespace gc {
35namespace collector {
36
37GarbageCollector::GarbageCollector(Heap* heap, const std::string& name)
38    : heap_(heap),
39      name_(name),
40      gc_cause_(kGcCauseForAlloc),
41      clear_soft_references_(false),
42      duration_ns_(0),
43      timings_(name_.c_str(), true, VLOG_IS_ON(heap)),
44      pause_histogram_((name_ + " paused").c_str(), kPauseBucketSize, kPauseBucketCount),
45      cumulative_timings_(name) {
46  ResetCumulativeStatistics();
47}
48
49void GarbageCollector::HandleDirtyObjectsPhase() {
50  LOG(FATAL) << "Unreachable";
51}
52
53void GarbageCollector::RegisterPause(uint64_t nano_length) {
54  pause_times_.push_back(nano_length);
55}
56
57void GarbageCollector::ResetCumulativeStatistics() {
58  cumulative_timings_.Reset();
59  pause_histogram_.Reset();
60  total_time_ns_ = 0;
61  total_freed_objects_ = 0;
62  total_freed_bytes_ = 0;
63}
64
65void GarbageCollector::Run(GcCause gc_cause, bool clear_soft_references) {
66  ThreadList* thread_list = Runtime::Current()->GetThreadList();
67  Thread* self = Thread::Current();
68  uint64_t start_time = NanoTime();
69  pause_times_.clear();
70  duration_ns_ = 0;
71  clear_soft_references_ = clear_soft_references;
72  gc_cause_ = gc_cause;
73
74  // Reset stats.
75  freed_bytes_ = 0;
76  freed_large_object_bytes_ = 0;
77  freed_objects_ = 0;
78  freed_large_objects_ = 0;
79
80  CollectorType collector_type = GetCollectorType();
81  switch (collector_type) {
82    case kCollectorTypeMS:      // Fall through.
83    case kCollectorTypeSS:      // Fall through.
84    case kCollectorTypeGSS: {
85      InitializePhase();
86      // Pause is the entire length of the GC.
87      uint64_t pause_start = NanoTime();
88      ATRACE_BEGIN("Application threads suspended");
89      // Mutator lock may be already exclusively held when we do garbage collections for changing
90      // the current collector / allocator during process state updates.
91      if (Locks::mutator_lock_->IsExclusiveHeld(self)) {
92        // PreGcRosAllocVerification() is called in Heap::TransitionCollector().
93        RevokeAllThreadLocalBuffers();
94        MarkingPhase();
95        ReclaimPhase();
96        // PostGcRosAllocVerification() is called in Heap::TransitionCollector().
97      } else {
98        ATRACE_BEGIN("Suspending mutator threads");
99        thread_list->SuspendAll();
100        ATRACE_END();
101        GetHeap()->PreGcRosAllocVerification(&timings_);
102        RevokeAllThreadLocalBuffers();
103        MarkingPhase();
104        ReclaimPhase();
105        GetHeap()->PostGcRosAllocVerification(&timings_);
106        ATRACE_BEGIN("Resuming mutator threads");
107        thread_list->ResumeAll();
108        ATRACE_END();
109      }
110      ATRACE_END();
111      RegisterPause(NanoTime() - pause_start);
112      FinishPhase();
113      break;
114    }
115    case kCollectorTypeCMS: {
116      InitializePhase();
117      CHECK(!Locks::mutator_lock_->IsExclusiveHeld(self));
118      {
119        ReaderMutexLock mu(self, *Locks::mutator_lock_);
120        MarkingPhase();
121      }
122      uint64_t pause_start = NanoTime();
123      ATRACE_BEGIN("Suspending mutator threads");
124      thread_list->SuspendAll();
125      ATRACE_END();
126      ATRACE_BEGIN("All mutator threads suspended");
127      GetHeap()->PreGcRosAllocVerification(&timings_);
128      HandleDirtyObjectsPhase();
129      RevokeAllThreadLocalBuffers();
130      GetHeap()->PostGcRosAllocVerification(&timings_);
131      ATRACE_END();
132      uint64_t pause_end = NanoTime();
133      ATRACE_BEGIN("Resuming mutator threads");
134      thread_list->ResumeAll();
135      ATRACE_END();
136      RegisterPause(pause_end - pause_start);
137      {
138        ReaderMutexLock mu(self, *Locks::mutator_lock_);
139        ReclaimPhase();
140      }
141      FinishPhase();
142      break;
143    }
144    default: {
145      LOG(FATAL) << "Unreachable collector type=" << static_cast<size_t>(collector_type);
146      break;
147    }
148  }
149  // Add the current timings to the cumulative timings.
150  cumulative_timings_.AddLogger(timings_);
151  // Update cumulative statistics with how many bytes the GC iteration freed.
152  total_freed_objects_ += GetFreedObjects() + GetFreedLargeObjects();
153  total_freed_bytes_ += GetFreedBytes() + GetFreedLargeObjectBytes();
154  uint64_t end_time = NanoTime();
155  duration_ns_ = end_time - start_time;
156  total_time_ns_ += GetDurationNs();
157  for (uint64_t pause_time : pause_times_) {
158    pause_histogram_.AddValue(pause_time / 1000);
159  }
160}
161
162void GarbageCollector::SwapBitmaps() {
163  // Swap the live and mark bitmaps for each alloc space. This is needed since sweep re-swaps
164  // these bitmaps. The bitmap swapping is an optimization so that we do not need to clear the live
165  // bits of dead objects in the live bitmap.
166  const GcType gc_type = GetGcType();
167  for (const auto& space : GetHeap()->GetContinuousSpaces()) {
168    // We never allocate into zygote spaces.
169    if (space->GetGcRetentionPolicy() == space::kGcRetentionPolicyAlwaysCollect ||
170        (gc_type == kGcTypeFull &&
171         space->GetGcRetentionPolicy() == space::kGcRetentionPolicyFullCollect)) {
172      accounting::SpaceBitmap* live_bitmap = space->GetLiveBitmap();
173      accounting::SpaceBitmap* mark_bitmap = space->GetMarkBitmap();
174      if (live_bitmap != nullptr && live_bitmap != mark_bitmap) {
175        heap_->GetLiveBitmap()->ReplaceBitmap(live_bitmap, mark_bitmap);
176        heap_->GetMarkBitmap()->ReplaceBitmap(mark_bitmap, live_bitmap);
177        CHECK(space->IsContinuousMemMapAllocSpace());
178        space->AsContinuousMemMapAllocSpace()->SwapBitmaps();
179      }
180    }
181  }
182  for (const auto& disc_space : GetHeap()->GetDiscontinuousSpaces()) {
183    space::LargeObjectSpace* space = down_cast<space::LargeObjectSpace*>(disc_space);
184    accounting::ObjectSet* live_set = space->GetLiveObjects();
185    accounting::ObjectSet* mark_set = space->GetMarkObjects();
186    heap_->GetLiveBitmap()->ReplaceObjectSet(live_set, mark_set);
187    heap_->GetMarkBitmap()->ReplaceObjectSet(mark_set, live_set);
188    down_cast<space::LargeObjectSpace*>(space)->SwapBitmaps();
189  }
190}
191
192uint64_t GarbageCollector::GetEstimatedMeanThroughput() const {
193  // Add 1ms to prevent possible division by 0.
194  return (total_freed_bytes_ * 1000) / (NsToMs(GetCumulativeTimings().GetTotalNs()) + 1);
195}
196
197uint64_t GarbageCollector::GetEstimatedLastIterationThroughput() const {
198  // Add 1ms to prevent possible division by 0.
199  return (freed_bytes_ * 1000) / (NsToMs(GetDurationNs()) + 1);
200}
201
202}  // namespace collector
203}  // namespace gc
204}  // namespace art
205