• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  * Copyright (c) 2024 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #ifndef PANDA_RUNTIME_TOOLING_PERF_COUNTER_H
17 #define PANDA_RUNTIME_TOOLING_PERF_COUNTER_H
18 
19 #include <memory>
20 #include <vector>
21 #include <unordered_map>
22 #include <cstring>
23 #include <optional>
24 
25 #include "libpandabase/os/time.h"
26 #include "libpandabase/utils/logger.h"
27 #include "libpandabase/utils/type_converter.h"
28 
29 #include <unistd.h>
30 #include <linux/perf_event.h>
31 #include <linux/hw_breakpoint.h>
32 #include <sys/syscall.h>
33 #include <sys/ioctl.h>
34 
35 namespace ark::tooling {
36 
37 /*
38   See perf_counter.md
39  */
40 
41 class CounterValue {
42 public:
43     static CounterValue CreateUnavailable();
44     static CounterValue CreateExact(uint64_t value);
45     static CounterValue CreateApprox(uint64_t value, double accuracy);
46 
47     uint64_t GetValue() const;
48     bool IsExact() const;
49     bool IsAvailable() const;
50     double GetAccuracy() const;
51 
52 private:
53     CounterValue(uint64_t value, bool exact, bool available, double accuracy);
54     uint64_t value_;
55     bool exact_;
56     bool available_;
57     double accuracy_;
58 };
59 
60 class CounterAccumulator {
61 public:
62     void Reset();
63     void Add(uint64_t value);
64     void AddMissing();
65     CounterValue GetValue() const;
66     bool IsAvailable() const;
67     bool HasMissing() const;
68     uint64_t GetExact() const;
69     uint64_t GetApprox() const;
70     double GetAccuracy() const;
71 
72 private:
73     std::atomic_uint64_t value_ {};
74     std::atomic_uint64_t missing_ {};
75     std::atomic_uint64_t total_ {};
76 };
77 
78 class PerfFileHandler {
79 public:
80     ~PerfFileHandler();
81 
82     NO_COPY_SEMANTIC(PerfFileHandler);
83 
84     PerfFileHandler(PerfFileHandler &&other);
85     PerfFileHandler &operator=(PerfFileHandler &&other);
86 
87     void Reset();
88     void Enable();
89     void Disable();
90 
91     std::optional<uint64_t> GetData() const;
92 
93 private:
94     static int OpenDescriptor(uint32_t type, uint64_t config);
95     PerfFileHandler(uint32_t type, uint64_t config);
96     int fd_;
97     friend class PerfCounterDescriptor;
98 };
99 
100 class Perf;
101 class PerfCounterDescriptor;
102 
103 class PerfCollector {
104 public:
105     NO_MOVE_SEMANTIC(PerfCollector);
106     NO_COPY_SEMANTIC(PerfCollector);
107 
108     PerfCollector(Perf *p, std::vector<const PerfCounterDescriptor *> &list, bool isWallTime);
109     ~PerfCollector();
110 
111     void Reset();
112     void Enable();
113     void Disable();
114 
115 private:
116     Perf *perf_;
117     std::unordered_map<const PerfCounterDescriptor *, PerfFileHandler> counters_;
118     bool isWallTime_ {false};
119     uint64_t startTime_;
120 };
121 
122 class CounterReporter;
123 
124 class PerfCounterDescriptor {
125 public:
126     NO_COPY_SEMANTIC(PerfCounterDescriptor);
127     NO_MOVE_SEMANTIC(PerfCounterDescriptor);
128 
129     ~PerfCounterDescriptor() = default;
130 
131     PerfFileHandler CreatePerfFileHandler() const;
132 
133     const char *GetName() const;
134     void Report(std::ostream &out, const Perf *p) const;
135 
136     static const PerfCounterDescriptor TASK_CLOCK;
137     static const PerfCounterDescriptor CONTEXT_SWITCHES;
138     static const PerfCounterDescriptor CPU_MIGRATION;
139     static const PerfCounterDescriptor PAGE_FAULT;
140     static const PerfCounterDescriptor TOTAL_CPU_CYCLES;
141     static const PerfCounterDescriptor STALLED_FRONTEND_CYCLES;
142     static const PerfCounterDescriptor STALLED_BACKEND_CYCLES;
143     static const PerfCounterDescriptor INSTRUCTIONS_COUNT;
144     static const PerfCounterDescriptor BRANCHES;
145     static const PerfCounterDescriptor BRANCH_MISSES;
146     static const PerfCounterDescriptor COUNT;
147 
148 private:
149     PerfCounterDescriptor(const char *name, uint32_t type, uint64_t config, std::unique_ptr<CounterReporter> reporter);
150 
151     const char *name_;
152     uint32_t type_;
153     uint64_t config_;
154     std::unique_ptr<CounterReporter> reporter_;
155 };
156 
157 class Perf {
158 public:
159     Perf();
160     Perf(std::initializer_list<const PerfCounterDescriptor *> list);
161     ~Perf() = default;
162 
163     NO_COPY_SEMANTIC(Perf);
164     NO_MOVE_SEMANTIC(Perf);
165 
166     PerfCollector CreateCollector(bool isWallTime = false);
167     void Reset();
168     void Add(const PerfCounterDescriptor *desc, uint64_t value);
169     void AddMissing(const PerfCounterDescriptor *desc);
170     void AddWallTime(uint64_t time);
171     CounterValue Get(const PerfCounterDescriptor *desc) const;
172     void Report(std::ostream &out) const;
173 
174 private:
175     std::vector<const PerfCounterDescriptor *> perfDescriptors_;
176     std::unordered_map<const PerfCounterDescriptor *, CounterAccumulator> counters_;
177     uint64_t wallTime_ {0};
178 };
179 
180 std::ostream &operator<<(std::ostream &out, const Perf &p);
181 
182 extern Perf g_perf;
183 }  // namespace ark::tooling
184 
185 #endif
186