diff options
author | 2025-03-12 07:35:24 -0700 | |
---|---|---|
committer | 2025-03-14 01:26:35 -0700 | |
commit | f1c6babf2197e233a929d94a9dcd4a403ab4eb7c (patch) | |
tree | 40183545da2433986993d37470b53acb05fb107c | |
parent | f3f82a4466bd377ca702982401f9dc8916fbb4ed (diff) |
Change allocations from strings to object arrays in HeapTest#GCMetrics
This test is occasionally failing because the slow path duration for either the full heap or the young generation is shorter than one millisecond.
Changing the allocations from string to object arrays should help making the duration consistently over one millisecond and the test less flaky.
Bug: 271990567
Test: atest art_standalone_runtime_tests
Change-Id: I7a6463716ad3540a7fab58544c3e176003f6e0ed
-rw-r--r-- | runtime/gc/heap_test.cc | 40 |
1 files changed, 26 insertions, 14 deletions
diff --git a/runtime/gc/heap_test.cc b/runtime/gc/heap_test.cc index 3d3cabff29..0275170d98 100644 --- a/runtime/gc/heap_test.cc +++ b/runtime/gc/heap_test.cc @@ -45,9 +45,9 @@ class HeapTest : public CommonRuntimeTest { gc::Heap::kPreferredAllocSpaceBegin, 16 * KB, PROT_READ, - /*low_4gb=*/ true, - /*reuse=*/ false, - /*reservation=*/ nullptr, + /*low_4gb=*/true, + /*reuse=*/false, + /*reservation=*/nullptr, &error_msg); // There is no guarantee that reserved_ will be valid (due to ASLR). See b/175018342. CommonRuntimeTest::SetUp(); @@ -71,16 +71,17 @@ TEST_F(HeapTest, ClearGrowthLimit) { TEST_F(HeapTest, GarbageCollectClassLinkerInit) { { ScopedObjectAccess soa(Thread::Current()); - // garbage is created during ClassLinker::Init - + // garbage is created during ClassLinker::Init() + constexpr size_t kNumArrays = 1024; + constexpr size_t kNumElements = 2048; StackHandleScope<1> hs(soa.Self()); Handle<mirror::Class> c( hs.NewHandle(class_linker_->FindSystemClass(soa.Self(), "[Ljava/lang/Object;"))); - for (size_t i = 0; i < 1024; ++i) { + for (size_t i = 0; i < kNumArrays; ++i) { StackHandleScope<1> hs2(soa.Self()); Handle<mirror::ObjectArray<mirror::Object>> array(hs2.NewHandle( - mirror::ObjectArray<mirror::Object>::Alloc(soa.Self(), c.Get(), 2048))); - for (size_t j = 0; j < 2048; ++j) { + mirror::ObjectArray<mirror::Object>::Alloc(soa.Self(), c.Get(), kNumElements))); + for (size_t j = 0; j < kNumElements; ++j) { ObjPtr<mirror::String> string = mirror::String::AllocFromModifiedUtf8(soa.Self(), "hello, world!"); // handle scope operator -> deferences the handle scope before running the method. @@ -109,18 +110,29 @@ TEST_F(HeapTest, DumpGCPerformanceOnShutdown) { bool AnyIsFalse(bool x, bool y) { return !x || !y; } TEST_F(HeapTest, GCMetrics) { - // Allocate a lot of string objects to be collected (to ensure the garbage collection is long + // Allocate a lot of object arrays to be collected (to ensure the garbage collection is long // enough for the timing metrics to be non-zero), then trigger garbage collection, and check that // GC metrics are updated (where applicable). Heap* heap = Runtime::Current()->GetHeap(); { - constexpr const size_t kNumObj = 32768; + constexpr size_t kNumArrays = 32768; + constexpr size_t kNumElements = 4; ScopedObjectAccess soa(Thread::Current()); - StackHandleScope<kNumObj> hs(soa.Self()); - for (size_t i = 0u; i < kNumObj; ++i) { - Handle<mirror::String> string [[maybe_unused]] ( - hs.NewHandle(mirror::String::AllocFromModifiedUtf8(soa.Self(), "test"))); + StackHandleScope<kNumArrays + 1> hs(soa.Self()); + Handle<mirror::Class> c( + hs.NewHandle(class_linker_->FindSystemClass(soa.Self(), "[Ljava/lang/Object;"))); + for (size_t i = 0; i < kNumArrays; i++) { + MutableHandle<mirror::ObjectArray<mirror::Object>> array(hs.NewHandle( + mirror::ObjectArray<mirror::Object>::Alloc(soa.Self(), c.Get(), kNumElements))); + // Perform another allocation so that the previous object array becomes garbage, + // forcing all the components of the GC to be involved due to the mix of reachable + // and unreachable objects. + array.Assign(mirror::ObjectArray<mirror::Object>::Alloc(soa.Self(), c.Get(), kNumElements)); + for (size_t j = 0; j < kNumElements; j++) { + array->Set<false>(j, array.Get()); + } } + // Do one GC while the temporary objects are reachable, forcing the GC to scan something. // The subsequent GC at line 127 may not scan anything but will certainly free some bytes. // Together the two GCs ensure success of the test. |