// 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/incremental-marking-schedule.h" #include "src/base/platform/time.h" #include "src/heap/cppgc/globals.h" #include "src/heap/cppgc/stats-collector.h" #include "testing/gtest/include/gtest/gtest.h" namespace cppgc { namespace internal { namespace { class IncrementalMarkingScheduleTest : public ::testing::Test { public: static const size_t kObjectSize; }; const size_t IncrementalMarkingScheduleTest::kObjectSize = 100 * IncrementalMarkingSchedule::kMinimumMarkedBytesPerIncrementalStep; } // namespace TEST_F(IncrementalMarkingScheduleTest, FirstStepReturnsDefaultDuration) { IncrementalMarkingSchedule schedule; schedule.NotifyIncrementalMarkingStart(); schedule.SetElapsedTimeForTesting(0); EXPECT_EQ(IncrementalMarkingSchedule::kMinimumMarkedBytesPerIncrementalStep, schedule.GetNextIncrementalStepDuration(kObjectSize)); } // If marking is not behind schedule and very small time passed between steps // the oracle should return the minimum step duration. TEST_F(IncrementalMarkingScheduleTest, NoTimePassedReturnsMinimumDuration) { IncrementalMarkingSchedule schedule; schedule.NotifyIncrementalMarkingStart(); // Add incrementally marked bytes to tell oracle this is not the first step. schedule.UpdateMutatorThreadMarkedBytes( IncrementalMarkingSchedule::kMinimumMarkedBytesPerIncrementalStep); schedule.SetElapsedTimeForTesting(0); EXPECT_EQ(IncrementalMarkingSchedule::kMinimumMarkedBytesPerIncrementalStep, schedule.GetNextIncrementalStepDuration(kObjectSize)); } TEST_F(IncrementalMarkingScheduleTest, OracleDoesntExccedMaximumStepDuration) { IncrementalMarkingSchedule schedule; schedule.NotifyIncrementalMarkingStart(); // Add incrementally marked bytes to tell oracle this is not the first step. static constexpr size_t kMarkedBytes = 1; schedule.UpdateMutatorThreadMarkedBytes(kMarkedBytes); schedule.SetElapsedTimeForTesting( IncrementalMarkingSchedule::kEstimatedMarkingTimeMs); EXPECT_EQ(kObjectSize - kMarkedBytes, schedule.GetNextIncrementalStepDuration(kObjectSize)); } TEST_F(IncrementalMarkingScheduleTest, AheadOfScheduleReturnsMinimumDuration) { IncrementalMarkingSchedule schedule; schedule.NotifyIncrementalMarkingStart(); // Add incrementally marked bytes to tell oracle this is not the first step. schedule.UpdateMutatorThreadMarkedBytes( IncrementalMarkingSchedule::kMinimumMarkedBytesPerIncrementalStep); schedule.AddConcurrentlyMarkedBytes(0.6 * kObjectSize); schedule.SetElapsedTimeForTesting( 0.5 * IncrementalMarkingSchedule::kEstimatedMarkingTimeMs); EXPECT_EQ(IncrementalMarkingSchedule::kMinimumMarkedBytesPerIncrementalStep, schedule.GetNextIncrementalStepDuration(kObjectSize)); } TEST_F(IncrementalMarkingScheduleTest, BehindScheduleReturnsCorrectDuration) { IncrementalMarkingSchedule schedule; schedule.NotifyIncrementalMarkingStart(); schedule.UpdateMutatorThreadMarkedBytes(0.1 * kObjectSize); schedule.AddConcurrentlyMarkedBytes(0.25 * kObjectSize); schedule.SetElapsedTimeForTesting( 0.5 * IncrementalMarkingSchedule::kEstimatedMarkingTimeMs); EXPECT_EQ(0.15 * kObjectSize, schedule.GetNextIncrementalStepDuration(kObjectSize)); schedule.AddConcurrentlyMarkedBytes(0.05 * kObjectSize); schedule.SetElapsedTimeForTesting( 0.5 * IncrementalMarkingSchedule::kEstimatedMarkingTimeMs); EXPECT_EQ(0.1 * kObjectSize, schedule.GetNextIncrementalStepDuration(kObjectSize)); schedule.AddConcurrentlyMarkedBytes(0.05 * kObjectSize); schedule.SetElapsedTimeForTesting( 0.5 * IncrementalMarkingSchedule::kEstimatedMarkingTimeMs); EXPECT_EQ(0.05 * kObjectSize, schedule.GetNextIncrementalStepDuration(kObjectSize)); } } // namespace internal } // namespace cppgc