File: measurement_delegates.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 (240 lines) | stat: -rw-r--r-- 9,754 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
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
// Copyright 2023 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef COMPONENTS_PERFORMANCE_MANAGER_TEST_SUPPORT_RESOURCE_ATTRIBUTION_MEASUREMENT_DELEGATES_H_
#define COMPONENTS_PERFORMANCE_MANAGER_TEST_SUPPORT_RESOURCE_ATTRIBUTION_MEASUREMENT_DELEGATES_H_

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

#include "base/functional/callback_forward.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/safe_ref.h"
#include "base/memory/weak_ptr.h"
#include "base/time/time.h"
#include "base/types/expected.h"
#include "base/types/pass_key.h"
#include "components/performance_manager/public/resource_attribution/cpu_measurement_delegate.h"
#include "components/performance_manager/public/resource_attribution/memory_measurement_delegate.h"

namespace performance_manager {
class ProcessNode;
}

namespace resource_attribution {

class SimulatedCPUMeasurementDelegate;

// The proportion of CPU used over time as a fraction, on the same scale as
// ProcessMetrics::GetPlatformIndependentCPUUsage: 0% to 100% *
// SysInfo::NumberOfProcessors().
//
// Since tests should be independent of the number of processors, it's usually
// convenient to use a range of 0.0 to 1.0 (for 100%), simulating a
// single-processor system. But if the code under test scales CPU measurements
// by SysInfo::NumberOfProcessors(), it's better to set the simulated usage to
// SysInfo::NumberOfProcessors() * a fraction, so that the code under test
// gets the same results after scaling on every system.
using SimulatedCPUUsage = double;

// A factory that manages SimulatedCPUMeasurementDelegate instances. Embed an
// instance of this in a unit test, and pass it to
// CPUMeasurementDelegate::SetDelegateFactoryForTesting(). The caller must
// ensure that the SimulatedCPUMeasurementDelegateFactory outlives all callers
// of CreateDelegateForProcess().
class SimulatedCPUMeasurementDelegateFactory final
    : public CPUMeasurementDelegate::Factory {
 public:
  using PassKey = base::PassKey<SimulatedCPUMeasurementDelegateFactory>;

  SimulatedCPUMeasurementDelegateFactory();
  ~SimulatedCPUMeasurementDelegateFactory() final;

  SimulatedCPUMeasurementDelegateFactory(
      const SimulatedCPUMeasurementDelegateFactory&) = delete;
  SimulatedCPUMeasurementDelegateFactory& operator=(
      const SimulatedCPUMeasurementDelegateFactory&) = delete;

  // Sets the default CPU usage reported by delegates created by this factory.
  // If this is not called, all delegates will report 100% CPU.
  void SetDefaultCPUUsage(SimulatedCPUUsage default_cpu_usage);

  // By default, delegates created by this factory can return simulated
  // measurements for ProcessNodes without a valid base::Process backing them.
  // This is useful because most tests use shim ProcessNodes and only need the
  // delegates to provide simple test data. Calling this with `require_valid`
  // true will apply all the valid process checks used in production, for tests
  // that do strict validation of CPU measurements.
  void SetRequireValidProcesses(bool require_valid);

  // Returns a delegate for `process_node`. This can be used to set initial
  // values on delegates before the code under test gets a pointer to them using
  // CreateDelegateForProcess().
  SimulatedCPUMeasurementDelegate& GetDelegate(
      const performance_manager::ProcessNode* process_node);

  // CPUMeasurementDelegate::Factory:

  bool ShouldMeasureProcess(
      const performance_manager::ProcessNode* process_node) final;

  std::unique_ptr<CPUMeasurementDelegate> CreateDelegateForProcess(
      const performance_manager::ProcessNode* process_node) final;

  // Private implementation guarded by PassKey:

  // Called by `delegate` when it's deleted.
  void OnDelegateDeleted(base::PassKey<SimulatedCPUMeasurementDelegate>,
                         SimulatedCPUMeasurementDelegate* delegate);

 private:
  // The default CPU usage of delegates created by this factory.
  SimulatedCPUUsage default_cpu_usage_ = 1.0;

  // If true, this factory won't create delegates for ProcessNodes without a
  // valid base::Process.
  bool require_valid_processes_ = false;

  // Map of ProcessNode to CPUMeasurementDelegate that simulates that process.
  // The delegates are owned by `pending_cpu_delegates_` when they're created,
  // then ownership is passed to the caller of TakeDelegate().
  std::map<const performance_manager::ProcessNode*,
           raw_ptr<SimulatedCPUMeasurementDelegate, CtnExperimental>>
      simulated_cpu_delegates_;

  // CPUMeasurementDelegates that have been created but not passed to the caller
  // of TakeDelegate() yet.
  std::map<const performance_manager::ProcessNode*,
           std::unique_ptr<SimulatedCPUMeasurementDelegate>>
      pending_cpu_delegates_;

  base::WeakPtrFactory<SimulatedCPUMeasurementDelegateFactory> weak_factory_{
      this};
};

// State of a simulated process for CPU measurements.
class SimulatedCPUMeasurementDelegate final : public CPUMeasurementDelegate {
 public:
  using PassKey = base::PassKey<SimulatedCPUMeasurementDelegate>;

