File: thread_load_tracker.cc

package info (click to toggle)
chromium 138.0.7204.183-1
  • links: PTS, VCS
  • area: main
  • in suites: trixie
  • size: 6,071,908 kB
  • sloc: cpp: 34,937,088; ansic: 7,176,967; javascript: 4,110,704; python: 1,419,953; asm: 946,768; xml: 739,971; pascal: 187,324; sh: 89,623; perl: 88,663; objc: 79,944; sql: 50,304; cs: 41,786; fortran: 24,137; makefile: 21,806; php: 13,980; tcl: 13,166; yacc: 8,925; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (124 lines) | stat: -rw-r--r-- 3,716 bytes parent folder | download | duplicates (10)
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
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
// Copyright 2016 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "third_party/blink/renderer/platform/scheduler/common/thread_load_tracker.h"

#include <algorithm>

namespace blink {
namespace scheduler {

ThreadLoadTracker::ThreadLoadTracker(base::TimeTicks now,
                                     const Callback& callback,
                                     base::TimeDelta reporting_interval)
    : time_(now),
      thread_state_(ThreadState::kPaused),
      last_state_change_time_(now),
      reporting_interval_(reporting_interval),
      callback_(callback) {
  next_reporting_time_ = now + reporting_interval_;
}

ThreadLoadTracker::~ThreadLoadTracker() = default;

void ThreadLoadTracker::Pause(base::TimeTicks now) {
  Advance(now, TaskState::kIdle);
  thread_state_ = ThreadState::kPaused;

  Reset(now);
}

void ThreadLoadTracker::Resume(base::TimeTicks now) {
  Advance(now, TaskState::kIdle);
  thread_state_ = ThreadState::kActive;

  Reset(now);
}

void ThreadLoadTracker::Reset(base::TimeTicks now) {
  last_state_change_time_ = now;
  next_reporting_time_ = now + reporting_interval_;
  run_time_inside_window_ = base::TimeDelta();
}

void ThreadLoadTracker::RecordTaskTime(base::TimeTicks start_time,
                                       base::TimeTicks end_time) {
  start_time = std::max(last_state_change_time_, start_time);
  end_time = std::max(last_state_change_time_, end_time);

  Advance(start_time, TaskState::kIdle);
  Advance(end_time, TaskState::kTaskRunning);
}

void ThreadLoadTracker::RecordIdle(base::TimeTicks now) {
  Advance(now, TaskState::kIdle);
}

namespace {

// Calculates length of intersection of two time intervals.
base::TimeDelta Intersection(base::TimeTicks left1,
                             base::TimeTicks right1,
                             base::TimeTicks left2,
                             base::TimeTicks right2) {
  DCHECK_LT(left1, right1);
  DCHECK_LT(left2, right2);
  base::TimeTicks left = std::max(left1, left2);
  base::TimeTicks right = std::min(right1, right2);

  if (left <= right)
    return right - left;

  return base::TimeDelta();
}

}  // namespace

void ThreadLoadTracker::Advance(base::TimeTicks now, TaskState task_state) {
  // This function advances |time_| to now and calls |callback_|
  // when appropriate.
  DCHECK_LE(time_, now);

  if (thread_state_ == ThreadState::kPaused) {
    // If the load tracker is paused, bail out early.
    time_ = now;
    return;
  }

  while (time_ < now) {
    // Advance time_ to the earliest of following:
    // a) time to call |callback_|
    // b) requested time to forward (|now|).
    base::TimeTicks next_current_time = std::min(next_reporting_time_, now);

    base::TimeDelta delta = next_current_time - time_;

    // Keep a running total of the time spent running tasks within the window
    // and the total time.
    if (task_state == TaskState::kTaskRunning) {
      run_time_inside_window_ +=
          Intersection(next_reporting_time_ - reporting_interval_,
                       next_reporting_time_, time_, time_ + delta);
    }

    time_ = next_current_time;

    if (time_ == next_reporting_time_) {
      // Call |callback_| if need and update next callback time.
      if (thread_state_ == ThreadState::kActive) {
        callback_.Run(time_, Load());
        DCHECK_EQ(thread_state_, ThreadState::kActive);
      }
      next_reporting_time_ += reporting_interval_;
      run_time_inside_window_ = base::TimeDelta();
    }
  }
}

double ThreadLoadTracker::Load() {
  return run_time_inside_window_ / reporting_interval_;
}

}  // namespace scheduler
}  // namespace blink