summaryrefslogtreecommitdiff
path: root/simpleperf/cmd_report.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'simpleperf/cmd_report.cpp')
-rw-r--r--simpleperf/cmd_report.cpp425
1 files changed, 203 insertions, 222 deletions
diff --git a/simpleperf/cmd_report.cpp b/simpleperf/cmd_report.cpp
index 399e4d82..8e67f5e0 100644
--- a/simpleperf/cmd_report.cpp
+++ b/simpleperf/cmd_report.cpp
@@ -41,16 +41,10 @@
#include "tracing.h"
#include "utils.h"
-namespace simpleperf {
namespace {
-using android::base::Split;
-
static std::set<std::string> branch_sort_keys = {
- "dso_from",
- "dso_to",
- "symbol_from",
- "symbol_to",
+ "dso_from", "dso_to", "symbol_from", "symbol_to",
};
struct BranchFromEntry {
const MapEntry* map;
@@ -58,7 +52,8 @@ struct BranchFromEntry {
uint64_t vaddr_in_file;
uint64_t flags;
- BranchFromEntry() : map(nullptr), symbol(nullptr), vaddr_in_file(0), flags(0) {}
+ BranchFromEntry()
+ : map(nullptr), symbol(nullptr), vaddr_in_file(0), flags(0) {}
};
struct SampleEntry {
@@ -67,7 +62,6 @@ struct SampleEntry {
// accumuated when appearing in other sample's callchain
uint64_t accumulated_period;
uint64_t sample_count;
- int cpu;
pid_t pid;
pid_t tid;
const char* thread_comm;
@@ -78,14 +72,13 @@ struct SampleEntry {
// a callchain tree representing all callchains in the sample
CallChainRoot<SampleEntry> callchain;
- SampleEntry(uint64_t time, uint64_t period, uint64_t accumulated_period, uint64_t sample_count,
- int cpu, const ThreadEntry* thread, const MapEntry* map, const Symbol* symbol,
- uint64_t vaddr_in_file)
+ SampleEntry(uint64_t time, uint64_t period, uint64_t accumulated_period,
+ uint64_t sample_count, const ThreadEntry* thread,
+ const MapEntry* map, const Symbol* symbol, uint64_t vaddr_in_file)
: time(time),
period(period),
accumulated_period(accumulated_period),
sample_count(sample_count),
- cpu(cpu),
pid(thread->pid),
tid(thread->tid),
thread_comm(thread->comm),
@@ -97,7 +90,9 @@ struct SampleEntry {
SampleEntry(SampleEntry&&) = default;
SampleEntry(SampleEntry&) = delete;
- uint64_t GetPeriod() const { return period; }
+ uint64_t GetPeriod() const {
+ return period;
+ }
};
struct SampleTree {
@@ -105,16 +100,11 @@ struct SampleTree {
uint64_t total_samples;
uint64_t total_period;
uint64_t total_error_callchains;
- std::string event_name;
};
BUILD_COMPARE_VALUE_FUNCTION(CompareVaddrInFile, vaddr_in_file);
BUILD_DISPLAY_HEX64_FUNCTION(DisplayVaddrInFile, vaddr_in_file);
-static std::string DisplayEventName(const SampleEntry*, const SampleTree* info) {
- return info->event_name;
-}
-
class ReportCmdSampleTreeBuilder : public SampleTreeBuilder<SampleEntry, uint64_t> {
public:
ReportCmdSampleTreeBuilder(const SampleComparator<SampleEntry>& sample_comparator,
@@ -125,13 +115,11 @@ class ReportCmdSampleTreeBuilder : public SampleTreeBuilder<SampleEntry, uint64_
total_period_(0),
total_error_callchains_(0) {}
- void SetFilters(const std::unordered_set<int>& cpu_filter,
- const std::unordered_set<int>& pid_filter,
+ void SetFilters(const std::unordered_set<int>& pid_filter,
const std::unordered_set<int>& tid_filter,
const std::unordered_set<std::string>& comm_filter,
const std::unordered_set<std::string>& dso_filter,
const std::unordered_set<std::string>& symbol_filter) {
- cpu_filter_ = cpu_filter;
pid_filter_ = pid_filter;
tid_filter_ = tid_filter;
comm_filter_ = comm_filter;
@@ -139,8 +127,6 @@ class ReportCmdSampleTreeBuilder : public SampleTreeBuilder<SampleEntry, uint64_
symbol_filter_ = symbol_filter;
}
- void SetEventName(const std::string& event_name) { event_name_ = event_name; }
-
SampleTree GetSampleTree() {
AddCallChainDuplicateInfo();
SampleTree sample_tree;
@@ -148,7 +134,6 @@ class ReportCmdSampleTreeBuilder : public SampleTreeBuilder<SampleEntry, uint64_
sample_tree.total_samples = total_samples_;
sample_tree.total_period = total_period_;
sample_tree.total_error_callchains = total_error_callchains_;
- sample_tree.event_name = event_name_;
return sample_tree;
}
@@ -163,28 +148,36 @@ class ReportCmdSampleTreeBuilder : public SampleTreeBuilder<SampleEntry, uint64_
protected:
virtual uint64_t GetPeriod(const SampleRecord& r) = 0;
- SampleEntry* CreateSample(const SampleRecord& r, bool in_kernel, uint64_t* acc_info) override {
- const ThreadEntry* thread = thread_tree_->FindThreadOrNew(r.tid_data.pid, r.tid_data.tid);
- const MapEntry* map = thread_tree_->FindMap(thread, r.ip_data.ip, in_kernel);
+ SampleEntry* CreateSample(const SampleRecord& r, bool in_kernel,
+ uint64_t* acc_info) override {
+ const ThreadEntry* thread =
+ thread_tree_->FindThreadOrNew(r.tid_data.pid, r.tid_data.tid);
+ const MapEntry* map =
+ thread_tree_->FindMap(thread, r.ip_data.ip, in_kernel);
uint64_t vaddr_in_file;
- const Symbol* symbol = thread_tree_->FindSymbol(map, r.ip_data.ip, &vaddr_in_file);
+ const Symbol* symbol =
+ thread_tree_->FindSymbol(map, r.ip_data.ip, &vaddr_in_file);
uint64_t period = GetPeriod(r);
*acc_info = period;
- return InsertSample(std::make_unique<SampleEntry>(r.time_data.time, period, 0, 1, r.Cpu(),
- thread, map, symbol, vaddr_in_file));
+ return InsertSample(std::unique_ptr<SampleEntry>(
+ new SampleEntry(r.time_data.time, period, 0, 1, thread, map, symbol, vaddr_in_file)));
}
- SampleEntry* CreateBranchSample(const SampleRecord& r, const BranchStackItemType& item) override {
- const ThreadEntry* thread = thread_tree_->FindThreadOrNew(r.tid_data.pid, r.tid_data.tid);
+ SampleEntry* CreateBranchSample(const SampleRecord& r,
+ const BranchStackItemType& item) override {
+ const ThreadEntry* thread =
+ thread_tree_->FindThreadOrNew(r.tid_data.pid, r.tid_data.tid);
const MapEntry* from_map = thread_tree_->FindMap(thread, item.from);
uint64_t from_vaddr_in_file;
- const Symbol* from_symbol = thread_tree_->FindSymbol(from_map, item.from, &from_vaddr_in_file);
+ const Symbol* from_symbol =
+ thread_tree_->FindSymbol(from_map, item.from, &from_vaddr_in_file);
const MapEntry* to_map = thread_tree_->FindMap(thread, item.to);
uint64_t to_vaddr_in_file;
- const Symbol* to_symbol = thread_tree_->FindSymbol(to_map, item.to, &to_vaddr_in_file);
- auto sample =
- std::make_unique<SampleEntry>(r.time_data.time, r.period_data.period, 0, 1, r.Cpu(), thread,
- to_map, to_symbol, to_vaddr_in_file);
+ const Symbol* to_symbol =
+ thread_tree_->FindSymbol(to_map, item.to, &to_vaddr_in_file);
+ std::unique_ptr<SampleEntry> sample(
+ new SampleEntry(r.time_data.time, r.period_data.period, 0, 1, thread,
+ to_map, to_symbol, to_vaddr_in_file));
sample->branch_from.map = from_map;
sample->branch_from.symbol = from_symbol;
sample->branch_from.vaddr_in_file = from_vaddr_in_file;
@@ -204,8 +197,8 @@ class ReportCmdSampleTreeBuilder : public SampleTreeBuilder<SampleEntry, uint64_
}
uint64_t vaddr_in_file;
const Symbol* symbol = thread_tree_->FindSymbol(map, ip, &vaddr_in_file);
- auto callchain_sample = std::make_unique<SampleEntry>(sample->time, 0, acc_info, 0, sample->cpu,
- thread, map, symbol, vaddr_in_file);
+ std::unique_ptr<SampleEntry> callchain_sample(new SampleEntry(
+ sample->time, 0, acc_info, 0, thread, map, symbol, vaddr_in_file));
callchain_sample->thread_comm = sample->thread_comm;
return InsertCallChainSample(std::move(callchain_sample), callchain);
}
@@ -214,25 +207,30 @@ class ReportCmdSampleTreeBuilder : public SampleTreeBuilder<SampleEntry, uint64_
return thread_tree_->FindThreadOrNew(sample->pid, sample->tid);
}
- uint64_t GetPeriodForCallChain(const uint64_t& acc_info) override { return acc_info; }
+ uint64_t GetPeriodForCallChain(const uint64_t& acc_info) override {
+ return acc_info;
+ }
bool FilterSample(const SampleEntry* sample) override {
- if (!cpu_filter_.empty() && cpu_filter_.count(sample->cpu) == 0) {
+ if (!pid_filter_.empty() &&
+ pid_filter_.find(sample->pid) == pid_filter_.end()) {
return false;
}
- if (!pid_filter_.empty() && pid_filter_.count(sample->pid) == 0) {
+ if (!tid_filter_.empty() &&
+ tid_filter_.find(sample->tid) == tid_filter_.end()) {
return false;
}
- if (!tid_filter_.empty() && tid_filter_.count(sample->tid) == 0) {
+ if (!comm_filter_.empty() &&
+ comm_filter_.find(sample->thread_comm) == comm_filter_.end()) {
return false;
}
- if (!comm_filter_.empty() && comm_filter_.count(sample->thread_comm) == 0) {
+ if (!dso_filter_.empty() &&
+ dso_filter_.find(sample->map->dso->Path()) == dso_filter_.end()) {
return false;
}
- if (!dso_filter_.empty() && dso_filter_.count(sample->map->dso->GetReportPath().data()) == 0) {
- return false;
- }
- if (!symbol_filter_.empty() && symbol_filter_.count(sample->symbol->DemangledName()) == 0) {
+ if (!symbol_filter_.empty() &&
+ symbol_filter_.find(sample->symbol->DemangledName()) ==
+ symbol_filter_.end()) {
return false;
}
return true;
@@ -252,7 +250,6 @@ class ReportCmdSampleTreeBuilder : public SampleTreeBuilder<SampleEntry, uint64_
private:
ThreadTree* thread_tree_;
- std::unordered_set<int> cpu_filter_;
std::unordered_set<int> pid_filter_;
std::unordered_set<int> tid_filter_;
std::unordered_set<std::string> comm_filter_;
@@ -262,8 +259,6 @@ class ReportCmdSampleTreeBuilder : public SampleTreeBuilder<SampleEntry, uint64_
uint64_t total_samples_;
uint64_t total_period_;
uint64_t total_error_callchains_;
-
- std::string event_name_;
};
// Build sample tree based on event count in each sample.
@@ -271,10 +266,12 @@ class EventCountSampleTreeBuilder : public ReportCmdSampleTreeBuilder {
public:
EventCountSampleTreeBuilder(const SampleComparator<SampleEntry>& sample_comparator,
ThreadTree* thread_tree)
- : ReportCmdSampleTreeBuilder(sample_comparator, thread_tree) {}
+ : ReportCmdSampleTreeBuilder(sample_comparator, thread_tree) { }
protected:
- uint64_t GetPeriod(const SampleRecord& r) override { return r.period_data.period; }
+ uint64_t GetPeriod(const SampleRecord& r) override {
+ return r.period_data.period;
+ }
};
// Build sample tree based on the time difference between current sample and next sample.
@@ -282,7 +279,7 @@ class TimestampSampleTreeBuilder : public ReportCmdSampleTreeBuilder {
public:
TimestampSampleTreeBuilder(const SampleComparator<SampleEntry>& sample_comparator,
ThreadTree* thread_tree)
- : ReportCmdSampleTreeBuilder(sample_comparator, thread_tree) {}
+ : ReportCmdSampleTreeBuilder(sample_comparator, thread_tree) { }
void ReportCmdProcessSampleRecord(std::shared_ptr<SampleRecord>& r) override {
pid_t tid = static_cast<pid_t>(r->tid_data.tid);
@@ -317,7 +314,6 @@ struct SampleTreeBuilderOptions {
std::unordered_set<std::string> comm_filter;
std::unordered_set<std::string> dso_filter;
std::unordered_set<std::string> symbol_filter;
- std::unordered_set<int> cpu_filter;
std::unordered_set<int> pid_filter;
std::unordered_set<int> tid_filter;
bool use_branch_address;
@@ -333,7 +329,7 @@ struct SampleTreeBuilderOptions {
} else {
builder.reset(new EventCountSampleTreeBuilder(comparator, thread_tree));
}
- builder->SetFilters(cpu_filter, pid_filter, tid_filter, comm_filter, dso_filter, symbol_filter);
+ builder->SetFilters(pid_filter, tid_filter, comm_filter, dso_filter, symbol_filter);
builder->SetBranchSampleOption(use_branch_address);
builder->SetCallChainSampleOptions(accumulate_callchain, build_callchain,
use_caller_as_callchain_root);
@@ -342,14 +338,18 @@ struct SampleTreeBuilderOptions {
};
using ReportCmdSampleTreeSorter = SampleTreeSorter<SampleEntry>;
-using ReportCmdSampleTreeDisplayer = SampleTreeDisplayer<SampleEntry, SampleTree>;
+using ReportCmdSampleTreeDisplayer =
+ SampleTreeDisplayer<SampleEntry, SampleTree>;
-using ReportCmdCallgraphDisplayer = CallgraphDisplayer<SampleEntry, CallChainNode<SampleEntry>>;
+using ReportCmdCallgraphDisplayer =
+ CallgraphDisplayer<SampleEntry, CallChainNode<SampleEntry>>;
-class ReportCmdCallgraphDisplayerWithVaddrInFile : public ReportCmdCallgraphDisplayer {
+class ReportCmdCallgraphDisplayerWithVaddrInFile
+ : public ReportCmdCallgraphDisplayer {
protected:
std::string PrintSampleName(const SampleEntry* sample) override {
- return android::base::StringPrintf("%s [+0x%" PRIx64 "]", sample->symbol->DemangledName(),
+ return android::base::StringPrintf("%s [+0x%" PRIx64 "]",
+ sample->symbol->DemangledName(),
sample->vaddr_in_file);
}
};
@@ -362,8 +362,9 @@ struct EventAttrWithName {
class ReportCommand : public Command {
public:
ReportCommand()
- : Command("report", "report sampling information in perf.data",
- // clang-format off
+ : Command(
+ "report", "report sampling information in perf.data",
+ // clang-format off
"Usage: simpleperf report [options]\n"
"The default options are: -i perf.data --sort comm,pid,tid,dso,symbol.\n"
"-b Use the branch-to addresses in sampled take branches instead of the\n"
@@ -371,10 +372,6 @@ class ReportCommand : public Command {
" option.\n"
"--children Print the overhead accumulated by appearing in the callchain.\n"
"--comms comm1,comm2,... Report only for selected comms.\n"
-"--cpu cpu_item1,cpu_item2,...\n"
-" Report samples on the selected cpus. cpu_item can be cpu\n"
-" number like 1, or cpu range like 0-3.\n"
-"--csv Report in csv format.\n"
"--dsos dso1,dso2,... Report only for selected dsos.\n"
"--full-callgraph Print full call graph. Used with -g option. By default,\n"
" brief call graph is printed.\n"
@@ -415,8 +412,8 @@ class ReportCommand : public Command {
"--symfs <dir> Look for files with symbols relative to this directory.\n"
"--tids tid1,tid2,... Report only for selected tids.\n"
"--vmlinux <file> Parse kernel symbols from <file>.\n"
- // clang-format on
- ),
+ // clang-format on
+ ),
record_filename_("perf.data"),
record_file_arch_(GetBuildArch()),
use_branch_address_(false),
@@ -435,8 +432,6 @@ class ReportCommand : public Command {
private:
bool ParseOptions(const std::vector<std::string>& args);
- bool BuildSampleComparatorAndDisplayer(bool print_sample_count,
- const std::vector<std::string>& sort_keys);
void ReadMetaInfoFromRecordFile();
bool ReadEventAttrFromRecordFile();
bool ReadFeaturesFromRecordFile();
@@ -471,7 +466,6 @@ class ReportCommand : public Command {
bool brief_callgraph_;
bool trace_offcpu_;
size_t sched_switch_attr_id_;
- bool report_csv_ = false;
std::string report_filename_;
};
@@ -509,140 +503,136 @@ bool ReportCommand::Run(const std::vector<std::string>& args) {
}
bool ReportCommand::ParseOptions(const std::vector<std::string>& args) {
- static OptionFormatMap option_formats = {
- {"-b", {OptionValueType::NONE, OptionType::SINGLE}},
- {"--children", {OptionValueType::NONE, OptionType::SINGLE}},
- {"--comms", {OptionValueType::STRING, OptionType::MULTIPLE}},
- {"--cpu", {OptionValueType::STRING, OptionType::MULTIPLE}},
- {"--csv", {OptionValueType::NONE, OptionType::SINGLE}},
- {"--dsos", {OptionValueType::STRING, OptionType::MULTIPLE}},
- {"--full-callgraph", {OptionValueType::NONE, OptionType::SINGLE}},
- {"-g", {OptionValueType::OPT_STRING, OptionType::SINGLE}},
- {"-i", {OptionValueType::STRING, OptionType::SINGLE}},
- {"--kallsyms", {OptionValueType::STRING, OptionType::SINGLE}},
- {"--max-stack", {OptionValueType::UINT, OptionType::SINGLE}},
- {"-n", {OptionValueType::NONE, OptionType::SINGLE}},
- {"--no-demangle", {OptionValueType::NONE, OptionType::SINGLE}},
- {"--no-show-ip", {OptionValueType::NONE, OptionType::SINGLE}},
- {"-o", {OptionValueType::STRING, OptionType::SINGLE}},
- {"--percent-limit", {OptionValueType::DOUBLE, OptionType::SINGLE}},
- {"--pids", {OptionValueType::STRING, OptionType::MULTIPLE}},
- {"--tids", {OptionValueType::STRING, OptionType::MULTIPLE}},
- {"--raw-period", {OptionValueType::NONE, OptionType::SINGLE}},
- {"--sort", {OptionValueType::STRING, OptionType::SINGLE}},
- {"--symbols", {OptionValueType::STRING, OptionType::MULTIPLE}},
- {"--symfs", {OptionValueType::STRING, OptionType::SINGLE}},
- {"--vmlinux", {OptionValueType::STRING, OptionType::SINGLE}},
- };
-
- OptionValueMap options;
- std::vector<std::pair<OptionName, OptionValue>> ordered_options;
- if (!PreprocessOptions(args, option_formats, &options, &ordered_options, nullptr)) {
- return false;
- }
+ bool demangle = true;
+ bool show_ip_for_unknown_symbol = true;
+ std::string vmlinux;
+ bool print_sample_count = false;
+ std::vector<std::string> sort_keys = {"comm", "pid", "tid", "dso", "symbol"};
- // Process options.
- use_branch_address_ = options.PullBoolValue("-b");
- accumulate_callchain_ = options.PullBoolValue("--children");
- for (const OptionValue& value : options.PullValues("--comms")) {
- std::vector<std::string> strs = Split(*value.str_value, ",");
- sample_tree_builder_options_.comm_filter.insert(strs.begin(), strs.end());
- }
- for (const OptionValue& value : options.PullValues("--cpu")) {
- if (auto cpus = GetCpusFromString(*value.str_value); cpus) {
- sample_tree_builder_options_.cpu_filter.insert(cpus->begin(), cpus->end());
- } else {
- return false;
- }
- }
- report_csv_ = options.PullBoolValue("--csv");
- for (const OptionValue& value : options.PullValues("--dsos")) {
- std::vector<std::string> strs = Split(*value.str_value, ",");
- sample_tree_builder_options_.dso_filter.insert(strs.begin(), strs.end());
- }
- brief_callgraph_ = !options.PullBoolValue("--full-callgraph");
-
- if (auto value = options.PullValue("-g"); value) {
- print_callgraph_ = true;
- accumulate_callchain_ = true;
- if (value->str_value != nullptr) {
- if (*value->str_value == "callee") {
- callgraph_show_callee_ = true;
- } else if (*value->str_value == "caller") {
- callgraph_show_callee_ = false;
- } else {
- LOG(ERROR) << "Unknown argument with -g option: " << *value->str_value;
+ for (size_t i = 0; i < args.size(); ++i) {
+ if (args[i] == "-b") {
+ use_branch_address_ = true;
+ } else if (args[i] == "--children") {
+ accumulate_callchain_ = true;
+ } else if (args[i] == "--comms" || args[i] == "--dsos") {
+ std::unordered_set<std::string>& filter =
+ (args[i] == "--comms" ? sample_tree_builder_options_.comm_filter
+ : sample_tree_builder_options_.dso_filter);
+ if (!NextArgumentOrError(args, &i)) {
return false;
}
- }
- }
- options.PullStringValue("-i", &record_filename_);
- if (auto value = options.PullValue("--kallsyms"); value) {
- std::string kallsyms;
- if (!android::base::ReadFileToString(*value->str_value, &kallsyms)) {
- LOG(ERROR) << "Can't read kernel symbols from " << *value->str_value;
- return false;
- }
- Dso::SetKallsyms(kallsyms);
- }
- if (!options.PullUintValue("--max-stack", &callgraph_max_stack_)) {
- return false;
- }
- bool print_sample_count = options.PullBoolValue("-n");
-
- Dso::SetDemangle(!options.PullBoolValue("--no-demangle"));
-
- if (!options.PullBoolValue("--no-show-ip")) {
- thread_tree_.ShowIpForUnknownSymbol();
- }
-
- options.PullStringValue("-o", &report_filename_);
- if (!options.PullDoubleValue("--percent-limit", &callgraph_percent_limit_, 0)) {
- return false;
- }
+ std::vector<std::string> strs = android::base::Split(args[i], ",");
+ filter.insert(strs.begin(), strs.end());
+ } else if (args[i] == "--full-callgraph") {
+ brief_callgraph_ = false;
+ } else if (args[i] == "-g") {
+ print_callgraph_ = true;
+ accumulate_callchain_ = true;
+ if (i + 1 < args.size() && args[i + 1][0] != '-') {
+ ++i;
+ if (args[i] == "callee") {
+ callgraph_show_callee_ = true;
+ } else if (args[i] == "caller") {
+ callgraph_show_callee_ = false;
+ } else {
+ LOG(ERROR) << "Unknown argument with -g option: " << args[i];
+ return false;
+ }
+ }
+ } else if (args[i] == "-i") {
+ if (!NextArgumentOrError(args, &i)) {
+ return false;
+ }
+ record_filename_ = args[i];
- for (const OptionValue& value : options.PullValues("--pids")) {
- if (auto pids = GetTidsFromString(*value.str_value, false); pids) {
- sample_tree_builder_options_.pid_filter.insert(pids->begin(), pids->end());
- } else {
- return false;
- }
- }
- for (const OptionValue& value : options.PullValues("--tids")) {
- if (auto tids = GetTidsFromString(*value.str_value, false); tids) {
- sample_tree_builder_options_.tid_filter.insert(tids->begin(), tids->end());
+ } else if (args[i] == "--kallsyms") {
+ if (!NextArgumentOrError(args, &i)) {
+ return false;
+ }
+ std::string kallsyms;
+ if (!android::base::ReadFileToString(args[i], &kallsyms)) {
+ LOG(ERROR) << "Can't read kernel symbols from " << args[i];
+ return false;
+ }
+ Dso::SetKallsyms(kallsyms);
+ } else if (args[i] == "--max-stack") {
+ if (!GetUintOption(args, &i, &callgraph_max_stack_)) {
+ return false;
+ }
+ } else if (args[i] == "-n") {
+ print_sample_count = true;
+
+ } else if (args[i] == "--no-demangle") {
+ demangle = false;
+ } else if (args[i] == "--no-show-ip") {
+ show_ip_for_unknown_symbol = false;
+ } else if (args[i] == "-o") {
+ if (!NextArgumentOrError(args, &i)) {
+ return false;
+ }
+ report_filename_ = args[i];
+ } else if (args[i] == "--percent-limit") {
+ if (!GetDoubleOption(args, &i, &callgraph_percent_limit_)) {
+ return false;
+ }
+ } else if (args[i] == "--pids" || args[i] == "--tids") {
+ const std::string& option = args[i];
+ std::unordered_set<int>& filter =
+ (option == "--pids" ? sample_tree_builder_options_.pid_filter
+ : sample_tree_builder_options_.tid_filter);
+ if (!NextArgumentOrError(args, &i)) {
+ return false;
+ }
+ std::vector<std::string> strs = android::base::Split(args[i], ",");
+ for (const auto& s : strs) {
+ int id;
+ if (!android::base::ParseInt(s.c_str(), &id, 0)) {
+ LOG(ERROR) << "invalid id in " << option << " option: " << s;
+ return false;
+ }
+ filter.insert(id);
+ }
+ } else if (args[i] == "--raw-period") {
+ raw_period_ = true;
+ } else if (args[i] == "--sort") {
+ if (!NextArgumentOrError(args, &i)) {
+ return false;
+ }
+ sort_keys = android::base::Split(args[i], ",");
+ } else if (args[i] == "--symbols") {
+ if (!NextArgumentOrError(args, &i)) {
+ return false;
+ }
+ std::vector<std::string> strs = android::base::Split(args[i], ";");
+ sample_tree_builder_options_.symbol_filter.insert(strs.begin(), strs.end());
+ } else if (args[i] == "--symfs") {
+ if (!NextArgumentOrError(args, &i)) {
+ return false;
+ }
+ if (!Dso::SetSymFsDir(args[i])) {
+ return false;
+ }
+ } else if (args[i] == "--vmlinux") {
+ if (!NextArgumentOrError(args, &i)) {
+ return false;
+ }
+ vmlinux = args[i];
} else {
+ ReportUnknownOption(args, i);
return false;
}
}
- raw_period_ = options.PullBoolValue("--raw-period");
-
- std::vector<std::string> sort_keys = {"comm", "pid", "tid", "dso", "symbol"};
- if (auto value = options.PullValue("--sort"); value) {
- sort_keys = Split(*value->str_value, ",");
- }
- for (const OptionValue& value : options.PullValues("--symbols")) {
- std::vector<std::string> symbols = Split(*value.str_value, ";");
- sample_tree_builder_options_.symbol_filter.insert(symbols.begin(), symbols.end());
+ Dso::SetDemangle(demangle);
+ if (!vmlinux.empty()) {
+ Dso::SetVmlinux(vmlinux);
}
- if (auto value = options.PullValue("--symfs"); value) {
- if (!Dso::SetSymFsDir(*value->str_value)) {
- return false;
- }
- }
- if (auto value = options.PullValue("--vmlinux"); value) {
- Dso::SetVmlinux(*value->str_value);
+ if (show_ip_for_unknown_symbol) {
+ thread_tree_.ShowIpForUnknownSymbol();
}
- CHECK(options.values.empty());
- return BuildSampleComparatorAndDisplayer(print_sample_count, sort_keys);
-}
-bool ReportCommand::BuildSampleComparatorAndDisplayer(bool print_sample_count,
- const std::vector<std::string>& sort_keys) {
SampleDisplayer<SampleEntry, SampleTree> displayer;
- displayer.SetReportFormat(report_csv_);
SampleComparator<SampleEntry> comparator;
if (accumulate_callchain_) {
@@ -665,7 +655,8 @@ bool ReportCommand::BuildSampleComparatorAndDisplayer(bool print_sample_count,
}
for (auto& key : sort_keys) {
- if (!use_branch_address_ && branch_sort_keys.find(key) != branch_sort_keys.end()) {
+ if (!use_branch_address_ &&
+ branch_sort_keys.find(key) != branch_sort_keys.end()) {
LOG(ERROR) << "sort key '" << key << "' can only be used with -b option.";
return false;
}
@@ -704,17 +695,6 @@ bool ReportCommand::BuildSampleComparatorAndDisplayer(bool print_sample_count,
return false;
}
}
-
- if (report_csv_) {
- if (accumulate_callchain_) {
- displayer.AddDisplayFunction("AccEventCount", DisplayAccumulatedPeriod);
- displayer.AddDisplayFunction("SelfEventCount", DisplaySelfPeriod);
- } else {
- displayer.AddDisplayFunction("EventCount", DisplaySelfPeriod);
- }
- displayer.AddDisplayFunction("EventName", DisplayEventName);
- }
-
if (print_callgraph_) {
bool has_symbol_key = false;
bool has_vaddr_in_file_key = false;
@@ -727,7 +707,8 @@ bool ReportCommand::BuildSampleComparatorAndDisplayer(bool print_sample_count,
}
if (has_symbol_key) {
if (has_vaddr_in_file_key) {
- displayer.AddExclusiveDisplayFunction(ReportCmdCallgraphDisplayerWithVaddrInFile());
+ displayer.AddExclusiveDisplayFunction(
+ ReportCmdCallgraphDisplayerWithVaddrInFile());
} else {
displayer.AddExclusiveDisplayFunction(ReportCmdCallgraphDisplayer(
callgraph_max_stack_, callgraph_percent_limit_, brief_callgraph_));
@@ -777,7 +758,8 @@ bool ReportCommand::ReadEventAttrFromRecordFile() {
}
}
if (!has_branch_stack) {
- LOG(ERROR) << record_filename_ << " is not recorded with branch stack sampling option.";
+ LOG(ERROR) << record_filename_
+ << " is not recorded with branch stack sampling option.";
return false;
}
}
@@ -797,7 +779,8 @@ bool ReportCommand::ReadEventAttrFromRecordFile() {
bool ReportCommand::ReadFeaturesFromRecordFile() {
record_file_reader_->LoadBuildIdAndFileFeatures(thread_tree_);
- std::string arch = record_file_reader_->ReadFeatureString(PerfFileFormat::FEAT_ARCH);
+ std::string arch =
+ record_file_reader_->ReadFeatureString(PerfFileFormat::FEAT_ARCH);
if (!arch.empty()) {
record_file_arch_ = GetArchType(arch);
if (record_file_arch_ == ARCH_UNSUPPORTED) {
@@ -816,8 +799,9 @@ bool ReportCommand::ReadFeaturesFromRecordFile() {
if (s == "-a") {
system_wide_collection_ = true;
break;
- } else if (s == "--call-graph" || s == "--cpu" || s == "-e" || s == "-f" || s == "-F" ||
- s == "-j" || s == "-m" || s == "-o" || s == "-p" || s == "-t") {
+ } else if (s == "--call-graph" || s == "--cpu" || s == "-e" ||
+ s == "-f" || s == "-F" || s == "-j" || s == "-m" ||
+ s == "-o" || s == "-p" || s == "-t") {
i++;
} else if (!s.empty() && s[0] != '-') {
break;
@@ -827,8 +811,8 @@ bool ReportCommand::ReadFeaturesFromRecordFile() {
}
if (record_file_reader_->HasFeature(PerfFileFormat::FEAT_TRACING_DATA)) {
std::vector<char> tracing_data;
- if (!record_file_reader_->ReadFeatureSection(PerfFileFormat::FEAT_TRACING_DATA,
- &tracing_data)) {
+ if (!record_file_reader_->ReadFeatureSection(
+ PerfFileFormat::FEAT_TRACING_DATA, &tracing_data)) {
return false;
}
if (!ProcessTracingData(tracing_data)) {
@@ -847,15 +831,12 @@ bool ReportCommand::ReadSampleTreeFromRecordFile() {
for (size_t i = 0; i < event_attrs_.size(); ++i) {
sample_tree_builder_.push_back(sample_tree_builder_options_.CreateSampleTreeBuilder());
- sample_tree_builder_.back()->SetEventName(event_attrs_[i].name);
- OfflineUnwinder* unwinder = sample_tree_builder_.back()->GetUnwinder();
- if (unwinder != nullptr) {
- unwinder->LoadMetaInfo(record_file_reader_->GetMetaInfoFeature());
- }
}
if (!record_file_reader_->ReadDataSection(
- [this](std::unique_ptr<Record> record) { return ProcessRecord(std::move(record)); })) {
+ [this](std::unique_ptr<Record> record) {
+ return ProcessRecord(std::move(record));
+ })) {
return false;
}
for (size_t i = 0; i < sample_tree_builder_.size(); ++i) {
@@ -885,6 +866,7 @@ bool ReportCommand::ProcessRecord(std::unique_ptr<Record> record) {
return true;
}
+
void ReportCommand::ProcessSampleRecordInTraceOffCpuMode(std::unique_ptr<Record> record,
size_t attr_id) {
std::shared_ptr<SampleRecord> r(static_cast<SampleRecord*>(record.release()));
@@ -934,8 +916,8 @@ bool ReportCommand::PrintReport() {
}
EventAttrWithName& attr = event_attrs_[i];
SampleTree& sample_tree = sample_tree_[i];
- fprintf(report_fp, "Event: %s (type %u, config %llu)\n", attr.name.c_str(), attr.attr.type,
- attr.attr.config);
+ fprintf(report_fp, "Event: %s (type %u, config %llu)\n", attr.name.c_str(),
+ attr.attr.type, attr.attr.config);
fprintf(report_fp, "Samples: %" PRIu64 "\n", sample_tree.total_samples);
if (sample_tree.total_error_callchains != 0) {
fprintf(report_fp, "Error Callchains: %" PRIu64 ", %f%%\n",
@@ -964,7 +946,6 @@ void ReportCommand::PrintReportContext(FILE* report_fp) {
} // namespace
void RegisterReportCommand() {
- RegisterCommand("report", [] { return std::unique_ptr<Command>(new ReportCommand()); });
+ RegisterCommand("report",
+ [] { return std::unique_ptr<Command>(new ReportCommand()); });
}
-
-} // namespace simpleperf