xref: /aosp_15_r20/system/extras/simpleperf/cmd_stat_impl.h (revision 288bf5226967eb3dac5cce6c939ccc2a7f2b4fe5)
1*288bf522SAndroid Build Coastguard Worker /*
2*288bf522SAndroid Build Coastguard Worker  * Copyright (C) 2020 The Android Open Source Project
3*288bf522SAndroid Build Coastguard Worker  *
4*288bf522SAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*288bf522SAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*288bf522SAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*288bf522SAndroid Build Coastguard Worker  *
8*288bf522SAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*288bf522SAndroid Build Coastguard Worker  *
10*288bf522SAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*288bf522SAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*288bf522SAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*288bf522SAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*288bf522SAndroid Build Coastguard Worker  * limitations under the License.
15*288bf522SAndroid Build Coastguard Worker  */
16*288bf522SAndroid Build Coastguard Worker 
17*288bf522SAndroid Build Coastguard Worker #pragma once
18*288bf522SAndroid Build Coastguard Worker 
19*288bf522SAndroid Build Coastguard Worker #include <math.h>
20*288bf522SAndroid Build Coastguard Worker #include <sys/types.h>
21*288bf522SAndroid Build Coastguard Worker 
22*288bf522SAndroid Build Coastguard Worker #include <algorithm>
23*288bf522SAndroid Build Coastguard Worker #include <optional>
24*288bf522SAndroid Build Coastguard Worker #include <string>
25*288bf522SAndroid Build Coastguard Worker #include <unordered_map>
26*288bf522SAndroid Build Coastguard Worker #include <vector>
27*288bf522SAndroid Build Coastguard Worker 
28*288bf522SAndroid Build Coastguard Worker #include <android-base/stringprintf.h>
29*288bf522SAndroid Build Coastguard Worker 
30*288bf522SAndroid Build Coastguard Worker #include "SampleComparator.h"
31*288bf522SAndroid Build Coastguard Worker #include "command.h"
32*288bf522SAndroid Build Coastguard Worker #include "event_selection_set.h"
33*288bf522SAndroid Build Coastguard Worker 
34*288bf522SAndroid Build Coastguard Worker namespace simpleperf {
35*288bf522SAndroid Build Coastguard Worker 
36*288bf522SAndroid Build Coastguard Worker struct CounterSum {
37*288bf522SAndroid Build Coastguard Worker   uint64_t value = 0;
38*288bf522SAndroid Build Coastguard Worker   uint64_t time_enabled = 0;
39*288bf522SAndroid Build Coastguard Worker   uint64_t time_running = 0;
40*288bf522SAndroid Build Coastguard Worker 
FromCounterCounterSum41*288bf522SAndroid Build Coastguard Worker   void FromCounter(const PerfCounter& counter) {
42*288bf522SAndroid Build Coastguard Worker     value = counter.value;
43*288bf522SAndroid Build Coastguard Worker     time_enabled = counter.time_enabled;
44*288bf522SAndroid Build Coastguard Worker     time_running = counter.time_running;
45*288bf522SAndroid Build Coastguard Worker   }
46*288bf522SAndroid Build Coastguard Worker 
ToCounterCounterSum47*288bf522SAndroid Build Coastguard Worker   void ToCounter(PerfCounter& counter) const {
48*288bf522SAndroid Build Coastguard Worker     counter.value = value;
49*288bf522SAndroid Build Coastguard Worker     counter.time_enabled = time_enabled;
50*288bf522SAndroid Build Coastguard Worker     counter.time_running = time_running;
51*288bf522SAndroid Build Coastguard Worker   }
52*288bf522SAndroid Build Coastguard Worker 
53*288bf522SAndroid Build Coastguard Worker   CounterSum operator+(const CounterSum& other) const {
54*288bf522SAndroid Build Coastguard Worker     CounterSum res;
55*288bf522SAndroid Build Coastguard Worker     res.value = value + other.value;
56*288bf522SAndroid Build Coastguard Worker     res.time_enabled = time_enabled + other.time_enabled;
57*288bf522SAndroid Build Coastguard Worker     res.time_running = time_running + other.time_running;
58*288bf522SAndroid Build Coastguard Worker     return res;
59*288bf522SAndroid Build Coastguard Worker   }
60*288bf522SAndroid Build Coastguard Worker 
61*288bf522SAndroid Build Coastguard Worker   CounterSum operator-(const CounterSum& other) const {
62*288bf522SAndroid Build Coastguard Worker     CounterSum res;
63*288bf522SAndroid Build Coastguard Worker     res.value = value - other.value;
64*288bf522SAndroid Build Coastguard Worker     res.time_enabled = time_enabled - other.time_enabled;
65*288bf522SAndroid Build Coastguard Worker     res.time_running = time_running - other.time_running;
66*288bf522SAndroid Build Coastguard Worker     return res;
67*288bf522SAndroid Build Coastguard Worker   }
68*288bf522SAndroid Build Coastguard Worker };
69*288bf522SAndroid Build Coastguard Worker 
70*288bf522SAndroid Build Coastguard Worker struct ThreadInfo {
71*288bf522SAndroid Build Coastguard Worker   pid_t tid;
72*288bf522SAndroid Build Coastguard Worker   pid_t pid;
73*288bf522SAndroid Build Coastguard Worker   std::string name;
74*288bf522SAndroid Build Coastguard Worker };
75*288bf522SAndroid Build Coastguard Worker 
76*288bf522SAndroid Build Coastguard Worker struct CounterSummary {
77*288bf522SAndroid Build Coastguard Worker   std::string type_name;
78*288bf522SAndroid Build Coastguard Worker   std::string modifier;
79*288bf522SAndroid Build Coastguard Worker   uint32_t group_id;
80*288bf522SAndroid Build Coastguard Worker   const ThreadInfo* thread;
81*288bf522SAndroid Build Coastguard Worker   int cpu;  // -1 represents all cpus
82*288bf522SAndroid Build Coastguard Worker   uint64_t count;
83*288bf522SAndroid Build Coastguard Worker   uint64_t runtime_in_ns;
84*288bf522SAndroid Build Coastguard Worker   double scale;
85*288bf522SAndroid Build Coastguard Worker   std::string readable_count;
86*288bf522SAndroid Build Coastguard Worker   std::string comment;
87*288bf522SAndroid Build Coastguard Worker   bool auto_generated;
88*288bf522SAndroid Build Coastguard Worker 
89*288bf522SAndroid Build Coastguard Worker   // used to sort summaries by count_per_thread
90*288bf522SAndroid Build Coastguard Worker   uint64_t count_per_thread = 0;
91*288bf522SAndroid Build Coastguard Worker 
CounterSummaryCounterSummary92*288bf522SAndroid Build Coastguard Worker   CounterSummary(const std::string& type_name, const std::string& modifier, uint32_t group_id,
93*288bf522SAndroid Build Coastguard Worker                  const ThreadInfo* thread, int cpu, uint64_t count, uint64_t runtime_in_ns,
94*288bf522SAndroid Build Coastguard Worker                  double scale, bool auto_generated, bool csv)
95*288bf522SAndroid Build Coastguard Worker       : type_name(type_name),
96*288bf522SAndroid Build Coastguard Worker         modifier(modifier),
97*288bf522SAndroid Build Coastguard Worker         group_id(group_id),
98*288bf522SAndroid Build Coastguard Worker         thread(thread),
99*288bf522SAndroid Build Coastguard Worker         cpu(cpu),
100*288bf522SAndroid Build Coastguard Worker         count(count),
101*288bf522SAndroid Build Coastguard Worker         runtime_in_ns(runtime_in_ns),
102*288bf522SAndroid Build Coastguard Worker         scale(scale),
103*288bf522SAndroid Build Coastguard Worker         auto_generated(auto_generated) {
104*288bf522SAndroid Build Coastguard Worker     readable_count = ReadableCountValue(csv);
105*288bf522SAndroid Build Coastguard Worker   }
106*288bf522SAndroid Build Coastguard Worker 
IsMonitoredAtTheSameTimeCounterSummary107*288bf522SAndroid Build Coastguard Worker   bool IsMonitoredAtTheSameTime(const CounterSummary& other) const {
108*288bf522SAndroid Build Coastguard Worker     // Two summaries are monitored at the same time if they are in the same
109*288bf522SAndroid Build Coastguard Worker     // group or are monitored all the time.
110*288bf522SAndroid Build Coastguard Worker     if (group_id == other.group_id) {
111*288bf522SAndroid Build Coastguard Worker       return true;
112*288bf522SAndroid Build Coastguard Worker     }
113*288bf522SAndroid Build Coastguard Worker     return IsMonitoredAllTheTime() && other.IsMonitoredAllTheTime();
114*288bf522SAndroid Build Coastguard Worker   }
115*288bf522SAndroid Build Coastguard Worker 
NameCounterSummary116*288bf522SAndroid Build Coastguard Worker   std::string Name() const {
117*288bf522SAndroid Build Coastguard Worker     if (modifier.empty()) {
118*288bf522SAndroid Build Coastguard Worker       return type_name;
119*288bf522SAndroid Build Coastguard Worker     }
120*288bf522SAndroid Build Coastguard Worker     return type_name + ":" + modifier;
121*288bf522SAndroid Build Coastguard Worker   }
122*288bf522SAndroid Build Coastguard Worker 
IsMonitoredAllTheTimeCounterSummary123*288bf522SAndroid Build Coastguard Worker   bool IsMonitoredAllTheTime() const {
124*288bf522SAndroid Build Coastguard Worker     // If an event runs all the time it is enabled (by not sharing hardware
125*288bf522SAndroid Build Coastguard Worker     // counters with other events), the scale of its summary is usually within
126*288bf522SAndroid Build Coastguard Worker     // [1, 1 + 1e-5]. By setting SCALE_ERROR_LIMIT to 1e-5, We can identify
127*288bf522SAndroid Build Coastguard Worker     // events monitored all the time in most cases while keeping the report
128*288bf522SAndroid Build Coastguard Worker     // error rate <= 1e-5.
129*288bf522SAndroid Build Coastguard Worker     constexpr double SCALE_ERROR_LIMIT = 1e-5;
130*288bf522SAndroid Build Coastguard Worker     return (fabs(scale - 1.0) < SCALE_ERROR_LIMIT);
131*288bf522SAndroid Build Coastguard Worker   }
132*288bf522SAndroid Build Coastguard Worker 
133*288bf522SAndroid Build Coastguard Worker  private:
134*288bf522SAndroid Build Coastguard Worker   std::string ReadableCountValue(bool csv);
135*288bf522SAndroid Build Coastguard Worker };
136*288bf522SAndroid Build Coastguard Worker 
137*288bf522SAndroid Build Coastguard Worker BUILD_COMPARE_VALUE_FUNCTION_REVERSE(CompareSummaryCount, count);
138*288bf522SAndroid Build Coastguard Worker BUILD_COMPARE_VALUE_FUNCTION_REVERSE(CompareSummaryCountPerThread, count_per_thread);
139*288bf522SAndroid Build Coastguard Worker BUILD_COMPARE_VALUE_FUNCTION(CompareSummaryCpu, cpu);
140*288bf522SAndroid Build Coastguard Worker BUILD_COMPARE_VALUE_FUNCTION(CompareSummaryPid, thread->pid);
141*288bf522SAndroid Build Coastguard Worker BUILD_COMPARE_VALUE_FUNCTION(CompareSummaryTid, thread->tid);
142*288bf522SAndroid Build Coastguard Worker BUILD_COMPARE_VALUE_FUNCTION(CompareSummaryComm, thread->name);
143*288bf522SAndroid Build Coastguard Worker 
144*288bf522SAndroid Build Coastguard Worker using SummaryComparator = SampleComparator<CounterSummary>;
145*288bf522SAndroid Build Coastguard Worker 
BuildSummaryComparator(const std::vector<std::string> & keys,bool report_per_thread,bool report_per_core)146*288bf522SAndroid Build Coastguard Worker inline std::optional<SummaryComparator> BuildSummaryComparator(const std::vector<std::string>& keys,
147*288bf522SAndroid Build Coastguard Worker                                                                bool report_per_thread,
148*288bf522SAndroid Build Coastguard Worker                                                                bool report_per_core) {
149*288bf522SAndroid Build Coastguard Worker   SummaryComparator comparator;
150*288bf522SAndroid Build Coastguard Worker   for (auto& key : keys) {
151*288bf522SAndroid Build Coastguard Worker     if (key == "count") {
152*288bf522SAndroid Build Coastguard Worker       comparator.AddCompareFunction(CompareSummaryCount);
153*288bf522SAndroid Build Coastguard Worker     } else if (key == "count_per_thread") {
154*288bf522SAndroid Build Coastguard Worker       if (report_per_thread) {
155*288bf522SAndroid Build Coastguard Worker         comparator.AddCompareFunction(CompareSummaryCountPerThread);
156*288bf522SAndroid Build Coastguard Worker       }
157*288bf522SAndroid Build Coastguard Worker     } else if (key == "cpu") {
158*288bf522SAndroid Build Coastguard Worker       if (report_per_core) {
159*288bf522SAndroid Build Coastguard Worker         comparator.AddCompareFunction(CompareSummaryCpu);
160*288bf522SAndroid Build Coastguard Worker       }
161*288bf522SAndroid Build Coastguard Worker     } else if (key == "pid") {
162*288bf522SAndroid Build Coastguard Worker       if (report_per_thread) {
163*288bf522SAndroid Build Coastguard Worker         comparator.AddCompareFunction(CompareSummaryPid);
164*288bf522SAndroid Build Coastguard Worker       }
165*288bf522SAndroid Build Coastguard Worker     } else if (key == "tid") {
166*288bf522SAndroid Build Coastguard Worker       if (report_per_thread) {
167*288bf522SAndroid Build Coastguard Worker         comparator.AddCompareFunction(CompareSummaryTid);
168*288bf522SAndroid Build Coastguard Worker       }
169*288bf522SAndroid Build Coastguard Worker     } else if (key == "comm") {
170*288bf522SAndroid Build Coastguard Worker       if (report_per_thread) {
171*288bf522SAndroid Build Coastguard Worker         comparator.AddCompareFunction(CompareSummaryComm);
172*288bf522SAndroid Build Coastguard Worker       }
173*288bf522SAndroid Build Coastguard Worker     } else {
174*288bf522SAndroid Build Coastguard Worker       LOG(ERROR) << "Unknown sort key: " << key;
175*288bf522SAndroid Build Coastguard Worker       return {};
176*288bf522SAndroid Build Coastguard Worker     }
177*288bf522SAndroid Build Coastguard Worker   }
178*288bf522SAndroid Build Coastguard Worker   return comparator;
179*288bf522SAndroid Build Coastguard Worker }
180*288bf522SAndroid Build Coastguard Worker 
181*288bf522SAndroid Build Coastguard Worker // Build a vector of CounterSummary.
182*288bf522SAndroid Build Coastguard Worker class CounterSummaryBuilder {
183*288bf522SAndroid Build Coastguard Worker  public:
CounterSummaryBuilder(bool report_per_thread,bool report_per_core,bool csv,const std::unordered_map<pid_t,ThreadInfo> & thread_map,const std::optional<SummaryComparator> & comparator)184*288bf522SAndroid Build Coastguard Worker   CounterSummaryBuilder(bool report_per_thread, bool report_per_core, bool csv,
185*288bf522SAndroid Build Coastguard Worker                         const std::unordered_map<pid_t, ThreadInfo>& thread_map,
186*288bf522SAndroid Build Coastguard Worker                         const std::optional<SummaryComparator>& comparator)
187*288bf522SAndroid Build Coastguard Worker       : report_per_thread_(report_per_thread),
188*288bf522SAndroid Build Coastguard Worker         report_per_core_(report_per_core),
189*288bf522SAndroid Build Coastguard Worker         csv_(csv),
190*288bf522SAndroid Build Coastguard Worker         thread_map_(thread_map),
191*288bf522SAndroid Build Coastguard Worker         summary_comparator_(comparator) {}
192*288bf522SAndroid Build Coastguard Worker 
AddCountersForOneEventType(const CountersInfo & info)193*288bf522SAndroid Build Coastguard Worker   void AddCountersForOneEventType(const CountersInfo& info) {
194*288bf522SAndroid Build Coastguard Worker     std::unordered_map<uint64_t, CounterSum> sum_map;
195*288bf522SAndroid Build Coastguard Worker     for (const auto& counter : info.counters) {
196*288bf522SAndroid Build Coastguard Worker       uint64_t key = 0;
197*288bf522SAndroid Build Coastguard Worker       if (report_per_thread_) {
198*288bf522SAndroid Build Coastguard Worker         key |= counter.tid;
199*288bf522SAndroid Build Coastguard Worker       }
200*288bf522SAndroid Build Coastguard Worker       if (report_per_core_) {
201*288bf522SAndroid Build Coastguard Worker         key |= static_cast<uint64_t>(counter.cpu) << 32;
202*288bf522SAndroid Build Coastguard Worker       }
203*288bf522SAndroid Build Coastguard Worker       CounterSum& sum = sum_map[key];
204*288bf522SAndroid Build Coastguard Worker       CounterSum add;
205*288bf522SAndroid Build Coastguard Worker       add.FromCounter(counter.counter);
206*288bf522SAndroid Build Coastguard Worker       sum = sum + add;
207*288bf522SAndroid Build Coastguard Worker     }
208*288bf522SAndroid Build Coastguard Worker     size_t pre_sum_count = summaries_.size();
209*288bf522SAndroid Build Coastguard Worker     for (const auto& pair : sum_map) {
210*288bf522SAndroid Build Coastguard Worker       pid_t tid = report_per_thread_ ? static_cast<pid_t>(pair.first & UINT32_MAX) : 0;
211*288bf522SAndroid Build Coastguard Worker       int cpu = report_per_core_ ? static_cast<int>(pair.first >> 32) : -1;
212*288bf522SAndroid Build Coastguard Worker       const CounterSum& sum = pair.second;
213*288bf522SAndroid Build Coastguard Worker       AddSummary(info, tid, cpu, sum);
214*288bf522SAndroid Build Coastguard Worker     }
215*288bf522SAndroid Build Coastguard Worker     if (report_per_thread_ || report_per_core_) {
216*288bf522SAndroid Build Coastguard Worker       SortSummaries(summaries_.begin() + pre_sum_count, summaries_.end());
217*288bf522SAndroid Build Coastguard Worker     }
218*288bf522SAndroid Build Coastguard Worker   }
219*288bf522SAndroid Build Coastguard Worker 
Build()220*288bf522SAndroid Build Coastguard Worker   std::vector<CounterSummary> Build() {
221*288bf522SAndroid Build Coastguard Worker     std::vector<CounterSummary> res = std::move(summaries_);
222*288bf522SAndroid Build Coastguard Worker     summaries_.clear();
223*288bf522SAndroid Build Coastguard Worker     return res;
224*288bf522SAndroid Build Coastguard Worker   }
225*288bf522SAndroid Build Coastguard Worker 
226*288bf522SAndroid Build Coastguard Worker  private:
AddSummary(const CountersInfo & info,pid_t tid,int cpu,const CounterSum & sum)227*288bf522SAndroid Build Coastguard Worker   void AddSummary(const CountersInfo& info, pid_t tid, int cpu, const CounterSum& sum) {
228*288bf522SAndroid Build Coastguard Worker     double scale = 1.0;
229*288bf522SAndroid Build Coastguard Worker     if (sum.time_running < sum.time_enabled && sum.time_running != 0) {
230*288bf522SAndroid Build Coastguard Worker       scale = static_cast<double>(sum.time_enabled) / sum.time_running;
231*288bf522SAndroid Build Coastguard Worker     }
232*288bf522SAndroid Build Coastguard Worker     if ((report_per_thread_ || report_per_core_) && sum.time_running == 0) {
233*288bf522SAndroid Build Coastguard Worker       // No need to report threads or cpus not running.
234*288bf522SAndroid Build Coastguard Worker       return;
235*288bf522SAndroid Build Coastguard Worker     }
236*288bf522SAndroid Build Coastguard Worker     const ThreadInfo* thread = nullptr;
237*288bf522SAndroid Build Coastguard Worker     if (report_per_thread_) {
238*288bf522SAndroid Build Coastguard Worker       auto it = thread_map_.find(tid);
239*288bf522SAndroid Build Coastguard Worker       CHECK(it != thread_map_.end());
240*288bf522SAndroid Build Coastguard Worker       thread = &it->second;
241*288bf522SAndroid Build Coastguard Worker     }
242*288bf522SAndroid Build Coastguard Worker     summaries_.emplace_back(info.event_name, info.event_modifier, info.group_id, thread, cpu,
243*288bf522SAndroid Build Coastguard Worker                             sum.value, sum.time_running, scale, false, csv_);
244*288bf522SAndroid Build Coastguard Worker   }
245*288bf522SAndroid Build Coastguard Worker 
SortSummaries(std::vector<CounterSummary>::iterator begin,std::vector<CounterSummary>::iterator end)246*288bf522SAndroid Build Coastguard Worker   void SortSummaries(std::vector<CounterSummary>::iterator begin,
247*288bf522SAndroid Build Coastguard Worker                      std::vector<CounterSummary>::iterator end) {
248*288bf522SAndroid Build Coastguard Worker     // Generate count_per_thread value for sorting.
249*288bf522SAndroid Build Coastguard Worker     if (report_per_thread_) {
250*288bf522SAndroid Build Coastguard Worker       if (report_per_core_) {
251*288bf522SAndroid Build Coastguard Worker         std::unordered_map<pid_t, uint64_t> count_per_thread;
252*288bf522SAndroid Build Coastguard Worker         for (auto it = begin; it != end; ++it) {
253*288bf522SAndroid Build Coastguard Worker           count_per_thread[it->thread->tid] += it->count;
254*288bf522SAndroid Build Coastguard Worker         }
255*288bf522SAndroid Build Coastguard Worker         for (auto it = begin; it != end; ++it) {
256*288bf522SAndroid Build Coastguard Worker           it->count_per_thread = count_per_thread[it->thread->tid];
257*288bf522SAndroid Build Coastguard Worker         }
258*288bf522SAndroid Build Coastguard Worker       } else {
259*288bf522SAndroid Build Coastguard Worker         for (auto it = begin; it != end; ++it) {
260*288bf522SAndroid Build Coastguard Worker           it->count_per_thread = it->count;
261*288bf522SAndroid Build Coastguard Worker         }
262*288bf522SAndroid Build Coastguard Worker       }
263*288bf522SAndroid Build Coastguard Worker     }
264*288bf522SAndroid Build Coastguard Worker 
265*288bf522SAndroid Build Coastguard Worker     std::sort(begin, end, summary_comparator_.value());
266*288bf522SAndroid Build Coastguard Worker   };
267*288bf522SAndroid Build Coastguard Worker 
268*288bf522SAndroid Build Coastguard Worker   const bool report_per_thread_;
269*288bf522SAndroid Build Coastguard Worker   const bool report_per_core_;
270*288bf522SAndroid Build Coastguard Worker   const bool csv_;
271*288bf522SAndroid Build Coastguard Worker   const std::unordered_map<pid_t, ThreadInfo>& thread_map_;
272*288bf522SAndroid Build Coastguard Worker   const std::optional<SummaryComparator>& summary_comparator_;
273*288bf522SAndroid Build Coastguard Worker   std::vector<CounterSummary> summaries_;
274*288bf522SAndroid Build Coastguard Worker };
275*288bf522SAndroid Build Coastguard Worker 
276*288bf522SAndroid Build Coastguard Worker class CounterSummaries {
277*288bf522SAndroid Build Coastguard Worker  public:
CounterSummaries(std::vector<CounterSummary> && summaries,bool csv)278*288bf522SAndroid Build Coastguard Worker   explicit CounterSummaries(std::vector<CounterSummary>&& summaries, bool csv)
279*288bf522SAndroid Build Coastguard Worker       : summaries_(std::move(summaries)), csv_(csv) {}
Summaries()280*288bf522SAndroid Build Coastguard Worker   const std::vector<CounterSummary>& Summaries() { return summaries_; }
281*288bf522SAndroid Build Coastguard Worker 
282*288bf522SAndroid Build Coastguard Worker   const CounterSummary* FindSummary(const std::string& type_name, const std::string& modifier,
283*288bf522SAndroid Build Coastguard Worker                                     const ThreadInfo* thread, int cpu);
284*288bf522SAndroid Build Coastguard Worker 
285*288bf522SAndroid Build Coastguard Worker   // If we have two summaries monitoring the same event type at the same time,
286*288bf522SAndroid Build Coastguard Worker   // that one is for user space only, and the other is for kernel space only;
287*288bf522SAndroid Build Coastguard Worker   // then we can automatically generate a summary combining the two results.
288*288bf522SAndroid Build Coastguard Worker   // For example, a summary of branch-misses:u and a summary for branch-misses:k
289*288bf522SAndroid Build Coastguard Worker   // can generate a summary of branch-misses.
290*288bf522SAndroid Build Coastguard Worker   void AutoGenerateSummaries();
291*288bf522SAndroid Build Coastguard Worker   void GenerateComments(double duration_in_sec);
292*288bf522SAndroid Build Coastguard Worker   void Show(FILE* fp);
293*288bf522SAndroid Build Coastguard Worker 
294*288bf522SAndroid Build Coastguard Worker  private:
295*288bf522SAndroid Build Coastguard Worker   std::string GetCommentForSummary(const CounterSummary& s, double duration_in_sec);
296*288bf522SAndroid Build Coastguard Worker   std::string GetRateComment(const CounterSummary& s, char sep);
297*288bf522SAndroid Build Coastguard Worker   bool FindRunningTimeForSummary(const CounterSummary& summary, double* running_time_in_sec);
298*288bf522SAndroid Build Coastguard Worker   void ShowCSV(FILE* fp, bool show_thread, bool show_core);
299*288bf522SAndroid Build Coastguard Worker   void ShowText(FILE* fp, bool show_thread, bool show_core);
300*288bf522SAndroid Build Coastguard Worker 
301*288bf522SAndroid Build Coastguard Worker  private:
302*288bf522SAndroid Build Coastguard Worker   std::vector<CounterSummary> summaries_;
303*288bf522SAndroid Build Coastguard Worker   bool csv_;
304*288bf522SAndroid Build Coastguard Worker };
305*288bf522SAndroid Build Coastguard Worker 
GetStatCmdOptionFormats()306*288bf522SAndroid Build Coastguard Worker inline const OptionFormatMap& GetStatCmdOptionFormats() {
307*288bf522SAndroid Build Coastguard Worker   static const OptionFormatMap option_formats = {
308*288bf522SAndroid Build Coastguard Worker       {"-a", {OptionValueType::NONE, OptionType::SINGLE, AppRunnerType::NOT_ALLOWED}},
309*288bf522SAndroid Build Coastguard Worker       {"--app", {OptionValueType::STRING, OptionType::SINGLE, AppRunnerType::NOT_ALLOWED}},
310*288bf522SAndroid Build Coastguard Worker       {"--cpu", {OptionValueType::STRING, OptionType::ORDERED, AppRunnerType::ALLOWED}},
311*288bf522SAndroid Build Coastguard Worker       {"--csv", {OptionValueType::NONE, OptionType::SINGLE, AppRunnerType::ALLOWED}},
312*288bf522SAndroid Build Coastguard Worker       {"--duration", {OptionValueType::DOUBLE, OptionType::SINGLE, AppRunnerType::ALLOWED}},
313*288bf522SAndroid Build Coastguard Worker       {"--interval", {OptionValueType::DOUBLE, OptionType::SINGLE, AppRunnerType::ALLOWED}},
314*288bf522SAndroid Build Coastguard Worker       {"--interval-only-values",
315*288bf522SAndroid Build Coastguard Worker        {OptionValueType::NONE, OptionType::SINGLE, AppRunnerType::ALLOWED}},
316*288bf522SAndroid Build Coastguard Worker       {"-e", {OptionValueType::STRING, OptionType::ORDERED, AppRunnerType::ALLOWED}},
317*288bf522SAndroid Build Coastguard Worker       {"--group", {OptionValueType::STRING, OptionType::ORDERED, AppRunnerType::ALLOWED}},
318*288bf522SAndroid Build Coastguard Worker       {"--in-app", {OptionValueType::NONE, OptionType::SINGLE, AppRunnerType::ALLOWED}},
319*288bf522SAndroid Build Coastguard Worker       {"--kprobe", {OptionValueType::STRING, OptionType::MULTIPLE, AppRunnerType::NOT_ALLOWED}},
320*288bf522SAndroid Build Coastguard Worker       {"--no-inherit", {OptionValueType::NONE, OptionType::SINGLE, AppRunnerType::ALLOWED}},
321*288bf522SAndroid Build Coastguard Worker       {"-o", {OptionValueType::STRING, OptionType::SINGLE, AppRunnerType::NOT_ALLOWED}},
322*288bf522SAndroid Build Coastguard Worker       {"--out-fd", {OptionValueType::UINT, OptionType::SINGLE, AppRunnerType::CHECK_FD}},
323*288bf522SAndroid Build Coastguard Worker       {"-p", {OptionValueType::STRING, OptionType::MULTIPLE, AppRunnerType::ALLOWED}},
324*288bf522SAndroid Build Coastguard Worker       {"--per-core", {OptionValueType::NONE, OptionType::SINGLE, AppRunnerType::ALLOWED}},
325*288bf522SAndroid Build Coastguard Worker       {"--per-thread", {OptionValueType::NONE, OptionType::SINGLE, AppRunnerType::ALLOWED}},
326*288bf522SAndroid Build Coastguard Worker       {"--print-hw-counter", {OptionValueType::NONE, OptionType::SINGLE, AppRunnerType::ALLOWED}},
327*288bf522SAndroid Build Coastguard Worker       {"--sort", {OptionValueType::STRING, OptionType::SINGLE, AppRunnerType::ALLOWED}},
328*288bf522SAndroid Build Coastguard Worker       {"--stop-signal-fd", {OptionValueType::UINT, OptionType::SINGLE, AppRunnerType::CHECK_FD}},
329*288bf522SAndroid Build Coastguard Worker       {"-t", {OptionValueType::STRING, OptionType::MULTIPLE, AppRunnerType::ALLOWED}},
330*288bf522SAndroid Build Coastguard Worker       {"--tp-filter", {OptionValueType::STRING, OptionType::ORDERED, AppRunnerType::ALLOWED}},
331*288bf522SAndroid Build Coastguard Worker       {"--tracepoint-events",
332*288bf522SAndroid Build Coastguard Worker        {OptionValueType::STRING, OptionType::SINGLE, AppRunnerType::CHECK_PATH}},
333*288bf522SAndroid Build Coastguard Worker       {"--use-devfreq-counters",
334*288bf522SAndroid Build Coastguard Worker        {OptionValueType::NONE, OptionType::SINGLE, AppRunnerType::NOT_ALLOWED}},
335*288bf522SAndroid Build Coastguard Worker       {"--verbose", {OptionValueType::NONE, OptionType::SINGLE, AppRunnerType::ALLOWED}},
336*288bf522SAndroid Build Coastguard Worker   };
337*288bf522SAndroid Build Coastguard Worker   return option_formats;
338*288bf522SAndroid Build Coastguard Worker }
339*288bf522SAndroid Build Coastguard Worker 
340*288bf522SAndroid Build Coastguard Worker }  // namespace simpleperf