summaryrefslogtreecommitdiff
path: root/deps/v8/src/heap/cppgc/incremental-marking-schedule.cc
blob: 7e1ff951ab7b742610c8274240556c8e8d0cd4c3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
// 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 <cmath>

#include "src/heap/cppgc/globals.h"

namespace cppgc {
namespace internal {

const double IncrementalMarkingSchedule::kEstimatedMarkingTimeMs = 500.0;
const size_t IncrementalMarkingSchedule::kMinimumMarkedBytesPerIncrementalStep =
    64 * kKB;

void IncrementalMarkingSchedule::NotifyIncrementalMarkingStart() {
  DCHECK(incremental_marking_start_time_.IsNull());
  incremental_marking_start_time_ = v8::base::TimeTicks::Now();
}

void IncrementalMarkingSchedule::UpdateIncrementalMarkedBytes(
    size_t overall_marked_bytes) {
  DCHECK(!incremental_marking_start_time_.IsNull());
  incrementally_marked_bytes_ = overall_marked_bytes;
}

void IncrementalMarkingSchedule::AddConcurrentlyMarkedBytes(
    size_t marked_bytes) {
  DCHECK(!incremental_marking_start_time_.IsNull());
  concurrently_marked_bytes_.fetch_add(marked_bytes, std::memory_order_relaxed);
}

size_t IncrementalMarkingSchedule::GetOverallMarkedBytes() {
  return incrementally_marked_bytes_ +
         concurrently_marked_bytes_.load(std::memory_order_relaxed);
}

double IncrementalMarkingSchedule::GetElapsedTimeInMs(
    v8::base::TimeTicks start_time) {
  if (elapsed_time_for_testing_ != kNoSetElapsedTimeForTesting) {
    double elapsed_time = elapsed_time_for_testing_;
    elapsed_time_for_testing_ = kNoSetElapsedTimeForTesting;
    return elapsed_time;
  }
  return (v8::base::TimeTicks::Now() - start_time).InMillisecondsF();
}

size_t IncrementalMarkingSchedule::GetNextIncrementalStepDuration(
    size_t estimated_live_bytes) {
  DCHECK(!incremental_marking_start_time_.IsNull());
  double elapsed_time_in_ms =
      GetElapsedTimeInMs(incremental_marking_start_time_);
  size_t actual_marked_bytes = GetOverallMarkedBytes();
  size_t expected_marked_bytes = std::ceil(
      estimated_live_bytes * elapsed_time_in_ms / kEstimatedMarkingTimeMs);
  if (expected_marked_bytes < actual_marked_bytes) {
    // Marking is ahead of schedule, incremental marking should do the minimum.
    return kMinimumMarkedBytesPerIncrementalStep;
  }
  // Assuming marking will take |kEstimatedMarkingTime|, overall there will
  // be |estimated_live_bytes| live bytes to mark, and that marking speed is
  // constant, after |elapsed_time| the number of marked_bytes should be
  // |estimated_live_bytes| * (|elapsed_time| / |kEstimatedMarkingTime|),
  // denoted as |expected_marked_bytes|.  If |actual_marked_bytes| is less,
  // i.e. marking is behind schedule, incremental marking should help "catch
  // up" by marking (|expected_marked_bytes| - |actual_marked_bytes|).
  return std::max(kMinimumMarkedBytesPerIncrementalStep,
                  expected_marked_bytes - actual_marked_bytes);
}

}  // namespace internal
}  // namespace cppgc