File: cpu_health_tracker.h

package info (click to toggle)
chromium 139.0.7258.127-1
  • links: PTS, VCS
  • area: main
  • in suites:
  • size: 6,122,068 kB
  • sloc: cpp: 35,100,771; ansic: 7,163,530; javascript: 4,103,002; python: 1,436,920; asm: 946,517; xml: 746,709; pascal: 187,653; perl: 88,691; sh: 88,436; objc: 79,953; sql: 51,488; cs: 44,583; fortran: 24,137; makefile: 22,147; tcl: 15,277; php: 13,980; yacc: 8,984; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (155 lines) | stat: -rw-r--r-- 6,861 bytes parent folder | download | duplicates (6)
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
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
// Copyright 2024 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef CHROME_BROWSER_PERFORMANCE_MANAGER_USER_TUNING_CPU_HEALTH_TRACKER_H_
#define CHROME_BROWSER_PERFORMANCE_MANAGER_USER_TUNING_CPU_HEALTH_TRACKER_H_

#include <map>
#include <optional>
#include <vector>

#include "base/containers/circular_deque.h"
#include "base/containers/flat_map.h"
#include "base/functional/callback_forward.h"
#include "base/memory/weak_ptr.h"
#include "base/time/time.h"
#include "base/timer/timer.h"
#include "base/types/strong_alias.h"
#include "chrome/browser/performance_manager/public/user_tuning/performance_detection_manager.h"
#include "components/performance_manager/public/graph/graph_registered.h"
#include "components/performance_manager/public/resource_attribution/cpu_proportion_tracker.h"
#include "components/performance_manager/public/resource_attribution/page_context.h"
#include "components/performance_manager/public/resource_attribution/queries.h"
#include "components/performance_manager/public/resource_attribution/query_results.h"
#include "components/system_cpu/cpu_probe.h"
#include "content/public/browser/resource_context.h"

namespace performance_manager::user_tuning {

class CpuHealthTracker
    : public performance_manager::GraphOwnedAndRegistered<CpuHealthTracker> {
 public:
  using ResourceType = PerformanceDetectionManager::ResourceType;
  using HealthLevel = PerformanceDetectionManager::HealthLevel;
  using ActionableTabsResult =
      PerformanceDetectionManager::ActionableTabsResult;
  using StatusChangeCallback =
      base::RepeatingCallback<void(ResourceType, HealthLevel, bool)>;
  using ActionableTabResultCallback =
      base::RepeatingCallback<void(ResourceType, ActionableTabsResult)>;
  using CpuPercent = base::StrongAlias<class CpuPercentTag, int>;

  CpuHealthTracker(StatusChangeCallback on_status_change_cb,
                   ActionableTabResultCallback on_actionability_change_cb);
  ~CpuHealthTracker() override;

  // This represents the duration that CPU must be over the threshold before
  // a notification is triggered.
  static constexpr base::TimeDelta kCPUTimeOverThreshold = base::Seconds(60);

  // Frequency to sample for cpu usage to ensure that the user is experiencing
  // consistent cpu issues before surfacing a notification.
  static constexpr base::TimeDelta kCPUSampleFrequency = base::Seconds(15);

  // If the system CPU consistently exceeds these percent thresholds, then
  // the CPU health will be classified as the threshold it is exceeding.
  static constexpr int kCPUDegradedHealthPercentageThreshold = 50;
  static constexpr int kCPUUnhealthyPercentageThreshold = 75;

  // Maximum number of tabs to be actionable.
  static constexpr int kCPUMaxActionableTabs = 4;

  // Minimum percentage to improve CPU health for a tab to be actionable.
  static constexpr int kMinimumActionableTabCPUPercentage = 10;

  HealthLevel GetCurrentHealthLevel();

  int GetTotalCpuPercentUsage(ActionableTabsResult tabs);

  // Queries and process tab CPU data. This data is recorded and may invoke the
  // status change and actionability change callback if the processed tab CPU
  // data meets the criteria to be actionable.
  void QueryAndProcessTabActionability(
      std::optional<CpuPercent> system_cpu_usage_percentage);

 private:
  friend class CpuHealthTrackerTestHelper;
  friend class CpuHealthTrackerTest;
  friend class CpuHealthTrackerBrowserTest;
  FRIEND_TEST_ALL_PREFIXES(CpuHealthTrackerTest,
                           RecordCpuAndUpdateHealthStatus);
  FRIEND_TEST_ALL_PREFIXES(CpuHealthTrackerTest, HealthyCpuUsageFromProbe);
  FRIEND_TEST_ALL_PREFIXES(CpuHealthTrackerBrowserTest,
                           PagesMeetMinimumCpuUsage);

  using PageResourceMeasurements =
      base::flat_map<resource_attribution::PageContext, CpuPercent>;

  base::OnceCallback<void(ActionableTabsResult)>
  GetStatusAndActionabilityCallback(bool did_status_change,
                                    HealthLevel health_level);

  // Returns the health level associated with the measurement
  HealthLevel GetHealthLevelForMeasurement(CpuPercent measurement);

  // Calls `callback` with a vector of actionable tabs that is determined from
  // 'unfiltered_measurements'.
  void GetFilteredActionableTabs(
      PageResourceMeasurements unfiltered_measurements,
      CpuPercent recent_measurement,
      base::OnceCallback<void(ActionableTabsResult)> callback);

  // Keeps track of the given measurement and potentially update the health
  // level if the tracker consistently records that level
  bool RecordAndUpdateHealthStatus(CpuPercent measurement);

  void ProcessCpuProbeResult(std::optional<system_cpu::CpuSample> cpu_sample);

  // Processes 'results' and notifies observers if the health status changes
  void ProcessQueryResultMap(
      CpuPercent system_cpu_usage_percentage,
      const resource_attribution::QueryResultMap& results);

  // Filter 'page_cpu' for pages that meet the minimum CPU usage to be
  // actionable and returns the result as a map of page contexts with its
  // corresponding CPU usage percentage. CPU usage percentages are converted
  // to range from 0-100%.
  PageResourceMeasurements FilterForPossibleActionablePages(
      std::map<resource_attribution::ResourceContext, double> page_cpu);

  bool CanDiscardPage(resource_attribution::PageContext context);

  // Health tracker automatically call these callbacks after CPU metrics
  // refreshes and the status or tab actionability changes.
  StatusChangeCallback status_change_cb_;
  ActionableTabResultCallback actionable_tabs_cb_;

  ActionableTabsResult actionable_tabs_;

  // Map containing all non-off record tab page contexts and their
  // corresponding resource measurements since the last measurement interval.
  // Some tabs are not actionable since their CPU usage may be lower than
  // the minimum to be considered as actionable.
  PageResourceMeasurements tab_page_measurements_;

  // Number of samples in a time window being used to consider the new health
  // status.
  const size_t cpu_health_sample_window_size_;

  const bool is_demo_mode_;

  // Recent resource measurements used to determine overall resource health.
  base::circular_deque<CpuPercent> recent_resource_measurements_;
  CpuPercent min_resource_measurement_ = CpuPercent(0);

  resource_attribution::ScopedResourceUsageQuery scoped_cpu_query_;
  HealthLevel current_health_status_ = HealthLevel::kHealthy;
  base::RepeatingTimer cpu_probe_timer_;
  resource_attribution::CPUProportionTracker page_cpu_proportion_tracker_;
  base::WeakPtrFactory<CpuHealthTracker> weak_ptr_factory_{this};
};

}  // namespace performance_manager::user_tuning

#endif  // CHROME_BROWSER_PERFORMANCE_MANAGER_USER_TUNING_CPU_HEALTH_TRACKER_H_