11cb0ef41Sopenharmony_ci// Copyright 2020 the V8 project authors. All rights reserved. 21cb0ef41Sopenharmony_ci// Use of this source code is governed by a BSD-style license that can be 31cb0ef41Sopenharmony_ci// found in the LICENSE file. 41cb0ef41Sopenharmony_ci 51cb0ef41Sopenharmony_ci#include "src/heap/cppgc/incremental-marking-schedule.h" 61cb0ef41Sopenharmony_ci 71cb0ef41Sopenharmony_ci#include <cmath> 81cb0ef41Sopenharmony_ci 91cb0ef41Sopenharmony_ci#include "src/heap/cppgc/globals.h" 101cb0ef41Sopenharmony_ci 111cb0ef41Sopenharmony_cinamespace cppgc { 121cb0ef41Sopenharmony_cinamespace internal { 131cb0ef41Sopenharmony_ci 141cb0ef41Sopenharmony_ci// static 151cb0ef41Sopenharmony_ciconstexpr size_t IncrementalMarkingSchedule::kInvalidLastEstimatedLiveBytes; 161cb0ef41Sopenharmony_ci 171cb0ef41Sopenharmony_ciconst double IncrementalMarkingSchedule::kEstimatedMarkingTimeMs = 500.0; 181cb0ef41Sopenharmony_ciconst size_t IncrementalMarkingSchedule::kMinimumMarkedBytesPerIncrementalStep = 191cb0ef41Sopenharmony_ci 64 * kKB; 201cb0ef41Sopenharmony_ci 211cb0ef41Sopenharmony_civoid IncrementalMarkingSchedule::NotifyIncrementalMarkingStart() { 221cb0ef41Sopenharmony_ci DCHECK(incremental_marking_start_time_.IsNull()); 231cb0ef41Sopenharmony_ci incremental_marking_start_time_ = v8::base::TimeTicks::Now(); 241cb0ef41Sopenharmony_ci} 251cb0ef41Sopenharmony_ci 261cb0ef41Sopenharmony_civoid IncrementalMarkingSchedule::UpdateMutatorThreadMarkedBytes( 271cb0ef41Sopenharmony_ci size_t overall_marked_bytes) { 281cb0ef41Sopenharmony_ci mutator_thread_marked_bytes_ = overall_marked_bytes; 291cb0ef41Sopenharmony_ci} 301cb0ef41Sopenharmony_ci 311cb0ef41Sopenharmony_civoid IncrementalMarkingSchedule::AddConcurrentlyMarkedBytes( 321cb0ef41Sopenharmony_ci size_t marked_bytes) { 331cb0ef41Sopenharmony_ci concurrently_marked_bytes_.fetch_add(marked_bytes, std::memory_order_relaxed); 341cb0ef41Sopenharmony_ci} 351cb0ef41Sopenharmony_ci 361cb0ef41Sopenharmony_cisize_t IncrementalMarkingSchedule::GetOverallMarkedBytes() const { 371cb0ef41Sopenharmony_ci return mutator_thread_marked_bytes_ + GetConcurrentlyMarkedBytes(); 381cb0ef41Sopenharmony_ci} 391cb0ef41Sopenharmony_ci 401cb0ef41Sopenharmony_cisize_t IncrementalMarkingSchedule::GetConcurrentlyMarkedBytes() const { 411cb0ef41Sopenharmony_ci return concurrently_marked_bytes_.load(std::memory_order_relaxed); 421cb0ef41Sopenharmony_ci} 431cb0ef41Sopenharmony_ci 441cb0ef41Sopenharmony_cidouble IncrementalMarkingSchedule::GetElapsedTimeInMs( 451cb0ef41Sopenharmony_ci v8::base::TimeTicks start_time) { 461cb0ef41Sopenharmony_ci if (elapsed_time_for_testing_ != kNoSetElapsedTimeForTesting) { 471cb0ef41Sopenharmony_ci double elapsed_time = elapsed_time_for_testing_; 481cb0ef41Sopenharmony_ci elapsed_time_for_testing_ = kNoSetElapsedTimeForTesting; 491cb0ef41Sopenharmony_ci return elapsed_time; 501cb0ef41Sopenharmony_ci } 511cb0ef41Sopenharmony_ci return (v8::base::TimeTicks::Now() - start_time).InMillisecondsF(); 521cb0ef41Sopenharmony_ci} 531cb0ef41Sopenharmony_ci 541cb0ef41Sopenharmony_cisize_t IncrementalMarkingSchedule::GetNextIncrementalStepDuration( 551cb0ef41Sopenharmony_ci size_t estimated_live_bytes) { 561cb0ef41Sopenharmony_ci last_estimated_live_bytes_ = estimated_live_bytes; 571cb0ef41Sopenharmony_ci DCHECK(!incremental_marking_start_time_.IsNull()); 581cb0ef41Sopenharmony_ci double elapsed_time_in_ms = 591cb0ef41Sopenharmony_ci GetElapsedTimeInMs(incremental_marking_start_time_); 601cb0ef41Sopenharmony_ci size_t actual_marked_bytes = GetOverallMarkedBytes(); 611cb0ef41Sopenharmony_ci size_t expected_marked_bytes = std::ceil( 621cb0ef41Sopenharmony_ci estimated_live_bytes * elapsed_time_in_ms / kEstimatedMarkingTimeMs); 631cb0ef41Sopenharmony_ci if (expected_marked_bytes < actual_marked_bytes) { 641cb0ef41Sopenharmony_ci // Marking is ahead of schedule, incremental marking should do the minimum. 651cb0ef41Sopenharmony_ci return kMinimumMarkedBytesPerIncrementalStep; 661cb0ef41Sopenharmony_ci } 671cb0ef41Sopenharmony_ci // Assuming marking will take |kEstimatedMarkingTime|, overall there will 681cb0ef41Sopenharmony_ci // be |estimated_live_bytes| live bytes to mark, and that marking speed is 691cb0ef41Sopenharmony_ci // constant, after |elapsed_time| the number of marked_bytes should be 701cb0ef41Sopenharmony_ci // |estimated_live_bytes| * (|elapsed_time| / |kEstimatedMarkingTime|), 711cb0ef41Sopenharmony_ci // denoted as |expected_marked_bytes|. If |actual_marked_bytes| is less, 721cb0ef41Sopenharmony_ci // i.e. marking is behind schedule, incremental marking should help "catch 731cb0ef41Sopenharmony_ci // up" by marking (|expected_marked_bytes| - |actual_marked_bytes|). 741cb0ef41Sopenharmony_ci return std::max(kMinimumMarkedBytesPerIncrementalStep, 751cb0ef41Sopenharmony_ci expected_marked_bytes - actual_marked_bytes); 761cb0ef41Sopenharmony_ci} 771cb0ef41Sopenharmony_ci 781cb0ef41Sopenharmony_ciconstexpr double 791cb0ef41Sopenharmony_ci IncrementalMarkingSchedule::kEphemeronPairsFlushingRatioIncrements; 801cb0ef41Sopenharmony_cibool IncrementalMarkingSchedule::ShouldFlushEphemeronPairs() { 811cb0ef41Sopenharmony_ci DCHECK_NE(kInvalidLastEstimatedLiveBytes, last_estimated_live_bytes_); 821cb0ef41Sopenharmony_ci if (GetOverallMarkedBytes() < 831cb0ef41Sopenharmony_ci (ephemeron_pairs_flushing_ratio_target * last_estimated_live_bytes_)) 841cb0ef41Sopenharmony_ci return false; 851cb0ef41Sopenharmony_ci ephemeron_pairs_flushing_ratio_target += 861cb0ef41Sopenharmony_ci kEphemeronPairsFlushingRatioIncrements; 871cb0ef41Sopenharmony_ci return true; 881cb0ef41Sopenharmony_ci} 891cb0ef41Sopenharmony_ci 901cb0ef41Sopenharmony_ci} // namespace internal 911cb0ef41Sopenharmony_ci} // namespace cppgc 92