  // Only SimulatedCPUMeasurementDelegateFactory can call the constructor.
  SimulatedCPUMeasurementDelegate(
      base::PassKey<SimulatedCPUMeasurementDelegateFactory>,
      base::SafeRef<SimulatedCPUMeasurementDelegateFactory> factory,
      SimulatedCPUUsage initial_usage);

  ~SimulatedCPUMeasurementDelegate() final;

  SimulatedCPUMeasurementDelegate(const SimulatedCPUMeasurementDelegate&) =
      delete;
  SimulatedCPUMeasurementDelegate& operator=(
      const SimulatedCPUMeasurementDelegate&) = delete;

  // Sets the CPU usage to `usage`, starting at `start_time` (which must be
  // later than any `start_time` previously used).
  void SetCPUUsage(SimulatedCPUUsage usage,
                   base::TimeTicks start_time = base::TimeTicks::Now());

  // Sets an error to report from GetCumulativeCPUUsage(). If `error` is
  // nullopt, GetCumulativeCPUUsage() will instead return a value accumulated
  // by calls to SetCPUUsage().
  void SetError(std::optional<ProcessCPUUsageError> error) { error_ = error; }

  // CPUMeasurementDelegate:

  // Returns the simulated CPU usage of the process by summing
  // `cpu_usage_periods`, or an error code if SetError() was called.
  base::expected<base::TimeDelta, ProcessCPUUsageError> GetCumulativeCPUUsage()
      final;

 private:
  struct CPUUsagePeriod {
    base::TimeTicks start_time;
    base::TimeTicks end_time;
    SimulatedCPUUsage cpu_usage;
  };

  // The factory that created this delegate. The factory's destructor CHECK's
  // that all delegates it created have already been destroyed.
  base::SafeRef<SimulatedCPUMeasurementDelegateFactory> factory_;

  // List of periods of varying CPU usage.
  std::vector<CPUUsagePeriod> cpu_usage_periods_;

  // If this is not nullopt, GetCumulativeCPUUsage() will ignore
  // `cpu_usage_periods` and return it as an error instead.
  std::optional<ProcessCPUUsageError> error_;
};

// A factory that manages FakeMemoryMeasurementDelegate instances. Embed an
// instance of this in a unit test, and pass it to
// MemoryMeasurementDelegate::SetDelegateFactoryForTesting(). The caller must
// ensure that the FakeMemoryMeasurementDelegateFactory outlives all callers
// of CreateDelegate().
class FakeMemoryMeasurementDelegateFactory final
    : public MemoryMeasurementDelegate::Factory {
 public:
  using PassKey = base::PassKey<FakeMemoryMeasurementDelegateFactory>;

  FakeMemoryMeasurementDelegateFactory();
  ~FakeMemoryMeasurementDelegateFactory() final;

  FakeMemoryMeasurementDelegateFactory(
      const FakeMemoryMeasurementDelegateFactory&) = delete;
  FakeMemoryMeasurementDelegateFactory& operator=(
      const FakeMemoryMeasurementDelegateFactory&) = delete;

  // Returns a reference to the map of memory measurements that will be returned
  // by delegates created by this factory. Callers can modify the map through
  // the reference. To simulate a measurement error, use an empty map.
  MemoryMeasurementDelegate::MemorySummaryMap& memory_summaries() {
    return memory_summaries_;
  }

  // MemoryMeasurementDelegate::Factory:

  std::unique_ptr<MemoryMeasurementDelegate> CreateDelegate(
      performance_manager::Graph*) final;

 private:
  // The MemorySummary results returned by delegates created by this factory.
  MemoryMeasurementDelegate::MemorySummaryMap memory_summaries_;

  base::WeakPtrFactory<FakeMemoryMeasurementDelegateFactory> weak_factory_{
      this};
};

// A MemoryMeasurementDelegate that returns fake results.
class FakeMemoryMeasurementDelegate final : public MemoryMeasurementDelegate {
 public:
  using PassKey = base::PassKey<FakeMemoryMeasurementDelegate>;

  // Only FakeMemoryMeasurementDelegateFactory can call the constructor.
  FakeMemoryMeasurementDelegate(
      base::PassKey<FakeMemoryMeasurementDelegateFactory>,
      base::SafeRef<FakeMemoryMeasurementDelegateFactory> factory);

  ~FakeMemoryMeasurementDelegate() final;

  FakeMemoryMeasurementDelegate(const FakeMemoryMeasurementDelegate&) = delete;
  FakeMemoryMeasurementDelegate& operator=(
      const FakeMemoryMeasurementDelegate&) = delete;

  // MemoryMeasurementDelegate:

  // Invokes `callback` with the fake measurements returned by
  // FakeMemoryMeasurementDelegateFactory::memory_summaries().
  void RequestMemorySummary(
      base::OnceCallback<void(MemorySummaryMap)> callback) final;

 private:
  // The factory that created this delegate.
  base::SafeRef<FakeMemoryMeasurementDelegateFactory> factory_;
};

}  // namespace resource_attribution

#endif  // COMPONENTS_PERFORMANCE_MANAGER_TEST_SUPPORT_RESOURCE_ATTRIBUTION_MEASUREMENT_DELEGATES_H_