1 /*
2 * Copyright (C) 2011 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 <algorithm>
18
19 #include "base/metrics/metrics.h"
20 #include "class_linker-inl.h"
21 #include "common_runtime_test.h"
22 #include "gc/accounting/card_table-inl.h"
23 #include "gc/accounting/space_bitmap-inl.h"
24 #include "handle_scope-inl.h"
25 #include "mirror/class-inl.h"
26 #include "mirror/object-inl.h"
27 #include "mirror/object_array-alloc-inl.h"
28 #include "mirror/object_array-inl.h"
29 #include "scoped_thread_state_change-inl.h"
30
31 namespace art HIDDEN {
32 namespace gc {
33
34 class HeapTest : public CommonRuntimeTest {
35 public:
HeapTest()36 HeapTest() {
37 use_boot_image_ = true; // Make the Runtime creation cheaper.
38 }
39
SetUp()40 void SetUp() override {
41 MemMap::Init();
42 std::string error_msg;
43 // Reserve the preferred address to force the heap to use another one for testing.
44 reserved_ = MemMap::MapAnonymous("ReserveMap",
45 gc::Heap::kPreferredAllocSpaceBegin,
46 16 * KB,
47 PROT_READ,
48 /*low_4gb=*/ true,
49 /*reuse=*/ false,
50 /*reservation=*/ nullptr,
51 &error_msg);
52 // There is no guarantee that reserved_ will be valid (due to ASLR). See b/175018342.
53 CommonRuntimeTest::SetUp();
54 }
55
56 private:
57 MemMap reserved_;
58 };
59
TEST_F(HeapTest,ClearGrowthLimit)60 TEST_F(HeapTest, ClearGrowthLimit) {
61 Heap* heap = Runtime::Current()->GetHeap();
62 int64_t max_memory_before = heap->GetMaxMemory();
63 int64_t total_memory_before = heap->GetTotalMemory();
64 heap->ClearGrowthLimit();
65 int64_t max_memory_after = heap->GetMaxMemory();
66 int64_t total_memory_after = heap->GetTotalMemory();
67 EXPECT_GE(max_memory_after, max_memory_before);
68 EXPECT_GE(total_memory_after, total_memory_before);
69 }
70
TEST_F(HeapTest,GarbageCollectClassLinkerInit)71 TEST_F(HeapTest, GarbageCollectClassLinkerInit) {
72 {
73 ScopedObjectAccess soa(Thread::Current());
74 // garbage is created during ClassLinker::Init
75
76 StackHandleScope<1> hs(soa.Self());
77 Handle<mirror::Class> c(
78 hs.NewHandle(class_linker_->FindSystemClass(soa.Self(), "[Ljava/lang/Object;")));
79 for (size_t i = 0; i < 1024; ++i) {
80 StackHandleScope<1> hs2(soa.Self());
81 Handle<mirror::ObjectArray<mirror::Object>> array(hs2.NewHandle(
82 mirror::ObjectArray<mirror::Object>::Alloc(soa.Self(), c.Get(), 2048)));
83 for (size_t j = 0; j < 2048; ++j) {
84 ObjPtr<mirror::String> string =
85 mirror::String::AllocFromModifiedUtf8(soa.Self(), "hello, world!");
86 // handle scope operator -> deferences the handle scope before running the method.
87 array->Set<false>(j, string);
88 }
89 }
90 }
91 Runtime::Current()->GetHeap()->CollectGarbage(/* clear_soft_references= */ false);
92 }
93
TEST_F(HeapTest,HeapBitmapCapacityTest)94 TEST_F(HeapTest, HeapBitmapCapacityTest) {
95 uint8_t* heap_begin = reinterpret_cast<uint8_t*>(0x1000);
96 const size_t heap_capacity = kObjectAlignment * (sizeof(intptr_t) * 8 + 1);
97 accounting::ContinuousSpaceBitmap bitmap(
98 accounting::ContinuousSpaceBitmap::Create("test bitmap", heap_begin, heap_capacity));
99 mirror::Object* fake_end_of_heap_object =
100 reinterpret_cast<mirror::Object*>(&heap_begin[heap_capacity - kObjectAlignment]);
101 bitmap.Set(fake_end_of_heap_object);
102 }
103
TEST_F(HeapTest,DumpGCPerformanceOnShutdown)104 TEST_F(HeapTest, DumpGCPerformanceOnShutdown) {
105 Runtime::Current()->GetHeap()->CollectGarbage(/* clear_soft_references= */ false);
106 Runtime::Current()->SetDumpGCPerformanceOnShutdown(true);
107 }
108
AnyIsFalse(bool x,bool y)109 bool AnyIsFalse(bool x, bool y) { return !x || !y; }
110
TEST_F(HeapTest,GCMetrics)111 TEST_F(HeapTest, GCMetrics) {
112 // Allocate a few string objects (to be collected), then trigger garbage
113 // collection, and check that GC metrics are updated (where applicable).
114 Heap* heap = Runtime::Current()->GetHeap();
115 {
116 constexpr const size_t kNumObj = 128;
117 ScopedObjectAccess soa(Thread::Current());
118 StackHandleScope<kNumObj> hs(soa.Self());
119 for (size_t i = 0u; i < kNumObj; ++i) {
120 Handle<mirror::String> string [[maybe_unused]] (
121 hs.NewHandle(mirror::String::AllocFromModifiedUtf8(soa.Self(), "test")));
122 }
123 // Do one GC while the temporary objects are reachable, forcing the GC to scan something.
124 // The subsequent GC at line 127 may not scan anything but will certainly free some bytes.
125 // Together the two GCs ensure success of the test.
126 heap->CollectGarbage(/* clear_soft_references= */ false);
127 }
128 heap->CollectGarbage(/* clear_soft_references= */ false);
129
130 // ART Metrics.
131 metrics::ArtMetrics* metrics = Runtime::Current()->GetMetrics();
132 // ART full-heap GC metrics.
133 metrics::MetricsBase<int64_t>* full_gc_collection_time = metrics->FullGcCollectionTime();
134 metrics::MetricsBase<uint64_t>* full_gc_count = metrics->FullGcCount();
135 metrics::MetricsBase<uint64_t>* full_gc_count_delta = metrics->FullGcCountDelta();
136 metrics::MetricsBase<int64_t>* full_gc_throughput = metrics->FullGcThroughput();
137 metrics::MetricsBase<int64_t>* full_gc_tracing_throughput = metrics->FullGcTracingThroughput();
138 metrics::MetricsBase<uint64_t>* full_gc_throughput_avg = metrics->FullGcThroughputAvg();
139 metrics::MetricsBase<uint64_t>* full_gc_tracing_throughput_avg =
140 metrics->FullGcTracingThroughputAvg();
141 metrics::MetricsBase<uint64_t>* full_gc_scanned_bytes = metrics->FullGcScannedBytes();
142 metrics::MetricsBase<uint64_t>* full_gc_scanned_bytes_delta = metrics->FullGcScannedBytesDelta();
143 metrics::MetricsBase<uint64_t>* full_gc_freed_bytes = metrics->FullGcFreedBytes();
144 metrics::MetricsBase<uint64_t>* full_gc_freed_bytes_delta = metrics->FullGcFreedBytesDelta();
145 metrics::MetricsBase<uint64_t>* full_gc_duration = metrics->FullGcDuration();
146 metrics::MetricsBase<uint64_t>* full_gc_duration_delta = metrics->FullGcDurationDelta();
147 // ART young-generation GC metrics.
148 metrics::MetricsBase<int64_t>* young_gc_collection_time = metrics->YoungGcCollectionTime();
149 metrics::MetricsBase<uint64_t>* young_gc_count = metrics->YoungGcCount();
150 metrics::MetricsBase<uint64_t>* young_gc_count_delta = metrics->YoungGcCountDelta();
151 metrics::MetricsBase<int64_t>* young_gc_throughput = metrics->YoungGcThroughput();
152 metrics::MetricsBase<int64_t>* young_gc_tracing_throughput = metrics->YoungGcTracingThroughput();
153 metrics::MetricsBase<uint64_t>* young_gc_throughput_avg = metrics->YoungGcThroughputAvg();
154 metrics::MetricsBase<uint64_t>* young_gc_tracing_throughput_avg =
155 metrics->YoungGcTracingThroughputAvg();
156 metrics::MetricsBase<uint64_t>* young_gc_scanned_bytes = metrics->YoungGcScannedBytes();
157 metrics::MetricsBase<uint64_t>* young_gc_scanned_bytes_delta =
158 metrics->YoungGcScannedBytesDelta();
159 metrics::MetricsBase<uint64_t>* young_gc_freed_bytes = metrics->YoungGcFreedBytes();
160 metrics::MetricsBase<uint64_t>* young_gc_freed_bytes_delta = metrics->YoungGcFreedBytesDelta();
161 metrics::MetricsBase<uint64_t>* young_gc_duration = metrics->YoungGcDuration();
162 metrics::MetricsBase<uint64_t>* young_gc_duration_delta = metrics->YoungGcDurationDelta();
163
164 CollectorType fg_collector_type = heap->GetForegroundCollectorType();
165 if (fg_collector_type == kCollectorTypeCC || fg_collector_type == kCollectorTypeCMC) {
166 // Only the Concurrent Copying and Concurrent Mark-Compact collectors enable
167 // GC metrics at the moment.
168 if (heap->GetUseGenerationalCC()) {
169 // Check that full-heap and/or young-generation GC metrics are non-null
170 // after trigerring the collection.
171 EXPECT_PRED2(
172 AnyIsFalse, full_gc_collection_time->IsNull(), young_gc_collection_time->IsNull());
173 EXPECT_PRED2(AnyIsFalse, full_gc_count->IsNull(), young_gc_count->IsNull());
174 EXPECT_PRED2(AnyIsFalse, full_gc_count_delta->IsNull(), young_gc_count_delta->IsNull());
175 EXPECT_PRED2(AnyIsFalse, full_gc_throughput->IsNull(), young_gc_throughput->IsNull());
176 EXPECT_PRED2(
177 AnyIsFalse, full_gc_tracing_throughput->IsNull(), young_gc_tracing_throughput->IsNull());
178 EXPECT_PRED2(AnyIsFalse, full_gc_throughput_avg->IsNull(), young_gc_throughput_avg->IsNull());
179 EXPECT_PRED2(AnyIsFalse,
180 full_gc_tracing_throughput_avg->IsNull(),
181 young_gc_tracing_throughput_avg->IsNull());
182 EXPECT_PRED2(AnyIsFalse, full_gc_scanned_bytes->IsNull(), young_gc_scanned_bytes->IsNull());
183 EXPECT_PRED2(AnyIsFalse,
184 full_gc_scanned_bytes_delta->IsNull(),
185 young_gc_scanned_bytes_delta->IsNull());
186 EXPECT_PRED2(AnyIsFalse, full_gc_freed_bytes->IsNull(), young_gc_freed_bytes->IsNull());
187 EXPECT_PRED2(
188 AnyIsFalse, full_gc_freed_bytes_delta->IsNull(), young_gc_freed_bytes_delta->IsNull());
189 // We have observed that sometimes the GC duration (both for full-heap and
190 // young-generation collections) is null (b/271112044). Temporarily
191 // suspend the following checks while we investigate.
192 //
193 // TODO(b/271112044): Investigate and adjust these expectations and/or the
194 // corresponding metric logic.
195 #if 0
196 EXPECT_PRED2(AnyIsFalse, full_gc_duration->IsNull(), young_gc_duration->IsNull());
197 EXPECT_PRED2(AnyIsFalse, full_gc_duration_delta->IsNull(), young_gc_duration_delta->IsNull());
198 #endif
199 } else {
200 // Check that only full-heap GC metrics are non-null after trigerring the collection.
201 EXPECT_FALSE(full_gc_collection_time->IsNull());
202 EXPECT_FALSE(full_gc_count->IsNull());
203 EXPECT_FALSE(full_gc_count_delta->IsNull());
204 EXPECT_FALSE(full_gc_throughput->IsNull());
205 EXPECT_FALSE(full_gc_tracing_throughput->IsNull());
206 EXPECT_FALSE(full_gc_throughput_avg->IsNull());
207 EXPECT_FALSE(full_gc_tracing_throughput_avg->IsNull());
208 EXPECT_FALSE(full_gc_scanned_bytes->IsNull());
209 EXPECT_FALSE(full_gc_scanned_bytes_delta->IsNull());
210 EXPECT_FALSE(full_gc_freed_bytes->IsNull());
211 EXPECT_FALSE(full_gc_freed_bytes_delta->IsNull());
212 EXPECT_FALSE(full_gc_duration->IsNull());
213 EXPECT_FALSE(full_gc_duration_delta->IsNull());
214
215 EXPECT_TRUE(young_gc_collection_time->IsNull());
216 EXPECT_TRUE(young_gc_count->IsNull());
217 EXPECT_TRUE(young_gc_count_delta->IsNull());
218 EXPECT_TRUE(young_gc_throughput->IsNull());
219 EXPECT_TRUE(young_gc_tracing_throughput->IsNull());
220 EXPECT_TRUE(young_gc_throughput_avg->IsNull());
221 EXPECT_TRUE(young_gc_tracing_throughput_avg->IsNull());
222 EXPECT_TRUE(young_gc_scanned_bytes->IsNull());
223 EXPECT_TRUE(young_gc_scanned_bytes_delta->IsNull());
224 EXPECT_TRUE(young_gc_freed_bytes->IsNull());
225 EXPECT_TRUE(young_gc_freed_bytes_delta->IsNull());
226 EXPECT_TRUE(young_gc_duration->IsNull());
227 EXPECT_TRUE(young_gc_duration_delta->IsNull());
228 }
229 } else {
230 // Check that all metrics are null after trigerring the collection.
231 EXPECT_TRUE(full_gc_collection_time->IsNull());
232 EXPECT_TRUE(full_gc_count->IsNull());
233 EXPECT_TRUE(full_gc_count_delta->IsNull());
234 EXPECT_TRUE(full_gc_throughput->IsNull());
235 EXPECT_TRUE(full_gc_tracing_throughput->IsNull());
236 EXPECT_TRUE(full_gc_throughput_avg->IsNull());
237 EXPECT_TRUE(full_gc_tracing_throughput_avg->IsNull());
238 EXPECT_TRUE(full_gc_scanned_bytes->IsNull());
239 EXPECT_TRUE(full_gc_scanned_bytes_delta->IsNull());
240 EXPECT_TRUE(full_gc_freed_bytes->IsNull());
241 EXPECT_TRUE(full_gc_freed_bytes_delta->IsNull());
242 EXPECT_TRUE(full_gc_duration->IsNull());
243 EXPECT_TRUE(full_gc_duration_delta->IsNull());
244
245 EXPECT_TRUE(young_gc_collection_time->IsNull());
246 EXPECT_TRUE(young_gc_count->IsNull());
247 EXPECT_TRUE(young_gc_count_delta->IsNull());
248 EXPECT_TRUE(young_gc_throughput->IsNull());
249 EXPECT_TRUE(young_gc_tracing_throughput->IsNull());
250 EXPECT_TRUE(young_gc_throughput_avg->IsNull());
251 EXPECT_TRUE(young_gc_tracing_throughput_avg->IsNull());
252 EXPECT_TRUE(young_gc_scanned_bytes->IsNull());
253 EXPECT_TRUE(young_gc_scanned_bytes_delta->IsNull());
254 EXPECT_TRUE(young_gc_freed_bytes->IsNull());
255 EXPECT_TRUE(young_gc_freed_bytes_delta->IsNull());
256 EXPECT_TRUE(young_gc_duration->IsNull());
257 EXPECT_TRUE(young_gc_duration_delta->IsNull());
258 }
259 }
260
261 class ZygoteHeapTest : public CommonRuntimeTest {
262 public:
ZygoteHeapTest()263 ZygoteHeapTest() {
264 use_boot_image_ = true; // Make the Runtime creation cheaper.
265 }
266
SetUpRuntimeOptions(RuntimeOptions * options)267 void SetUpRuntimeOptions(RuntimeOptions* options) override {
268 CommonRuntimeTest::SetUpRuntimeOptions(options);
269 options->push_back(std::make_pair("-Xzygote", nullptr));
270 }
271 };
272
TEST_F(ZygoteHeapTest,PreZygoteFork)273 TEST_F(ZygoteHeapTest, PreZygoteFork) {
274 // Exercise Heap::PreZygoteFork() to check it does not crash.
275 Runtime::Current()->GetHeap()->PreZygoteFork();
276 }
277
278 } // namespace gc
279 } // namespace art
280