diff options
| author | 2023-02-27 11:54:44 +0000 | |
|---|---|---|
| committer | 2023-02-28 15:14:10 +0000 | |
| commit | 92a1eacde8c0720939eea3841bfb6cc4d70b6040 (patch) | |
| tree | f700f24f09cfc83e48183dbbb4e0ef9f4dc8ac83 /runtime/gc/heap_test.cc | |
| parent | f2f8f762eb247cd193664b6dce3f4dc2c9c34c30 (diff) | |
Add a test checking that ART Metrics are enabled in ART's CMC collector.
ART GC Metrics are currently only enabled in ART's Concurrent Copying
(CC) collector; add a test to ensure this is and will still be true.
Test: ART_USE_READ_BARRIER=true ART_USE_GENERATIONAL_CC=true \
m test-art-host-gtest-art_runtime_tests
Test: ART_USE_READ_BARRIER=true ART_USE_GENERATIONAL_CC=false \
m test-art-host-gtest-art_runtime_tests
Test: ART_USE_READ_BARRIER=false \
m test-art-host-gtest-art_runtime_tests
Bug: 270391874
Change-Id: I00bc64fdb665fe1a61b7b571963231ae51e82fea
Diffstat (limited to 'runtime/gc/heap_test.cc')
| -rw-r--r-- | runtime/gc/heap_test.cc | 140 |
1 files changed, 140 insertions, 0 deletions
diff --git a/runtime/gc/heap_test.cc b/runtime/gc/heap_test.cc index 55ddd72715..7fa37f3adb 100644 --- a/runtime/gc/heap_test.cc +++ b/runtime/gc/heap_test.cc @@ -14,6 +14,9 @@ * limitations under the License. */ +#include <algorithm> + +#include "base/metrics/metrics.h" #include "class_linker-inl.h" #include "common_runtime_test.h" #include "gc/accounting/card_table-inl.h" @@ -103,6 +106,143 @@ TEST_F(HeapTest, DumpGCPerformanceOnShutdown) { Runtime::Current()->SetDumpGCPerformanceOnShutdown(true); } +template <typename T> +bool AnyIsNonNull(const metrics::MetricsBase<T>* x, const metrics::MetricsBase<T>* y) { + return !x->IsNull() || !y->IsNull(); +} + +TEST_F(HeapTest, GCMetrics) { + // Allocate a few string objects (to be collected), then trigger garbage + // collection, and check that GC metrics are updated (where applicable). + { + constexpr const size_t kNumObj = 128; + 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"))); + } + } + Heap* heap = Runtime::Current()->GetHeap(); + heap->CollectGarbage(/* clear_soft_references= */ false); + + // ART Metrics. + metrics::ArtMetrics* metrics = Runtime::Current()->GetMetrics(); + // ART full-heap GC metrics. + metrics::MetricsBase<int64_t>* full_gc_collection_time = metrics->FullGcCollectionTime(); + metrics::MetricsBase<uint64_t>* full_gc_count = metrics->FullGcCount(); + metrics::MetricsBase<uint64_t>* full_gc_count_delta = metrics->FullGcCountDelta(); + metrics::MetricsBase<int64_t>* full_gc_throughput = metrics->FullGcThroughput(); + metrics::MetricsBase<int64_t>* full_gc_tracing_throughput = metrics->FullGcTracingThroughput(); + metrics::MetricsBase<uint64_t>* full_gc_throughput_avg = metrics->FullGcThroughputAvg(); + metrics::MetricsBase<uint64_t>* full_gc_tracing_throughput_avg = + metrics->FullGcTracingThroughputAvg(); + metrics::MetricsBase<uint64_t>* full_gc_scanned_bytes = metrics->FullGcScannedBytes(); + metrics::MetricsBase<uint64_t>* full_gc_scanned_bytes_delta = metrics->FullGcScannedBytesDelta(); + metrics::MetricsBase<uint64_t>* full_gc_freed_bytes = metrics->FullGcFreedBytes(); + metrics::MetricsBase<uint64_t>* full_gc_freed_bytes_delta = metrics->FullGcFreedBytesDelta(); + metrics::MetricsBase<uint64_t>* full_gc_duration = metrics->FullGcDuration(); + metrics::MetricsBase<uint64_t>* full_gc_duration_delta = metrics->FullGcDurationDelta(); + // ART young-generation GC metrics. + metrics::MetricsBase<int64_t>* young_gc_collection_time = metrics->YoungGcCollectionTime(); + metrics::MetricsBase<uint64_t>* young_gc_count = metrics->YoungGcCount(); + metrics::MetricsBase<uint64_t>* young_gc_count_delta = metrics->YoungGcCountDelta(); + metrics::MetricsBase<int64_t>* young_gc_throughput = metrics->YoungGcThroughput(); + metrics::MetricsBase<int64_t>* young_gc_tracing_throughput = metrics->YoungGcTracingThroughput(); + metrics::MetricsBase<uint64_t>* young_gc_throughput_avg = metrics->YoungGcThroughputAvg(); + metrics::MetricsBase<uint64_t>* young_gc_tracing_throughput_avg = + metrics->YoungGcTracingThroughputAvg(); + metrics::MetricsBase<uint64_t>* young_gc_scanned_bytes = metrics->YoungGcScannedBytes(); + metrics::MetricsBase<uint64_t>* young_gc_scanned_bytes_delta = + metrics->YoungGcScannedBytesDelta(); + metrics::MetricsBase<uint64_t>* young_gc_freed_bytes = metrics->YoungGcFreedBytes(); + metrics::MetricsBase<uint64_t>* young_gc_freed_bytes_delta = metrics->YoungGcFreedBytesDelta(); + metrics::MetricsBase<uint64_t>* young_gc_duration = metrics->YoungGcDuration(); + metrics::MetricsBase<uint64_t>* young_gc_duration_delta = metrics->YoungGcDurationDelta(); + + CollectorType fg_collector_type = heap->GetForegroundCollectorType(); + if (fg_collector_type == kCollectorTypeCC) { + // Only the Concurrent Copying collector enables GC metrics at the moment. + if (heap->GetUseGenerationalCC()) { + // Check that full-heap and/or young-generation GC metrics are non-null + // after trigerring the collection. + EXPECT_PRED2(AnyIsNonNull<int64_t>, full_gc_collection_time, young_gc_collection_time); + EXPECT_PRED2(AnyIsNonNull<uint64_t>, full_gc_count, young_gc_count); + EXPECT_PRED2(AnyIsNonNull<uint64_t>, full_gc_count_delta, young_gc_count_delta); + EXPECT_PRED2(AnyIsNonNull<int64_t>, full_gc_throughput, young_gc_throughput); + EXPECT_PRED2(AnyIsNonNull<int64_t>, full_gc_tracing_throughput, young_gc_tracing_throughput); + EXPECT_PRED2(AnyIsNonNull<uint64_t>, full_gc_throughput_avg, young_gc_throughput_avg); + EXPECT_PRED2( + AnyIsNonNull<uint64_t>, full_gc_tracing_throughput_avg, young_gc_tracing_throughput_avg); + EXPECT_PRED2(AnyIsNonNull<uint64_t>, full_gc_scanned_bytes, young_gc_scanned_bytes); + EXPECT_PRED2( + AnyIsNonNull<uint64_t>, full_gc_scanned_bytes_delta, young_gc_scanned_bytes_delta); + EXPECT_PRED2(AnyIsNonNull<uint64_t>, full_gc_freed_bytes, young_gc_freed_bytes); + EXPECT_PRED2(AnyIsNonNull<uint64_t>, full_gc_freed_bytes_delta, young_gc_freed_bytes_delta); + EXPECT_PRED2(AnyIsNonNull<uint64_t>, full_gc_duration, young_gc_duration); + EXPECT_PRED2(AnyIsNonNull<uint64_t>, full_gc_duration_delta, young_gc_duration_delta); + } else { + // Check that only full-heap GC metrics are non-null after trigerring the collection. + EXPECT_FALSE(full_gc_collection_time->IsNull()); + EXPECT_FALSE(full_gc_count->IsNull()); + EXPECT_FALSE(full_gc_count_delta->IsNull()); + EXPECT_FALSE(full_gc_throughput->IsNull()); + EXPECT_FALSE(full_gc_tracing_throughput->IsNull()); + EXPECT_FALSE(full_gc_throughput_avg->IsNull()); + EXPECT_FALSE(full_gc_tracing_throughput_avg->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()); + EXPECT_FALSE(full_gc_duration_delta->IsNull()); + + EXPECT_TRUE(young_gc_collection_time->IsNull()); + EXPECT_TRUE(young_gc_count->IsNull()); + EXPECT_TRUE(young_gc_count_delta->IsNull()); + EXPECT_TRUE(young_gc_throughput->IsNull()); + EXPECT_TRUE(young_gc_tracing_throughput->IsNull()); + EXPECT_TRUE(young_gc_throughput_avg->IsNull()); + EXPECT_TRUE(young_gc_tracing_throughput_avg->IsNull()); + EXPECT_TRUE(young_gc_scanned_bytes->IsNull()); + EXPECT_TRUE(young_gc_scanned_bytes_delta->IsNull()); + EXPECT_TRUE(young_gc_freed_bytes->IsNull()); + EXPECT_TRUE(young_gc_freed_bytes_delta->IsNull()); + EXPECT_TRUE(young_gc_duration->IsNull()); + EXPECT_TRUE(young_gc_duration_delta->IsNull()); + } + } else { + // Check that all metrics are null after trigerring the collection. + EXPECT_TRUE(full_gc_collection_time->IsNull()); + EXPECT_TRUE(full_gc_count->IsNull()); + EXPECT_TRUE(full_gc_count_delta->IsNull()); + EXPECT_TRUE(full_gc_throughput->IsNull()); + EXPECT_TRUE(full_gc_tracing_throughput->IsNull()); + EXPECT_TRUE(full_gc_throughput_avg->IsNull()); + EXPECT_TRUE(full_gc_tracing_throughput_avg->IsNull()); + EXPECT_TRUE(full_gc_scanned_bytes->IsNull()); + EXPECT_TRUE(full_gc_scanned_bytes_delta->IsNull()); + EXPECT_TRUE(full_gc_freed_bytes->IsNull()); + EXPECT_TRUE(full_gc_freed_bytes_delta->IsNull()); + EXPECT_TRUE(full_gc_duration->IsNull()); + EXPECT_TRUE(full_gc_duration_delta->IsNull()); + + EXPECT_TRUE(young_gc_collection_time->IsNull()); + EXPECT_TRUE(young_gc_count->IsNull()); + EXPECT_TRUE(young_gc_count_delta->IsNull()); + EXPECT_TRUE(young_gc_throughput->IsNull()); + EXPECT_TRUE(young_gc_tracing_throughput->IsNull()); + EXPECT_TRUE(young_gc_throughput_avg->IsNull()); + EXPECT_TRUE(young_gc_tracing_throughput_avg->IsNull()); + EXPECT_TRUE(young_gc_scanned_bytes->IsNull()); + EXPECT_TRUE(young_gc_scanned_bytes_delta->IsNull()); + EXPECT_TRUE(young_gc_freed_bytes->IsNull()); + EXPECT_TRUE(young_gc_freed_bytes_delta->IsNull()); + EXPECT_TRUE(young_gc_duration->IsNull()); + EXPECT_TRUE(young_gc_duration_delta->IsNull()); + } +} + class ZygoteHeapTest : public CommonRuntimeTest { public: ZygoteHeapTest() { |