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