1*288bf522SAndroid Build Coastguard Worker /*
2*288bf522SAndroid Build Coastguard Worker * Copyright (C) 2016 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 #ifndef SIMPLE_PERF_SAMPLE_DISPLAYER_H_
18*288bf522SAndroid Build Coastguard Worker #define SIMPLE_PERF_SAMPLE_DISPLAYER_H_
19*288bf522SAndroid Build Coastguard Worker
20*288bf522SAndroid Build Coastguard Worker #include <inttypes.h>
21*288bf522SAndroid Build Coastguard Worker
22*288bf522SAndroid Build Coastguard Worker #include <functional>
23*288bf522SAndroid Build Coastguard Worker #include <optional>
24*288bf522SAndroid Build Coastguard Worker #include <string>
25*288bf522SAndroid Build Coastguard Worker
26*288bf522SAndroid Build Coastguard Worker #include <android-base/logging.h>
27*288bf522SAndroid Build Coastguard Worker #include <android-base/stringprintf.h>
28*288bf522SAndroid Build Coastguard Worker
29*288bf522SAndroid Build Coastguard Worker namespace simpleperf {
30*288bf522SAndroid Build Coastguard Worker
31*288bf522SAndroid Build Coastguard Worker // The display functions below are used to show items in a sample.
32*288bf522SAndroid Build Coastguard Worker
33*288bf522SAndroid Build Coastguard Worker template <typename EntryT, typename InfoT>
DisplayAccumulatedOverhead(const EntryT * sample,const InfoT * info)34*288bf522SAndroid Build Coastguard Worker std::string DisplayAccumulatedOverhead(const EntryT* sample, const InfoT* info) {
35*288bf522SAndroid Build Coastguard Worker uint64_t period = sample->period + sample->accumulated_period;
36*288bf522SAndroid Build Coastguard Worker uint64_t total_period = info->total_period;
37*288bf522SAndroid Build Coastguard Worker double percentage = (total_period != 0) ? 100.0 * period / total_period : 0.0;
38*288bf522SAndroid Build Coastguard Worker return android::base::StringPrintf("%.2f%%", percentage);
39*288bf522SAndroid Build Coastguard Worker }
40*288bf522SAndroid Build Coastguard Worker
41*288bf522SAndroid Build Coastguard Worker template <typename EntryT>
DisplayAccumulatedPeriod(const EntryT * sample)42*288bf522SAndroid Build Coastguard Worker std::string DisplayAccumulatedPeriod(const EntryT* sample) {
43*288bf522SAndroid Build Coastguard Worker return android::base::StringPrintf("%" PRIu64, sample->period + sample->accumulated_period);
44*288bf522SAndroid Build Coastguard Worker }
45*288bf522SAndroid Build Coastguard Worker
46*288bf522SAndroid Build Coastguard Worker template <typename EntryT, typename InfoT>
DisplaySelfOverhead(const EntryT * sample,const InfoT * info)47*288bf522SAndroid Build Coastguard Worker std::string DisplaySelfOverhead(const EntryT* sample, const InfoT* info) {
48*288bf522SAndroid Build Coastguard Worker uint64_t period = sample->period;
49*288bf522SAndroid Build Coastguard Worker uint64_t total_period = info->total_period;
50*288bf522SAndroid Build Coastguard Worker double percentage = (total_period != 0) ? 100.0 * period / total_period : 0.0;
51*288bf522SAndroid Build Coastguard Worker return android::base::StringPrintf("%.2f%%", percentage);
52*288bf522SAndroid Build Coastguard Worker }
53*288bf522SAndroid Build Coastguard Worker
54*288bf522SAndroid Build Coastguard Worker #define BUILD_DISPLAY_UINT64_FUNCTION(function_name, display_part) \
55*288bf522SAndroid Build Coastguard Worker template <typename EntryT> \
56*288bf522SAndroid Build Coastguard Worker std::string function_name(const EntryT* sample) { \
57*288bf522SAndroid Build Coastguard Worker return android::base::StringPrintf("%" PRIu64, sample->display_part); \
58*288bf522SAndroid Build Coastguard Worker }
59*288bf522SAndroid Build Coastguard Worker
60*288bf522SAndroid Build Coastguard Worker #define BUILD_DISPLAY_HEX64_FUNCTION(function_name, display_part) \
61*288bf522SAndroid Build Coastguard Worker template <typename EntryT> \
62*288bf522SAndroid Build Coastguard Worker std::string function_name(const EntryT* sample) { \
63*288bf522SAndroid Build Coastguard Worker return android::base::StringPrintf("0x%" PRIx64, sample->display_part); \
64*288bf522SAndroid Build Coastguard Worker }
65*288bf522SAndroid Build Coastguard Worker
66*288bf522SAndroid Build Coastguard Worker BUILD_DISPLAY_UINT64_FUNCTION(DisplaySelfPeriod, period);
67*288bf522SAndroid Build Coastguard Worker BUILD_DISPLAY_UINT64_FUNCTION(DisplaySampleCount, sample_count);
68*288bf522SAndroid Build Coastguard Worker
69*288bf522SAndroid Build Coastguard Worker template <typename EntryT>
DisplayPid(const EntryT * sample)70*288bf522SAndroid Build Coastguard Worker std::string DisplayPid(const EntryT* sample) {
71*288bf522SAndroid Build Coastguard Worker return android::base::StringPrintf("%d", static_cast<int>(sample->pid));
72*288bf522SAndroid Build Coastguard Worker }
73*288bf522SAndroid Build Coastguard Worker
74*288bf522SAndroid Build Coastguard Worker template <typename EntryT>
DisplayTid(const EntryT * sample)75*288bf522SAndroid Build Coastguard Worker std::string DisplayTid(const EntryT* sample) {
76*288bf522SAndroid Build Coastguard Worker return android::base::StringPrintf("%d", static_cast<int>(sample->tid));
77*288bf522SAndroid Build Coastguard Worker }
78*288bf522SAndroid Build Coastguard Worker
79*288bf522SAndroid Build Coastguard Worker template <typename EntryT>
DisplayComm(const EntryT * sample)80*288bf522SAndroid Build Coastguard Worker std::string DisplayComm(const EntryT* sample) {
81*288bf522SAndroid Build Coastguard Worker return sample->thread_comm;
82*288bf522SAndroid Build Coastguard Worker }
83*288bf522SAndroid Build Coastguard Worker
84*288bf522SAndroid Build Coastguard Worker template <typename EntryT>
DisplayDso(const EntryT * sample)85*288bf522SAndroid Build Coastguard Worker std::string DisplayDso(const EntryT* sample) {
86*288bf522SAndroid Build Coastguard Worker return std::string{sample->map->dso->GetReportPath()};
87*288bf522SAndroid Build Coastguard Worker }
88*288bf522SAndroid Build Coastguard Worker
89*288bf522SAndroid Build Coastguard Worker template <typename EntryT>
DisplaySymbol(const EntryT * sample)90*288bf522SAndroid Build Coastguard Worker std::string DisplaySymbol(const EntryT* sample) {
91*288bf522SAndroid Build Coastguard Worker return sample->symbol->DemangledName();
92*288bf522SAndroid Build Coastguard Worker }
93*288bf522SAndroid Build Coastguard Worker
94*288bf522SAndroid Build Coastguard Worker template <typename EntryT>
DisplayDsoFrom(const EntryT * sample)95*288bf522SAndroid Build Coastguard Worker std::string DisplayDsoFrom(const EntryT* sample) {
96*288bf522SAndroid Build Coastguard Worker return std::string{sample->branch_from.map->dso->GetReportPath()};
97*288bf522SAndroid Build Coastguard Worker }
98*288bf522SAndroid Build Coastguard Worker
99*288bf522SAndroid Build Coastguard Worker template <typename EntryT>
DisplaySymbolFrom(const EntryT * sample)100*288bf522SAndroid Build Coastguard Worker std::string DisplaySymbolFrom(const EntryT* sample) {
101*288bf522SAndroid Build Coastguard Worker return sample->branch_from.symbol->DemangledName();
102*288bf522SAndroid Build Coastguard Worker }
103*288bf522SAndroid Build Coastguard Worker
104*288bf522SAndroid Build Coastguard Worker template <typename SampleT, typename CallChainNodeT>
105*288bf522SAndroid Build Coastguard Worker class CallgraphDisplayer {
106*288bf522SAndroid Build Coastguard Worker private:
107*288bf522SAndroid Build Coastguard Worker static constexpr int SPACES_BETWEEN_CALLGRAPH_ENTRIES = 4;
108*288bf522SAndroid Build Coastguard Worker
109*288bf522SAndroid Build Coastguard Worker public:
110*288bf522SAndroid Build Coastguard Worker CallgraphDisplayer(uint32_t max_stack = UINT32_MAX, double percent_limit = 0.0,
111*288bf522SAndroid Build Coastguard Worker bool brief_callgraph = false)
max_stack_(max_stack)112*288bf522SAndroid Build Coastguard Worker : max_stack_(max_stack), percent_limit_(percent_limit), brief_callgraph_(brief_callgraph) {}
113*288bf522SAndroid Build Coastguard Worker
~CallgraphDisplayer()114*288bf522SAndroid Build Coastguard Worker virtual ~CallgraphDisplayer() {}
115*288bf522SAndroid Build Coastguard Worker
operator()116*288bf522SAndroid Build Coastguard Worker void operator()(FILE* fp, const SampleT* sample) {
117*288bf522SAndroid Build Coastguard Worker if (sample->callchain.children.empty()) {
118*288bf522SAndroid Build Coastguard Worker return;
119*288bf522SAndroid Build Coastguard Worker }
120*288bf522SAndroid Build Coastguard Worker std::string prefix = " ";
121*288bf522SAndroid Build Coastguard Worker if (brief_callgraph_ && sample->callchain.duplicated) {
122*288bf522SAndroid Build Coastguard Worker fprintf(fp, "%s[skipped in brief callgraph mode]\n", prefix.c_str());
123*288bf522SAndroid Build Coastguard Worker return;
124*288bf522SAndroid Build Coastguard Worker }
125*288bf522SAndroid Build Coastguard Worker fprintf(fp, "%s|\n", prefix.c_str());
126*288bf522SAndroid Build Coastguard Worker fprintf(fp, "%s-- %s\n", prefix.c_str(), PrintSampleName(sample).c_str());
127*288bf522SAndroid Build Coastguard Worker prefix.append(3, ' ');
128*288bf522SAndroid Build Coastguard Worker for (size_t i = 0; i < sample->callchain.children.size(); ++i) {
129*288bf522SAndroid Build Coastguard Worker DisplayCallGraphEntry(fp, 1, prefix, sample->callchain.children[i],
130*288bf522SAndroid Build Coastguard Worker sample->callchain.children_period + sample->GetPeriod(),
131*288bf522SAndroid Build Coastguard Worker (i + 1 == sample->callchain.children.size()));
132*288bf522SAndroid Build Coastguard Worker }
133*288bf522SAndroid Build Coastguard Worker }
134*288bf522SAndroid Build Coastguard Worker
DisplayCallGraphEntry(FILE * fp,size_t depth,std::string prefix,const std::unique_ptr<CallChainNodeT> & node,uint64_t parent_period,bool last)135*288bf522SAndroid Build Coastguard Worker void DisplayCallGraphEntry(FILE* fp, size_t depth, std::string prefix,
136*288bf522SAndroid Build Coastguard Worker const std::unique_ptr<CallChainNodeT>& node, uint64_t parent_period,
137*288bf522SAndroid Build Coastguard Worker bool last) {
138*288bf522SAndroid Build Coastguard Worker if (depth > max_stack_) {
139*288bf522SAndroid Build Coastguard Worker return;
140*288bf522SAndroid Build Coastguard Worker }
141*288bf522SAndroid Build Coastguard Worker std::string percentage_s = "-- ";
142*288bf522SAndroid Build Coastguard Worker if (node->period + node->children_period != parent_period) {
143*288bf522SAndroid Build Coastguard Worker double percentage = 100.0 * (node->period + node->children_period) / parent_period;
144*288bf522SAndroid Build Coastguard Worker if (percentage < percent_limit_) {
145*288bf522SAndroid Build Coastguard Worker return;
146*288bf522SAndroid Build Coastguard Worker }
147*288bf522SAndroid Build Coastguard Worker percentage_s = android::base::StringPrintf("--%.2f%%-- ", percentage);
148*288bf522SAndroid Build Coastguard Worker }
149*288bf522SAndroid Build Coastguard Worker prefix += "|";
150*288bf522SAndroid Build Coastguard Worker fprintf(fp, "%s\n", prefix.c_str());
151*288bf522SAndroid Build Coastguard Worker if (last) {
152*288bf522SAndroid Build Coastguard Worker prefix.back() = ' ';
153*288bf522SAndroid Build Coastguard Worker }
154*288bf522SAndroid Build Coastguard Worker fprintf(fp, "%s%s%s\n", prefix.c_str(), percentage_s.c_str(),
155*288bf522SAndroid Build Coastguard Worker PrintSampleName(node->chain[0]).c_str());
156*288bf522SAndroid Build Coastguard Worker for (size_t i = 1; i < node->chain.size(); ++i) {
157*288bf522SAndroid Build Coastguard Worker fprintf(fp, "%s%*s%s\n", prefix.c_str(), static_cast<int>(percentage_s.size()), "",
158*288bf522SAndroid Build Coastguard Worker PrintSampleName(node->chain[i]).c_str());
159*288bf522SAndroid Build Coastguard Worker }
160*288bf522SAndroid Build Coastguard Worker prefix.append(SPACES_BETWEEN_CALLGRAPH_ENTRIES, ' ');
161*288bf522SAndroid Build Coastguard Worker if (!node->children.empty() && node->period != 0) {
162*288bf522SAndroid Build Coastguard Worker fprintf(fp, "%s|--%.2f%%-- [hit in function]\n", prefix.c_str(),
163*288bf522SAndroid Build Coastguard Worker 100.0 * node->period / (node->period + node->children_period));
164*288bf522SAndroid Build Coastguard Worker }
165*288bf522SAndroid Build Coastguard Worker for (size_t i = 0; i < node->children.size(); ++i) {
166*288bf522SAndroid Build Coastguard Worker DisplayCallGraphEntry(fp, depth + 1, prefix, node->children[i],
167*288bf522SAndroid Build Coastguard Worker node->children_period + node->period, (i + 1 == node->children.size()));
168*288bf522SAndroid Build Coastguard Worker }
169*288bf522SAndroid Build Coastguard Worker }
170*288bf522SAndroid Build Coastguard Worker
171*288bf522SAndroid Build Coastguard Worker protected:
PrintSampleName(const SampleT * sample)172*288bf522SAndroid Build Coastguard Worker virtual std::string PrintSampleName(const SampleT* sample) {
173*288bf522SAndroid Build Coastguard Worker return sample->symbol->DemangledName();
174*288bf522SAndroid Build Coastguard Worker }
175*288bf522SAndroid Build Coastguard Worker
176*288bf522SAndroid Build Coastguard Worker private:
177*288bf522SAndroid Build Coastguard Worker uint32_t max_stack_;
178*288bf522SAndroid Build Coastguard Worker double percent_limit_;
179*288bf522SAndroid Build Coastguard Worker bool brief_callgraph_;
180*288bf522SAndroid Build Coastguard Worker };
181*288bf522SAndroid Build Coastguard Worker
182*288bf522SAndroid Build Coastguard Worker // SampleDisplayer is a class using a collections of display functions to show a
183*288bf522SAndroid Build Coastguard Worker // sample.
184*288bf522SAndroid Build Coastguard Worker
185*288bf522SAndroid Build Coastguard Worker template <typename EntryT, typename InfoT>
186*288bf522SAndroid Build Coastguard Worker class SampleDisplayer {
187*288bf522SAndroid Build Coastguard Worker public:
188*288bf522SAndroid Build Coastguard Worker using display_sample_func_t = std::function<std::string(const EntryT*)>;
189*288bf522SAndroid Build Coastguard Worker using display_sample_with_info_func_t = std::function<std::string(const EntryT*, const InfoT*)>;
190*288bf522SAndroid Build Coastguard Worker using exclusive_display_sample_func_t = std::function<void(FILE*, const EntryT*)>;
191*288bf522SAndroid Build Coastguard Worker
192*288bf522SAndroid Build Coastguard Worker private:
193*288bf522SAndroid Build Coastguard Worker struct Item {
194*288bf522SAndroid Build Coastguard Worker std::string name;
195*288bf522SAndroid Build Coastguard Worker size_t width;
196*288bf522SAndroid Build Coastguard Worker display_sample_func_t func;
197*288bf522SAndroid Build Coastguard Worker display_sample_with_info_func_t func_with_info;
198*288bf522SAndroid Build Coastguard Worker };
199*288bf522SAndroid Build Coastguard Worker
200*288bf522SAndroid Build Coastguard Worker public:
SetInfo(const InfoT * info)201*288bf522SAndroid Build Coastguard Worker void SetInfo(const InfoT* info) { info_ = info; }
SetReportFormat(bool report_csv,const std::string & csv_separator)202*288bf522SAndroid Build Coastguard Worker void SetReportFormat(bool report_csv, const std::string& csv_separator) {
203*288bf522SAndroid Build Coastguard Worker report_csv_ = report_csv;
204*288bf522SAndroid Build Coastguard Worker csv_separator_ = csv_separator;
205*288bf522SAndroid Build Coastguard Worker }
SetFilterFunction(const std::function<bool (const EntryT *,const InfoT *)> & filter)206*288bf522SAndroid Build Coastguard Worker void SetFilterFunction(const std::function<bool(const EntryT*, const InfoT*)>& filter) {
207*288bf522SAndroid Build Coastguard Worker filter_func_ = filter;
208*288bf522SAndroid Build Coastguard Worker }
209*288bf522SAndroid Build Coastguard Worker
AddDisplayFunction(const std::string & name,const display_sample_func_t & func)210*288bf522SAndroid Build Coastguard Worker void AddDisplayFunction(const std::string& name, const display_sample_func_t& func) {
211*288bf522SAndroid Build Coastguard Worker Item item;
212*288bf522SAndroid Build Coastguard Worker item.name = name;
213*288bf522SAndroid Build Coastguard Worker item.width = name.size();
214*288bf522SAndroid Build Coastguard Worker item.func = func;
215*288bf522SAndroid Build Coastguard Worker item.func_with_info = nullptr;
216*288bf522SAndroid Build Coastguard Worker display_v_.push_back(item);
217*288bf522SAndroid Build Coastguard Worker }
218*288bf522SAndroid Build Coastguard Worker
AddDisplayFunction(const std::string & name,const display_sample_with_info_func_t & func_with_info)219*288bf522SAndroid Build Coastguard Worker void AddDisplayFunction(const std::string& name,
220*288bf522SAndroid Build Coastguard Worker const display_sample_with_info_func_t& func_with_info) {
221*288bf522SAndroid Build Coastguard Worker Item item;
222*288bf522SAndroid Build Coastguard Worker item.name = name;
223*288bf522SAndroid Build Coastguard Worker item.width = name.size();
224*288bf522SAndroid Build Coastguard Worker item.func = nullptr;
225*288bf522SAndroid Build Coastguard Worker item.func_with_info = func_with_info;
226*288bf522SAndroid Build Coastguard Worker display_v_.push_back(item);
227*288bf522SAndroid Build Coastguard Worker }
228*288bf522SAndroid Build Coastguard Worker
AddExclusiveDisplayFunction(const exclusive_display_sample_func_t & func)229*288bf522SAndroid Build Coastguard Worker void AddExclusiveDisplayFunction(const exclusive_display_sample_func_t& func) {
230*288bf522SAndroid Build Coastguard Worker exclusive_display_v_.push_back(func);
231*288bf522SAndroid Build Coastguard Worker }
232*288bf522SAndroid Build Coastguard Worker
AdjustWidth(const EntryT * sample)233*288bf522SAndroid Build Coastguard Worker void AdjustWidth(const EntryT* sample) {
234*288bf522SAndroid Build Coastguard Worker if (report_csv_) {
235*288bf522SAndroid Build Coastguard Worker return;
236*288bf522SAndroid Build Coastguard Worker }
237*288bf522SAndroid Build Coastguard Worker if (filter_func_ && !filter_func_.value()(sample, info_)) {
238*288bf522SAndroid Build Coastguard Worker return;
239*288bf522SAndroid Build Coastguard Worker }
240*288bf522SAndroid Build Coastguard Worker for (auto& item : display_v_) {
241*288bf522SAndroid Build Coastguard Worker std::string data =
242*288bf522SAndroid Build Coastguard Worker (item.func != nullptr) ? item.func(sample) : item.func_with_info(sample, info_);
243*288bf522SAndroid Build Coastguard Worker item.width = std::max(item.width, data.size());
244*288bf522SAndroid Build Coastguard Worker }
245*288bf522SAndroid Build Coastguard Worker }
246*288bf522SAndroid Build Coastguard Worker
PrintNames(FILE * fp)247*288bf522SAndroid Build Coastguard Worker void PrintNames(FILE* fp) {
248*288bf522SAndroid Build Coastguard Worker for (size_t i = 0; i < display_v_.size(); ++i) {
249*288bf522SAndroid Build Coastguard Worker auto& item = display_v_[i];
250*288bf522SAndroid Build Coastguard Worker if (report_csv_) {
251*288bf522SAndroid Build Coastguard Worker fprintf(fp, "%s%s", item.name.c_str(),
252*288bf522SAndroid Build Coastguard Worker (i + 1 == display_v_.size()) ? "\n" : csv_separator_.c_str());
253*288bf522SAndroid Build Coastguard Worker } else {
254*288bf522SAndroid Build Coastguard Worker if (i != display_v_.size() - 1) {
255*288bf522SAndroid Build Coastguard Worker fprintf(fp, "%-*s ", static_cast<int>(item.width), item.name.c_str());
256*288bf522SAndroid Build Coastguard Worker } else {
257*288bf522SAndroid Build Coastguard Worker fprintf(fp, "%s\n", item.name.c_str());
258*288bf522SAndroid Build Coastguard Worker }
259*288bf522SAndroid Build Coastguard Worker }
260*288bf522SAndroid Build Coastguard Worker }
261*288bf522SAndroid Build Coastguard Worker }
262*288bf522SAndroid Build Coastguard Worker
PrintSample(FILE * fp,const EntryT * sample)263*288bf522SAndroid Build Coastguard Worker void PrintSample(FILE* fp, const EntryT* sample) {
264*288bf522SAndroid Build Coastguard Worker if (filter_func_ && !filter_func_.value()(sample, info_)) {
265*288bf522SAndroid Build Coastguard Worker return;
266*288bf522SAndroid Build Coastguard Worker }
267*288bf522SAndroid Build Coastguard Worker for (size_t i = 0; i < display_v_.size(); ++i) {
268*288bf522SAndroid Build Coastguard Worker auto& item = display_v_[i];
269*288bf522SAndroid Build Coastguard Worker std::string data =
270*288bf522SAndroid Build Coastguard Worker (item.func != nullptr) ? item.func(sample) : item.func_with_info(sample, info_);
271*288bf522SAndroid Build Coastguard Worker if (report_csv_) {
272*288bf522SAndroid Build Coastguard Worker if (data.find(csv_separator_) == std::string::npos) {
273*288bf522SAndroid Build Coastguard Worker fprintf(fp, "%s", data.c_str());
274*288bf522SAndroid Build Coastguard Worker } else {
275*288bf522SAndroid Build Coastguard Worker fprintf(fp, "\"%s\"", data.c_str());
276*288bf522SAndroid Build Coastguard Worker }
277*288bf522SAndroid Build Coastguard Worker fputs((i + 1 == display_v_.size()) ? "\n" : csv_separator_.c_str(), fp);
278*288bf522SAndroid Build Coastguard Worker } else {
279*288bf522SAndroid Build Coastguard Worker if (i != display_v_.size() - 1) {
280*288bf522SAndroid Build Coastguard Worker fprintf(fp, "%-*s ", static_cast<int>(item.width), data.c_str());
281*288bf522SAndroid Build Coastguard Worker } else {
282*288bf522SAndroid Build Coastguard Worker fprintf(fp, "%s\n", data.c_str());
283*288bf522SAndroid Build Coastguard Worker }
284*288bf522SAndroid Build Coastguard Worker }
285*288bf522SAndroid Build Coastguard Worker }
286*288bf522SAndroid Build Coastguard Worker for (auto& func : exclusive_display_v_) {
287*288bf522SAndroid Build Coastguard Worker func(fp, sample);
288*288bf522SAndroid Build Coastguard Worker }
289*288bf522SAndroid Build Coastguard Worker }
290*288bf522SAndroid Build Coastguard Worker
291*288bf522SAndroid Build Coastguard Worker private:
292*288bf522SAndroid Build Coastguard Worker const InfoT* info_;
293*288bf522SAndroid Build Coastguard Worker std::vector<Item> display_v_;
294*288bf522SAndroid Build Coastguard Worker std::vector<exclusive_display_sample_func_t> exclusive_display_v_;
295*288bf522SAndroid Build Coastguard Worker std::optional<std::function<bool(const EntryT*, const InfoT*)>> filter_func_;
296*288bf522SAndroid Build Coastguard Worker bool report_csv_ = false;
297*288bf522SAndroid Build Coastguard Worker std::string csv_separator_;
298*288bf522SAndroid Build Coastguard Worker };
299*288bf522SAndroid Build Coastguard Worker
300*288bf522SAndroid Build Coastguard Worker } // namespace simpleperf
301*288bf522SAndroid Build Coastguard Worker
302*288bf522SAndroid Build Coastguard Worker #endif // SIMPLE_PERF_SAMPLE_DISPLAYER_H_
303