diff options
author | 2023-03-17 17:59:05 +0000 | |
---|---|---|
committer | 2023-03-27 10:18:58 +0000 | |
commit | 6dc2655b1474d137f59dc92c00458f6440a59e03 (patch) | |
tree | dc8d09e72d962b6b2d8bf1174b15d82e26158804 | |
parent | 4efc53d64dd5a04fcb9203bee756ae462c6da9f9 (diff) |
Compute "scanned bytes" GC metrics in ART's CMC collector.
Test: ART_USE_READ_BARRIER=false \
m test-art-host-gtest-art_runtime_tests
Bug: 270957146
Bug: 270391874
Change-Id: Ie64ed1c89774676af58a47caa7e697474bbeaaf4
-rw-r--r-- | runtime/gc/collector/mark_compact.cc | 19 | ||||
-rw-r--r-- | runtime/gc/collector/mark_compact.h | 5 | ||||
-rw-r--r-- | runtime/gc/heap_test.cc | 8 |
3 files changed, 21 insertions, 11 deletions
diff --git a/runtime/gc/collector/mark_compact.cc b/runtime/gc/collector/mark_compact.cc index 03e8bdd17b..3c2606a6d7 100644 --- a/runtime/gc/collector/mark_compact.cc +++ b/runtime/gc/collector/mark_compact.cc @@ -587,6 +587,7 @@ void MarkCompact::InitializePhase() { moving_first_objs_count_ = 0; non_moving_first_objs_count_ = 0; black_page_count_ = 0; + bytes_scanned_ = 0; freed_objects_ = 0; // The first buffer is used by gc-thread. compaction_buffer_counter_ = 1; @@ -2266,7 +2267,9 @@ void MarkCompact::UpdateMovingSpaceBlackAllocations() { && obj->GetClass<kDefaultVerifyFlags, kWithoutReadBarrier>() != nullptr) { // Try to keep instructions which access class instance together to // avoid reloading the pointer from object. - size_t obj_size = RoundUp(obj->SizeOf(), kAlignment); + size_t obj_size = obj->SizeOf(); + bytes_scanned_ += obj_size; + obj_size = RoundUp(obj_size, kAlignment); UpdateClassAfterObjectMap(obj); if (first_obj == nullptr) { first_obj = obj; @@ -3921,11 +3924,12 @@ size_t MarkCompact::LiveWordsBitmap<kAlignment>::LiveBytesInBitmapWord(size_t ch return words * kAlignment; } -void MarkCompact::UpdateLivenessInfo(mirror::Object* obj) { +void MarkCompact::UpdateLivenessInfo(mirror::Object* obj, size_t obj_size) { DCHECK(obj != nullptr); + DCHECK_EQ(obj_size, obj->SizeOf<kDefaultVerifyFlags>()); uintptr_t obj_begin = reinterpret_cast<uintptr_t>(obj); UpdateClassAfterObjectMap(obj); - size_t size = RoundUp(obj->SizeOf<kDefaultVerifyFlags>(), kAlignment); + size_t size = RoundUp(obj_size, kAlignment); uintptr_t bit_index = live_words_bitmap_->SetLiveWords(obj_begin, size); size_t chunk_idx = (obj_begin - live_words_bitmap_->Begin()) / kOffsetChunkSize; // Compute the bit-index within the chunk-info vector word. @@ -3944,10 +3948,16 @@ void MarkCompact::UpdateLivenessInfo(mirror::Object* obj) { template <bool kUpdateLiveWords> void MarkCompact::ScanObject(mirror::Object* obj) { + // The size of `obj` is used both here (to update `bytes_scanned_`) and in + // `UpdateLivenessInfo`. As fetching this value can be expensive, do it once + // here and pass that information to `UpdateLivenessInfo`. + size_t obj_size = obj->SizeOf<kDefaultVerifyFlags>(); + bytes_scanned_ += obj_size; + RefFieldsVisitor visitor(this); DCHECK(IsMarked(obj)) << "Scanning marked object " << obj << "\n" << heap_->DumpSpaces(); if (kUpdateLiveWords && moving_space_bitmap_->HasAddress(obj)) { - UpdateLivenessInfo(obj); + UpdateLivenessInfo(obj, obj_size); } obj->VisitReferences(visitor, visitor); } @@ -4132,6 +4142,7 @@ void MarkCompact::DelayReferenceReferent(ObjPtr<mirror::Class> klass, } void MarkCompact::FinishPhase() { + GetCurrentIteration()->SetScannedBytes(bytes_scanned_); bool is_zygote = Runtime::Current()->IsZygote(); compacting_ = false; minor_fault_initialized_ = !is_zygote && uffd_minor_fault_supported_; diff --git a/runtime/gc/collector/mark_compact.h b/runtime/gc/collector/mark_compact.h index 3504ad3c0d..d73f40d436 100644 --- a/runtime/gc/collector/mark_compact.h +++ b/runtime/gc/collector/mark_compact.h @@ -422,7 +422,8 @@ class MarkCompact final : public GarbageCollector { // Update the live-words bitmap as well as add the object size to the // chunk-info vector. Both are required for computation of post-compact addresses. // Also updates freed_objects_ counter. - void UpdateLivenessInfo(mirror::Object* obj) REQUIRES_SHARED(Locks::mutator_lock_); + void UpdateLivenessInfo(mirror::Object* obj, size_t obj_size) + REQUIRES_SHARED(Locks::mutator_lock_); void ProcessReferences(Thread* self) REQUIRES_SHARED(Locks::mutator_lock_) @@ -655,6 +656,8 @@ class MarkCompact final : public GarbageCollector { size_t vector_length_; size_t live_stack_freeze_size_; + uint64_t bytes_scanned_; + // For every page in the to-space (post-compact heap) we need to know the // first object from which we must compact and/or update references. This is // for both non-moving and moving space. Additionally, for the moving-space, diff --git a/runtime/gc/heap_test.cc b/runtime/gc/heap_test.cc index 5e64ae2192..b569241bdc 100644 --- a/runtime/gc/heap_test.cc +++ b/runtime/gc/heap_test.cc @@ -201,12 +201,8 @@ TEST_F(HeapTest, GCMetrics) { EXPECT_FALSE(full_gc_tracing_throughput->IsNull()); EXPECT_FALSE(full_gc_throughput_avg->IsNull()); EXPECT_FALSE(full_gc_tracing_throughput_avg->IsNull()); - if (fg_collector_type != kCollectorTypeCMC) { - // TODO(b/270957146): For some reason, these metrics are still null - // after running the Concurrent Mark-Compact collector; investigate why. - EXPECT_FALSE(full_gc_scanned_bytes->IsNull()); - EXPECT_FALSE(full_gc_scanned_bytes_delta->IsNull()); - } + EXPECT_FALSE(full_gc_scanned_bytes->IsNull()); + EXPECT_FALSE(full_gc_scanned_bytes_delta->IsNull()); EXPECT_FALSE(full_gc_freed_bytes->IsNull()); EXPECT_FALSE(full_gc_freed_bytes_delta->IsNull()); EXPECT_FALSE(full_gc_duration->IsNull()); |