• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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     constexpr size_t kNumArrays = 1024;
76     constexpr size_t kNumElements = 2048;
77     StackHandleScope<1> hs(soa.Self());
78     Handle<mirror::Class> c(
79         hs.NewHandle(class_linker_->FindSystemClass(soa.Self(), "[Ljava/lang/Object;")));
80     for (size_t i = 0; i < kNumArrays; ++i) {
81       StackHandleScope<1> hs2(soa.Self());
82       Handle<mirror::ObjectArray<mirror::Object>> array(hs2.NewHandle(
83           mirror::ObjectArray<mirror::Object>::Alloc(soa.Self(), c.Get(), kNumElements)));
84       for (size_t j = 0; j < kNumElements; ++j) {
85         ObjPtr<mirror::String> string =
86             mirror::String::AllocFromModifiedUtf8(soa.Self(), "hello, world!");
87         // handle scope operator -> deferences the handle scope before running the method.
88         array->Set<false>(j, string);
89       }
90     }
91   }
92   Runtime::Current()->GetHeap()->CollectGarbage(/* clear_soft_references= */ false);
93 }
94 
TEST_F(HeapTest,HeapBitmapCapacityTest)95 TEST_F(HeapTest, HeapBitmapCapacityTest) {
96   uint8_t* heap_begin = reinterpret_cast<uint8_t*>(0x1000);
97   const size_t heap_capacity = kObjectAlignment * (sizeof(intptr_t) * 8 + 1);
98   accounting::ContinuousSpaceBitmap bitmap(
99       accounting::ContinuousSpaceBitmap::Create("test bitmap", heap_begin, heap_capacity));
100   mirror::Object* fake_end_of_heap_object =
101       reinterpret_cast<mirror::Object*>(&heap_begin[heap_capacity - kObjectAlignment]);
102   bitmap.Set(fake_end_of_heap_object);
103 }
104 
TEST_F(HeapTest,DumpGCPerformanceOnShutdown)105 TEST_F(HeapTest, DumpGCPerformanceOnShutdown) {
106   Runtime::Current()->GetHeap()->CollectGarbage(/* clear_soft_references= */ false);
107   Runtime::Current()->SetDumpGCPerformanceOnShutdown(true);
108 }
109 
AnyIsFalse(bool x,bool y)110 bool AnyIsFalse(bool x, bool y) { return !x || !y; }
111 
TEST_F(HeapTest,GCMetrics)112 TEST_F(HeapTest, GCMetrics) {
113   // Allocate a lot of object arrays to be collected (to ensure the garbage collection is long
114   // enough for the timing metrics to be non-zero), then trigger garbage collection, and check that
115   // GC metrics are updated (where applicable).
116   Heap* heap = Runtime::Current()->GetHeap();
117   {
118     constexpr size_t kNumArrays = 32768;
119     constexpr size_t kNumElements = 4;
120     ScopedObjectAccess soa(Thread::Current());
121     StackHandleScope<kNumArrays + 1> hs(soa.Self());
122     Handle<mirror::Class> c(
123         hs.NewHandle(class_linker_->FindSystemClass(soa.Self(), "[Ljava/lang/Object;")));
124     for (size_t i = 0; i < kNumArrays; i++) {
125       MutableHandle<mirror::ObjectArray<mirror::Object>> array(hs.NewHandle(
126           mirror::ObjectArray<mirror::Object>::Alloc(soa.Self(), c.Get(), kNumElements)));
127       // Perform another allocation so that the previous object array becomes garbage,
128       // forcing all the components of the GC to be involved due to the mix of reachable
129       // and unreachable objects.
130       array.Assign(mirror::ObjectArray<mirror::Object>::Alloc(soa.Self(), c.Get(), kNumElements));
131       for (size_t j = 0; j < kNumElements; j++) {
132         array->Set<false>(j, array.Get());
133       }
134     }
135 
136     // Do one GC while the temporary objects are reachable, forcing the GC to scan something.
137     // The subsequent GC at line 127 may not scan anything but will certainly free some bytes.
138     // Together the two GCs ensure success of the test.
139     heap->CollectGarbage(/* clear_soft_references= */ false);
140   }
141   heap->CollectGarbage(/* clear_soft_references= */ false);
142 
143   // ART Metrics.
144   metrics::ArtMetrics* metrics = Runtime::Current()->GetMetrics();
145   // ART full-heap GC metrics.
146   metrics::MetricsBase<int64_t>* full_gc_collection_time = metrics->FullGcCollectionTime();
147   metrics::MetricsBase<uint64_t>* full_gc_count = metrics->FullGcCount();
148   metrics::MetricsBase<uint64_t>* full_gc_count_delta = metrics->FullGcCountDelta();
149   metrics::MetricsBase<int64_t>* full_gc_throughput = metrics->FullGcThroughput();
150   metrics::MetricsBase<int64_t>* full_gc_tracing_throughput = metrics->FullGcTracingThroughput();
151   metrics::MetricsBase<uint64_t>* full_gc_throughput_avg = metrics->FullGcThroughputAvg();
152   metrics::MetricsBase<uint64_t>* full_gc_tracing_throughput_avg =
153       metrics->FullGcTracingThroughputAvg();
154   metrics::MetricsBase<uint64_t>* full_gc_scanned_bytes = metrics->FullGcScannedBytes();
155   metrics::MetricsBase<uint64_t>* full_gc_scanned_bytes_delta = metrics->FullGcScannedBytesDelta();
156   metrics::MetricsBase<uint64_t>* full_gc_freed_bytes = metrics->FullGcFreedBytes();
157   metrics::MetricsBase<uint64_t>* full_gc_freed_bytes_delta = metrics->FullGcFreedBytesDelta();
158   metrics::MetricsBase<uint64_t>* full_gc_duration = metrics->FullGcDuration();
159   metrics::MetricsBase<uint64_t>* full_gc_duration_delta = metrics->FullGcDurationDelta();
160   metrics::MetricsBase<uint64_t>* full_gc_app_slow_path_duration_delta =
161       metrics->AppSlowPathDuringFullGcDurationDelta();
162   // ART young-generation GC metrics.
163   metrics::MetricsBase<int64_t>* young_gc_collection_time = metrics->YoungGcCollectionTime();
164   metrics::MetricsBase<uint64_t>* young_gc_count = metrics->YoungGcCount();
165   metrics::MetricsBase<uint64_t>* young_gc_count_delta = metrics->YoungGcCountDelta();
166   metrics::MetricsBase<int64_t>* young_gc_throughput = metrics->YoungGcThroughput();
167   metrics::MetricsBase<int64_t>* young_gc_tracing_throughput = metrics->YoungGcTracingThroughput();
168   metrics::MetricsBase<uint64_t>* young_gc_throughput_avg = metrics->YoungGcThroughputAvg();
169   metrics::MetricsBase<uint64_t>* young_gc_tracing_throughput_avg =
170       metrics->YoungGcTracingThroughputAvg();
171   metrics::MetricsBase<uint64_t>* young_gc_scanned_bytes = metrics->YoungGcScannedBytes();
172   metrics::MetricsBase<uint64_t>* young_gc_scanned_bytes_delta =
173       metrics->YoungGcScannedBytesDelta();
174   metrics::MetricsBase<uint64_t>* young_gc_freed_bytes = metrics->YoungGcFreedBytes();
175   metrics::MetricsBase<uint64_t>* young_gc_freed_bytes_delta = metrics->YoungGcFreedBytesDelta();
176   metrics::MetricsBase<uint64_t>* young_gc_duration = metrics->YoungGcDuration();
177   metrics::MetricsBase<uint64_t>* young_gc_duration_delta = metrics->YoungGcDurationDelta();
178   metrics::MetricsBase<uint64_t>* young_gc_app_slow_path_duration_delta =
179       metrics->AppSlowPathDuringYoungGcDurationDelta();
180 
181   CollectorType fg_collector_type = heap->GetForegroundCollectorType();
182   if (fg_collector_type == kCollectorTypeCC || fg_collector_type == kCollectorTypeCMC) {
183     // Only the Concurrent Copying and Concurrent Mark-Compact collectors enable
184     // GC metrics at the moment.
185     if (heap->GetUseGenerational()) {
186       // Check that full-heap and/or young-generation GC metrics are non-null
187       // after triggering the collection.
188       EXPECT_PRED2(
189           AnyIsFalse, full_gc_collection_time->IsNull(), young_gc_collection_time->IsNull());
190       EXPECT_PRED2(AnyIsFalse, full_gc_count->IsNull(), young_gc_count->IsNull());
191       EXPECT_PRED2(AnyIsFalse, full_gc_count_delta->IsNull(), young_gc_count_delta->IsNull());
192       EXPECT_PRED2(AnyIsFalse, full_gc_throughput->IsNull(), young_gc_throughput->IsNull());
193       EXPECT_PRED2(
194           AnyIsFalse, full_gc_tracing_throughput->IsNull(), young_gc_tracing_throughput->IsNull());
195       EXPECT_PRED2(AnyIsFalse, full_gc_throughput_avg->IsNull(), young_gc_throughput_avg->IsNull());
196       EXPECT_PRED2(AnyIsFalse,
197                    full_gc_tracing_throughput_avg->IsNull(),
198                    young_gc_tracing_throughput_avg->IsNull());
199       EXPECT_PRED2(AnyIsFalse, full_gc_scanned_bytes->IsNull(), young_gc_scanned_bytes->IsNull());
200       EXPECT_PRED2(AnyIsFalse,
201                    full_gc_scanned_bytes_delta->IsNull(),
202                    young_gc_scanned_bytes_delta->IsNull());
203       EXPECT_PRED2(AnyIsFalse, full_gc_freed_bytes->IsNull(), young_gc_freed_bytes->IsNull());
204       EXPECT_PRED2(
205           AnyIsFalse, full_gc_freed_bytes_delta->IsNull(), young_gc_freed_bytes_delta->IsNull());
206       EXPECT_PRED2(AnyIsFalse, full_gc_duration->IsNull(), young_gc_duration->IsNull());
207       EXPECT_PRED2(AnyIsFalse, full_gc_duration_delta->IsNull(), young_gc_duration_delta->IsNull());
208       EXPECT_PRED2(AnyIsFalse,
209                    full_gc_app_slow_path_duration_delta->IsNull(),
210                    young_gc_app_slow_path_duration_delta->IsNull());
211     } else {
212       // Check that only full-heap GC metrics are non-null after triggering the collection.
213       EXPECT_FALSE(full_gc_collection_time->IsNull());
214       EXPECT_FALSE(full_gc_count->IsNull());
215       EXPECT_FALSE(full_gc_count_delta->IsNull());
216       EXPECT_FALSE(full_gc_throughput->IsNull());
217       EXPECT_FALSE(full_gc_tracing_throughput->IsNull());
218       EXPECT_FALSE(full_gc_throughput_avg->IsNull());
219       EXPECT_FALSE(full_gc_tracing_throughput_avg->IsNull());
220       EXPECT_FALSE(full_gc_scanned_bytes->IsNull());
221       EXPECT_FALSE(full_gc_scanned_bytes_delta->IsNull());
222       EXPECT_FALSE(full_gc_freed_bytes->IsNull());
223       EXPECT_FALSE(full_gc_freed_bytes_delta->IsNull());
224       EXPECT_FALSE(full_gc_duration->IsNull());
225       EXPECT_FALSE(full_gc_duration_delta->IsNull());
226       EXPECT_FALSE(full_gc_app_slow_path_duration_delta->IsNull());
227 
228       EXPECT_TRUE(young_gc_collection_time->IsNull());
229       EXPECT_TRUE(young_gc_count->IsNull());
230       EXPECT_TRUE(young_gc_count_delta->IsNull());
231       EXPECT_TRUE(young_gc_throughput->IsNull());
232       EXPECT_TRUE(young_gc_tracing_throughput->IsNull());
233       EXPECT_TRUE(young_gc_throughput_avg->IsNull());
234       EXPECT_TRUE(young_gc_tracing_throughput_avg->IsNull());
235       EXPECT_TRUE(young_gc_scanned_bytes->IsNull());
236       EXPECT_TRUE(young_gc_scanned_bytes_delta->IsNull());
237       EXPECT_TRUE(young_gc_freed_bytes->IsNull());
238       EXPECT_TRUE(young_gc_freed_bytes_delta->IsNull());
239       EXPECT_TRUE(young_gc_duration->IsNull());
240       EXPECT_TRUE(young_gc_duration_delta->IsNull());
241       EXPECT_TRUE(young_gc_app_slow_path_duration_delta->IsNull());
242     }
243   } else {
244     // Check that all metrics are null after triggering the collection.
245     EXPECT_TRUE(full_gc_collection_time->IsNull());
246     EXPECT_TRUE(full_gc_count->IsNull());
247     EXPECT_TRUE(full_gc_count_delta->IsNull());
248     EXPECT_TRUE(full_gc_throughput->IsNull());
249     EXPECT_TRUE(full_gc_tracing_throughput->IsNull());
250     EXPECT_TRUE(full_gc_throughput_avg->IsNull());
251     EXPECT_TRUE(full_gc_tracing_throughput_avg->IsNull());
252     EXPECT_TRUE(full_gc_scanned_bytes->IsNull());
253     EXPECT_TRUE(full_gc_scanned_bytes_delta->IsNull());
254     EXPECT_TRUE(full_gc_freed_bytes->IsNull());
255     EXPECT_TRUE(full_gc_freed_bytes_delta->IsNull());
256     EXPECT_TRUE(full_gc_duration->IsNull());
257     EXPECT_TRUE(full_gc_duration_delta->IsNull());
258     EXPECT_TRUE(full_gc_app_slow_path_duration_delta->IsNull());
259 
260     EXPECT_TRUE(young_gc_collection_time->IsNull());
261     EXPECT_TRUE(young_gc_count->IsNull());
262     EXPECT_TRUE(young_gc_count_delta->IsNull());
263     EXPECT_TRUE(young_gc_throughput->IsNull());
264     EXPECT_TRUE(young_gc_tracing_throughput->IsNull());
265     EXPECT_TRUE(young_gc_throughput_avg->IsNull());
266     EXPECT_TRUE(young_gc_tracing_throughput_avg->IsNull());
267     EXPECT_TRUE(young_gc_scanned_bytes->IsNull());
268     EXPECT_TRUE(young_gc_scanned_bytes_delta->IsNull());
269     EXPECT_TRUE(young_gc_freed_bytes->IsNull());
270     EXPECT_TRUE(young_gc_freed_bytes_delta->IsNull());
271     EXPECT_TRUE(young_gc_duration->IsNull());
272     EXPECT_TRUE(young_gc_duration_delta->IsNull());
273     EXPECT_TRUE(young_gc_app_slow_path_duration_delta->IsNull());
274   }
275 }
276 
277 class ZygoteHeapTest : public CommonRuntimeTest {
278  public:
ZygoteHeapTest()279   ZygoteHeapTest() {
280     use_boot_image_ = true;  // Make the Runtime creation cheaper.
281   }
282 
SetUpRuntimeOptions(RuntimeOptions * options)283   void SetUpRuntimeOptions(RuntimeOptions* options) override {
284     CommonRuntimeTest::SetUpRuntimeOptions(options);
285     options->push_back(std::make_pair("-Xzygote", nullptr));
286   }
287 };
288 
TEST_F(ZygoteHeapTest,PreZygoteFork)289 TEST_F(ZygoteHeapTest, PreZygoteFork) {
290   // Exercise Heap::PreZygoteFork() to check it does not crash.
291   Runtime::Current()->GetHeap()->PreZygoteFork();
292 }
293 
294 }  // namespace gc
295 }  // namespace art
296