v8/test/unittests/heap/cppgc/metric-recorder-unittest.cc
Omer Katz e6e9721b55 cppgc: Increase tolerance in MetricRecorder unittests
Tolerance was set to 50 microseconds. This is not enough and causes
flaky failures. Tolerance is needed because we record milliseconds and
an empty scope can still take a few milliseconds to create and destroy.

Increasing the tolerance to 500 microseconds should suffice and makes
sense for the test. All expected values are in 10s of milliseconds, so
half a millisecond tolerance should be reasonable.

Bug: v8:11367
Change-Id: I2d284efe5176ec9938b6a378f4b5f1bda0e58781
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2659058
Commit-Queue: Omer Katz <omerkatz@chromium.org>
Auto-Submit: Omer Katz <omerkatz@chromium.org>
Reviewed-by: Michael Lippautz <mlippautz@chromium.org>
Cr-Commit-Position: refs/heads/master@{#72426}
2021-01-29 11:21:23 +00:00

319 lines
12 KiB
C++

// Copyright 2020 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "src/heap/cppgc/metric-recorder.h"
#include "src/heap/cppgc/stats-collector.h"
#include "test/unittests/heap/cppgc/tests.h"
namespace cppgc {
namespace internal {
namespace {
class MetricRecorderImpl final : public MetricRecorder {
public:
void AddMainThreadEvent(const CppGCFullCycle& event) final {
CppGCFullCycle_event = event;
CppGCFullCycle_callcount++;
}
void AddMainThreadEvent(const CppGCMainThreadIncrementalMark& event) final {
CppGCMainThreadIncrementalMark_event = event;
CppGCMainThreadIncrementalMark_callcount++;
}
void AddMainThreadEvent(const CppGCMainThreadIncrementalSweep& event) final {
CppGCMainThreadIncrementalSweep_event = event;
CppGCMainThreadIncrementalSweep_callcount++;
}
static size_t CppGCFullCycle_callcount;
static CppGCFullCycle CppGCFullCycle_event;
static size_t CppGCMainThreadIncrementalMark_callcount;
static CppGCMainThreadIncrementalMark CppGCMainThreadIncrementalMark_event;
static size_t CppGCMainThreadIncrementalSweep_callcount;
static CppGCMainThreadIncrementalSweep CppGCMainThreadIncrementalSweep_event;
};
// static
size_t MetricRecorderImpl::CppGCFullCycle_callcount = 0u;
MetricRecorderImpl::CppGCFullCycle MetricRecorderImpl::CppGCFullCycle_event;
size_t MetricRecorderImpl::CppGCMainThreadIncrementalMark_callcount = 0u;
MetricRecorderImpl::CppGCMainThreadIncrementalMark
MetricRecorderImpl::CppGCMainThreadIncrementalMark_event;
size_t MetricRecorderImpl::CppGCMainThreadIncrementalSweep_callcount = 0u;
MetricRecorderImpl::CppGCMainThreadIncrementalSweep
MetricRecorderImpl::CppGCMainThreadIncrementalSweep_event;
class MetricRecorderTest : public testing::TestWithHeap {
public:
MetricRecorderTest() : stats(Heap::From(GetHeap())->stats_collector()) {
stats->SetMetricRecorderForTesting(std::make_unique<MetricRecorderImpl>());
}
void StartGC() {
stats->NotifyMarkingStarted(
GarbageCollector::Config::CollectionType::kMajor,
GarbageCollector::Config::IsForcedGC::kNotForced);
}
void EndGC(size_t marked_bytes) {
stats->NotifyMarkingCompleted(marked_bytes);
stats->NotifySweepingCompleted();
}
StatsCollector* stats;
};
} // namespace
TEST_F(MetricRecorderTest, IncrementalScopesReportedImmediately) {
MetricRecorderImpl::CppGCFullCycle_callcount = 0u;
MetricRecorderImpl::CppGCMainThreadIncrementalMark_callcount = 0u;
MetricRecorderImpl::CppGCMainThreadIncrementalSweep_callcount = 0u;
StartGC();
{
EXPECT_EQ(0u, MetricRecorderImpl::CppGCMainThreadIncrementalMark_callcount);
{
StatsCollector::EnabledScope scope(*Heap::From(GetHeap()),
StatsCollector::kIncrementalMark);
scope.DecreaseStartTimeForTesting(
v8::base::TimeDelta::FromMilliseconds(1));
}
EXPECT_EQ(1u, MetricRecorderImpl::CppGCMainThreadIncrementalMark_callcount);
EXPECT_LT(
0u,
MetricRecorderImpl::CppGCMainThreadIncrementalMark_event.duration_us);
}
{
EXPECT_EQ(0u,
MetricRecorderImpl::CppGCMainThreadIncrementalSweep_callcount);
{
StatsCollector::EnabledScope scope(*Heap::From(GetHeap()),
StatsCollector::kIncrementalSweep);
scope.DecreaseStartTimeForTesting(
v8::base::TimeDelta::FromMilliseconds(1));
}
EXPECT_EQ(1u,
MetricRecorderImpl::CppGCMainThreadIncrementalSweep_callcount);
EXPECT_LT(
0u,
MetricRecorderImpl::CppGCMainThreadIncrementalSweep_event.duration_us);
}
EXPECT_EQ(0u, MetricRecorderImpl::CppGCFullCycle_callcount);
EndGC(0);
}
TEST_F(MetricRecorderTest, NonIncrementlaScopesNotReportedImmediately) {
MetricRecorderImpl::CppGCFullCycle_callcount = 0u;
MetricRecorderImpl::CppGCMainThreadIncrementalMark_callcount = 0u;
MetricRecorderImpl::CppGCMainThreadIncrementalSweep_callcount = 0u;
StartGC();
{
StatsCollector::EnabledScope scope(*Heap::From(GetHeap()),
StatsCollector::kAtomicMark);
}
{
StatsCollector::EnabledScope scope(*Heap::From(GetHeap()),
StatsCollector::kAtomicWeak);
}
{
StatsCollector::EnabledScope scope(*Heap::From(GetHeap()),
StatsCollector::kAtomicCompact);
}
{
StatsCollector::EnabledScope scope(*Heap::From(GetHeap()),
StatsCollector::kAtomicSweep);
}
{
StatsCollector::EnabledConcurrentScope scope(
*Heap::From(GetHeap()), StatsCollector::kConcurrentMark);
}
{
StatsCollector::EnabledConcurrentScope scope(
*Heap::From(GetHeap()), StatsCollector::kConcurrentSweep);
}
EXPECT_EQ(0u, MetricRecorderImpl::CppGCMainThreadIncrementalMark_callcount);
EXPECT_EQ(0u, MetricRecorderImpl::CppGCMainThreadIncrementalSweep_callcount);
EXPECT_EQ(0u, MetricRecorderImpl::CppGCFullCycle_callcount);
EndGC(0);
}
TEST_F(MetricRecorderTest, CycleEndMetricsReportedOnGcEnd) {
MetricRecorderImpl::CppGCFullCycle_callcount = 0u;
MetricRecorderImpl::CppGCMainThreadIncrementalMark_callcount = 0u;
MetricRecorderImpl::CppGCMainThreadIncrementalSweep_callcount = 0u;
StartGC();
EndGC(0);
EXPECT_EQ(0u, MetricRecorderImpl::CppGCMainThreadIncrementalMark_callcount);
EXPECT_EQ(0u, MetricRecorderImpl::CppGCMainThreadIncrementalSweep_callcount);
EXPECT_EQ(1u, MetricRecorderImpl::CppGCFullCycle_callcount);
}
TEST_F(MetricRecorderTest, CycleEndHistogramReportsCorrectValues) {
StartGC();
EndGC(1000);
StartGC();
{
StatsCollector::EnabledScope scope(*Heap::From(GetHeap()),
StatsCollector::kIncrementalMark);
scope.DecreaseStartTimeForTesting(
v8::base::TimeDelta::FromMilliseconds(10));
}
{
StatsCollector::EnabledScope scope(*Heap::From(GetHeap()),
StatsCollector::kIncrementalSweep);
scope.DecreaseStartTimeForTesting(
v8::base::TimeDelta::FromMilliseconds(20));
}
{
StatsCollector::EnabledScope scope(*Heap::From(GetHeap()),
StatsCollector::kAtomicMark);
scope.DecreaseStartTimeForTesting(
v8::base::TimeDelta::FromMilliseconds(30));
}
{
StatsCollector::EnabledScope scope(*Heap::From(GetHeap()),
StatsCollector::kAtomicWeak);
scope.DecreaseStartTimeForTesting(
v8::base::TimeDelta::FromMilliseconds(50));
}
{
StatsCollector::EnabledScope scope(*Heap::From(GetHeap()),
StatsCollector::kAtomicCompact);
scope.DecreaseStartTimeForTesting(
v8::base::TimeDelta::FromMilliseconds(60));
}
{
StatsCollector::EnabledScope scope(*Heap::From(GetHeap()),
StatsCollector::kAtomicSweep);
scope.DecreaseStartTimeForTesting(
v8::base::TimeDelta::FromMilliseconds(70));
}
{
StatsCollector::EnabledConcurrentScope scope(
*Heap::From(GetHeap()), StatsCollector::kConcurrentMark);
scope.DecreaseStartTimeForTesting(
v8::base::TimeDelta::FromMilliseconds(80));
}
{
StatsCollector::EnabledConcurrentScope scope(
*Heap::From(GetHeap()), StatsCollector::kConcurrentSweep);
scope.DecreaseStartTimeForTesting(
v8::base::TimeDelta::FromMilliseconds(100));
}
EndGC(300);
// Check durations.
static constexpr int64_t kDurationComparisonTolerance = 500;
EXPECT_LT(std::abs(MetricRecorderImpl::CppGCFullCycle_event
.main_thread_incremental.mark_duration_us -
10000),
kDurationComparisonTolerance);
EXPECT_LT(std::abs(MetricRecorderImpl::CppGCFullCycle_event
.main_thread_incremental.sweep_duration_us -
20000),
kDurationComparisonTolerance);
EXPECT_LT(std::abs(MetricRecorderImpl::CppGCFullCycle_event.main_thread_atomic
.mark_duration_us -
30000),
kDurationComparisonTolerance);
EXPECT_LT(std::abs(MetricRecorderImpl::CppGCFullCycle_event.main_thread_atomic
.weak_duration_us -
50000),
kDurationComparisonTolerance);
EXPECT_LT(std::abs(MetricRecorderImpl::CppGCFullCycle_event.main_thread_atomic
.compact_duration_us -
60000),
kDurationComparisonTolerance);
EXPECT_LT(std::abs(MetricRecorderImpl::CppGCFullCycle_event.main_thread_atomic
.sweep_duration_us -
70000),
kDurationComparisonTolerance);
EXPECT_LT(std::abs(MetricRecorderImpl::CppGCFullCycle_event.main_thread
.mark_duration_us -
40000),
kDurationComparisonTolerance);
EXPECT_LT(std::abs(MetricRecorderImpl::CppGCFullCycle_event.main_thread
.weak_duration_us -
50000),
kDurationComparisonTolerance);
EXPECT_LT(std::abs(MetricRecorderImpl::CppGCFullCycle_event.main_thread
.compact_duration_us -
60000),
kDurationComparisonTolerance);
EXPECT_LT(std::abs(MetricRecorderImpl::CppGCFullCycle_event.main_thread
.sweep_duration_us -
90000),
kDurationComparisonTolerance);
EXPECT_LT(
std::abs(MetricRecorderImpl::CppGCFullCycle_event.total.mark_duration_us -
120000),
kDurationComparisonTolerance);
EXPECT_LT(
std::abs(MetricRecorderImpl::CppGCFullCycle_event.total.weak_duration_us -
50000),
kDurationComparisonTolerance);
EXPECT_LT(
std::abs(
MetricRecorderImpl::CppGCFullCycle_event.total.compact_duration_us -
60000),
kDurationComparisonTolerance);
EXPECT_LT(
std::abs(
MetricRecorderImpl::CppGCFullCycle_event.total.sweep_duration_us -
190000),
kDurationComparisonTolerance);
// Check collection rate and efficiency.
EXPECT_DOUBLE_EQ(
0.3, MetricRecorderImpl::CppGCFullCycle_event.collection_rate_in_percent);
static constexpr double kEfficiencyComparisonTolerance = 0.00001;
EXPECT_LT(
std::abs(
MetricRecorderImpl::CppGCFullCycle_event.efficiency_in_bytes_per_us -
(700.0 / (120000 + 50000 + 60000 + 190000))),
kEfficiencyComparisonTolerance);
EXPECT_LT(std::abs(MetricRecorderImpl::CppGCFullCycle_event
.main_thread_efficiency_in_bytes_per_us -
(700.0 / (40000 + 50000 + 60000 + 90000))),
kEfficiencyComparisonTolerance);
}
TEST_F(MetricRecorderTest, ObjectSizeMetricsNoAllocations) {
// Populate previous event.
StartGC();
EndGC(1000);
// Populate current event.
StartGC();
EndGC(800);
EXPECT_EQ(1000u,
MetricRecorderImpl::CppGCFullCycle_event.objects.before_bytes);
EXPECT_EQ(800u, MetricRecorderImpl::CppGCFullCycle_event.objects.after_bytes);
EXPECT_EQ(200u, MetricRecorderImpl::CppGCFullCycle_event.objects.freed_bytes);
EXPECT_EQ(0u, MetricRecorderImpl::CppGCFullCycle_event.memory.before_bytes);
EXPECT_EQ(0u, MetricRecorderImpl::CppGCFullCycle_event.memory.after_bytes);
EXPECT_EQ(0u, MetricRecorderImpl::CppGCFullCycle_event.memory.freed_bytes);
}
TEST_F(MetricRecorderTest, ObjectSizeMetricsWithAllocations) {
// Populate previous event.
StartGC();
EndGC(1000);
// Populate current event.
StartGC();
stats->NotifyAllocation(300);
stats->NotifyAllocatedMemory(1400);
stats->NotifyFreedMemory(700);
stats->NotifyMarkingCompleted(800);
stats->NotifyAllocation(150);
stats->NotifyAllocatedMemory(1000);
stats->NotifyFreedMemory(400);
stats->NotifySweepingCompleted();
EXPECT_EQ(1300u,
MetricRecorderImpl::CppGCFullCycle_event.objects.before_bytes);
EXPECT_EQ(800, MetricRecorderImpl::CppGCFullCycle_event.objects.after_bytes);
EXPECT_EQ(500u, MetricRecorderImpl::CppGCFullCycle_event.objects.freed_bytes);
EXPECT_EQ(700u, MetricRecorderImpl::CppGCFullCycle_event.memory.before_bytes);
EXPECT_EQ(300u, MetricRecorderImpl::CppGCFullCycle_event.memory.after_bytes);
EXPECT_EQ(400u, MetricRecorderImpl::CppGCFullCycle_event.memory.freed_bytes);
}
} // namespace internal
} // namespace cppgc