File: perf_events_collector.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 (210 lines) | stat: -rw-r--r-- 7,529 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
// Copyright 2018 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_METRICS_PERF_PERF_EVENTS_COLLECTOR_H_
#define CHROME_BROWSER_METRICS_PERF_PERF_EVENTS_COLLECTOR_H_

#include <map>
#include <memory>
#include <string>
#include <string_view>
#include <vector>

#include "base/time/time.h"
#include "chrome/browser/metrics/perf/metric_collector.h"
#include "chrome/browser/metrics/perf/perf_output.h"
#include "chrome/browser/metrics/perf/random_selector.h"
#include "third_party/metrics_proto/sampled_profile.pb.h"
#include "third_party/metrics_proto/system_profile.pb.h"

namespace ash {
class DebugDaemonClientProvider;
}

namespace base {
class SequencedTaskRunner;
}

namespace metrics {

struct CPUIdentity;
class WindowedIncognitoObserver;

// Enables collection of perf events profile data. perf aka "perf events" is a
// performance profiling infrastructure built into the linux kernel. For more
// information, see: https://perf.wiki.kernel.org/index.php/Main_Page.
class PerfCollector : public internal::MetricCollector {
 public:
  PerfCollector();

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

  // MetricCollector:
  ~PerfCollector() override;
  const char* ToolName() const override;

 protected:
  // For testing to mock PerfOutputCall.
  virtual std::unique_ptr<PerfOutputCall> CreatePerfOutputCall(
      const std::vector<std::string>& quipper_args,
      bool disable_cpu_idle,
      PerfOutputCall::DoneCallback callback);

  void OnPerfOutputComplete(
      std::unique_ptr<WindowedIncognitoObserver> incognito_observer,
      std::unique_ptr<SampledProfile> sampled_profile,
      bool has_cycles,
      std::string perf_stdout);

  // Parses a PerfDataProto from serialized data |perf_stdout|, if non-empty.
  // If |perf_stdout| is empty, it is counted as an error. |incognito_observer|
  // indicates whether an incognito window had been opened during the profile
  // collection period. If there was an incognito window, discard the incoming
  // data.
  void ParseOutputProtoIfValid(
      std::unique_ptr<WindowedIncognitoObserver> incognito_observer,
      std::unique_ptr<SampledProfile> sampled_profile,
      bool has_cycles,
      std::string perf_stdout);

  // MetricCollector:
  void SetUp() override;
  base::WeakPtr<internal::MetricCollector> GetWeakPtr() override;
  bool ShouldCollect() const override;
  void CollectProfile(std::unique_ptr<SampledProfile> sampled_profile) override;
  void StopCollection() override;

  const RandomSelector& command_selector() const { return command_selector_; }

  // Collects both Ash and Lacros Chrome process and thread types.
  static void CollectProcessTypes(SampledProfile* sampled_profile);

  // Executes asynchronously on another thread pool and retries with a delay if
  // all frequencies couldn't be read. Posts a task on the given task_runner
  // after each attempt.
  static void ParseCPUFrequencies(
      scoped_refptr<base::SequencedTaskRunner> task_runner,
      base::WeakPtr<PerfCollector> perf_collector,
      int attempt,
      int max_retries);
  // Saves the given frequencies to |max_frequencies_mhz_|.
  void SaveCPUFrequencies(const std::vector<uint32_t>& frequencies);

  const std::vector<uint32_t>& max_frequencies_mhz() const {
    return max_frequencies_mhz_;
  }

  // Enumeration representing success and various failure modes for parsing CPU
  // frequencies. These values are persisted to logs. Entries should not be
  // renumbered and numeric values should never be reused.
  enum class ParseFrequencyStatus {
    kSuccess,
    kNumCPUsIsZero,
    kSomeZeroCPUFrequencies,
    kAllZeroCPUFrequencies,
    kSuccessOnRetry,
    kNumCPUsMoreThanPossible,
    // Magic constant used by the histogram macros.
    kMaxValue = kNumCPUsMoreThanPossible,
  };

  // Extracts the |lacros_channel| and |lacros_version| from |lacros_path|.
  static bool LacrosChannelAndVersion(
      std::string_view lacros_path,
      metrics::SystemProfileProto_Channel& lacros_channel,
      std::string& lacros_version);

  // Enumeration of various locations gotten from parsing a Lacros binary path.
  // This is used to monitor any change to the Lacros path.
  enum class ParseLacrosPath {
    kRootfs,
    kStateful,
    kUnrecognized,
    // Magic constant used by the histogram macros.
    kMaxValue = kUnrecognized,
  };

  // Annotations on the collected sampled_profile, including adding process
  // types and PSI CPU data.
  static void PostCollectionProfileAnnotation(SampledProfile* sampled_profile,
                                              bool has_cycles);

  // Collect PSI CPU data and add to sampled_profile.
  static void CollectPSICPU(SampledProfile* sampled_profile,
                            const std::string& psi_cpu_path);

  // Enumeration representing success and various failure modes for parsing PSI
  // CPU data. These values are persisted to logs. Entries should not be
  // renumbered and numeric values should never be reused.
  enum class ParsePSICPUStatus {
    kSuccess,
    kReadFileFailed,
    kUnexpectedDataFormat,
    kParsePSIValueFailed,
    // Magic constant used by the histogram macros.
    kMaxValue = kParsePSIValueFailed,
  };

  SampledProfile::TriggerEvent current_trigger_ =
      SampledProfile::UNKNOWN_TRIGGER_EVENT;

  // Enumeration representing event types that need additional treatment
  // during or after the collection.
  enum class EventType {
    kOther,
    kCycles,
    kETM,
  };
  static EventType CommandEventType(const std::vector<std::string>& args);

 private:
  // Change the values in |collection_params_| and the commands in
  // |command_selector| for any keys that are present in |params|.
  void SetCollectionParamsFromVariationParams(
      const std::map<std::string, std::string>& params);

  // Set of commands to choose from.
  RandomSelector command_selector_;

  // |debugd_client_provider_| hosts the private DBus connection to debugd.
  std::unique_ptr<ash::DebugDaemonClientProvider> debugd_client_provider_;

  // An active call to perf/quipper, if set.
  std::unique_ptr<PerfOutputCall> perf_output_call_;

  // Vector of max frequencies associated with each logical CPU. Computed
  // asynchronously at start.
  std::vector<uint32_t> max_frequencies_mhz_;

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

// Exposed for unit testing.
namespace internal {

// Return the default set of perf commands and their odds of selection given
// the identity of the CPU in |cpuid|.
std::vector<RandomSelector::WeightAndValue> GetDefaultCommandsForCpuModel(
    const CPUIdentity& cpuid,
    const std::string& model);

// For the "PerfCommand::"-prefixed keys in |params|, return the cpu specifier
// that is the narrowest match for the CPU identified by |cpuid|.
// Valid CPU specifiers, in increasing order of specificity, are:
// "default", a system architecture (e.g. "x86_64"), a CPU microarchitecture
// (currently only some Intel and AMD uarchs supported), or a CPU model name
// substring.
std::string FindBestCpuSpecifierFromParams(
    const std::map<std::string, std::string>& params,
    const CPUIdentity& cpuid);

// Returns if the given perf command samples CPU cycles.
bool CommandSamplesCPUCycles(const std::vector<std::string>& args);

}  // namespace internal

}  // namespace metrics

#endif  // CHROME_BROWSER_METRICS_PERF_PERF_EVENTS_COLLECTOR_H_