summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYabin Cui <yabinc@google.com>2021-06-17 16:50:34 -0700
committerYabin Cui <yabinc@google.com>2021-06-18 13:18:50 -0700
commitb83b11272253ba5c14bb303872d39d16d13672dc (patch)
tree286ec43218ed930e061db21ddfa275afdacebb87
parent9ce72af0a2de4caf994402dcfdd7a929fbaefdc7 (diff)
downloadextras-b83b11272253ba5c14bb303872d39d16d13672dc.tar.gz
simpleperf debug-unwind: add --skip-sample-print option.
When unwinding all samples in a record file, printing samples may take a lot of time. So skip it when not needed. Bug: none Test: run simpleperf_unit_test. Change-Id: Ib5801aa8eb8b931bd56aba5c717cf37b45e984c1
-rw-r--r--simpleperf/cmd_debug_unwind.cpp63
-rw-r--r--simpleperf/cmd_debug_unwind_test.cpp12
2 files changed, 48 insertions, 27 deletions
diff --git a/simpleperf/cmd_debug_unwind.cpp b/simpleperf/cmd_debug_unwind.cpp
index 18ffb86d..b096aeba 100644
--- a/simpleperf/cmd_debug_unwind.cpp
+++ b/simpleperf/cmd_debug_unwind.cpp
@@ -216,8 +216,10 @@ static void DumpUnwindingResult(const UnwindingResult& result, FILE* fp) {
class SampleUnwinder : public RecordFileProcessor {
public:
SampleUnwinder(const std::string& output_filename,
- const std::unordered_set<uint64_t>& sample_times)
- : RecordFileProcessor(output_filename, false), sample_times_(sample_times) {}
+ const std::unordered_set<uint64_t>& sample_times, bool skip_sample_print)
+ : RecordFileProcessor(output_filename, false),
+ sample_times_(sample_times),
+ skip_sample_print_(skip_sample_print) {}
protected:
bool CheckRecordCmd(const std::string& record_cmd) override {
@@ -308,38 +310,41 @@ class SampleUnwinder : public RecordFileProcessor {
}
stat_.AddUnwindingResult(unwinder_->GetUnwindingResult());
- // Print unwinding result.
- fprintf(out_fp_, "sample_time: %" PRIu64 "\n", r.Timestamp());
- DumpUnwindingResult(unwinder_->GetUnwindingResult(), out_fp_);
- std::vector<CallChainReportEntry> entries = callchain_report_builder_.Build(thread, ips, 0);
- for (size_t i = 0; i < entries.size(); i++) {
- size_t id = i + 1;
- auto& entry = entries[i];
- fprintf(out_fp_, "ip_%zu: 0x%" PRIx64 "\n", id, entry.ip);
- fprintf(out_fp_, "sp_%zu: 0x%" PRIx64 "\n", id, sps[i]);
- fprintf(out_fp_, "map_%zu: [0x%" PRIx64 "-0x%" PRIx64 "], pgoff 0x%" PRIx64 "\n", id,
- entry.map->start_addr, entry.map->get_end_addr(), entry.map->pgoff);
- Dso* dso = entry.map->dso;
- if (dso->Path() == record_filename_) {
- auto it = debug_unwind_dsos_.find(entry.map->pgoff);
- CHECK(it != debug_unwind_dsos_.end());
- const auto& p = it->second;
- dso = p.first;
- if (!JITDebugReader::IsPathInJITSymFile(dso->Path())) {
- entry.vaddr_in_file = dso->IpToVaddrInFile(entry.ip, entry.map->start_addr, p.second);
+ if (!skip_sample_print_) {
+ // Print unwinding result.
+ fprintf(out_fp_, "sample_time: %" PRIu64 "\n", r.Timestamp());
+ DumpUnwindingResult(unwinder_->GetUnwindingResult(), out_fp_);
+ std::vector<CallChainReportEntry> entries = callchain_report_builder_.Build(thread, ips, 0);
+ for (size_t i = 0; i < entries.size(); i++) {
+ size_t id = i + 1;
+ auto& entry = entries[i];
+ fprintf(out_fp_, "ip_%zu: 0x%" PRIx64 "\n", id, entry.ip);
+ fprintf(out_fp_, "sp_%zu: 0x%" PRIx64 "\n", id, sps[i]);
+ fprintf(out_fp_, "map_%zu: [0x%" PRIx64 "-0x%" PRIx64 "], pgoff 0x%" PRIx64 "\n", id,
+ entry.map->start_addr, entry.map->get_end_addr(), entry.map->pgoff);
+ Dso* dso = entry.map->dso;
+ if (dso->Path() == record_filename_) {
+ auto it = debug_unwind_dsos_.find(entry.map->pgoff);
+ CHECK(it != debug_unwind_dsos_.end());
+ const auto& p = it->second;
+ dso = p.first;
+ if (!JITDebugReader::IsPathInJITSymFile(dso->Path())) {
+ entry.vaddr_in_file = dso->IpToVaddrInFile(entry.ip, entry.map->start_addr, p.second);
+ }
+ entry.symbol = dso->FindSymbol(entry.vaddr_in_file);
}
- entry.symbol = dso->FindSymbol(entry.vaddr_in_file);
+ fprintf(out_fp_, "dso_%zu: %s\n", id, dso->Path().c_str());
+ fprintf(out_fp_, "vaddr_in_file_%zu: 0x%" PRIx64 "\n", id, entry.vaddr_in_file);
+ fprintf(out_fp_, "symbol_%zu: %s\n", id, entry.symbol->DemangledName());
}
- fprintf(out_fp_, "dso_%zu: %s\n", id, dso->Path().c_str());
- fprintf(out_fp_, "vaddr_in_file_%zu: 0x%" PRIx64 "\n", id, entry.vaddr_in_file);
- fprintf(out_fp_, "symbol_%zu: %s\n", id, entry.symbol->DemangledName());
+ fprintf(out_fp_, "\n");
}
- fprintf(out_fp_, "\n");
return true;
}
private:
const std::unordered_set<uint64_t> sample_times_;
+ bool skip_sample_print_;
// Map from offset in recording file to the corresponding debug_unwind_file.
std::unordered_map<uint64_t, std::pair<Dso*, uint64_t>> debug_unwind_dsos_;
UnwindingStat stat_;
@@ -605,6 +610,7 @@ class DebugUnwindCommand : public Command {
"--sample-time time1,time2... Only process samples recorded at selected times.\n"
"--symfs <dir> Look for files with symbols relative to this directory.\n"
"--unwind-sample Unwind samples.\n"
+"--skip-sample-print Skip printing unwound samples.\n"
"\n"
"Examples:\n"
"1. Unwind a sample.\n"
@@ -629,6 +635,7 @@ class DebugUnwindCommand : public Command {
std::string input_filename_ = "perf.data";
std::string output_filename_;
bool unwind_sample_ = false;
+ bool skip_sample_print_ = false;
bool generate_report_ = false;
bool generate_test_file_;
std::unordered_set<std::string> kept_binaries_in_test_file_;
@@ -643,7 +650,7 @@ bool DebugUnwindCommand::Run(const std::vector<std::string>& args) {
// 2. Distribute sub commands.
if (unwind_sample_) {
- SampleUnwinder sample_unwinder(output_filename_, sample_times_);
+ SampleUnwinder sample_unwinder(output_filename_, sample_times_, skip_sample_print_);
return sample_unwinder.ProcessFile(input_filename_);
}
if (generate_test_file_) {
@@ -666,6 +673,7 @@ bool DebugUnwindCommand::ParseOptions(const std::vector<std::string>& args) {
{"--keep-binaries-in-test-file", {OptionValueType::STRING, OptionType::MULTIPLE}},
{"-o", {OptionValueType::STRING, OptionType::SINGLE}},
{"--sample-time", {OptionValueType::STRING, OptionType::MULTIPLE}},
+ {"--skip-sample-print", {OptionValueType::NONE, OptionType::SINGLE}},
{"--symfs", {OptionValueType::STRING, OptionType::MULTIPLE}},
{"--unwind-sample", {OptionValueType::NONE, OptionType::SINGLE}},
};
@@ -681,6 +689,7 @@ bool DebugUnwindCommand::ParseOptions(const std::vector<std::string>& args) {
std::vector<std::string> binaries = android::base::Split(*value.str_value, ",");
kept_binaries_in_test_file_.insert(binaries.begin(), binaries.end());
}
+ skip_sample_print_ = options.PullBoolValue("--skip-sample-print");
options.PullStringValue("-o", &output_filename_);
for (auto& value : options.PullValues("--sample-time")) {
auto times = ParseUintVector<uint64_t>(*value.str_value);
diff --git a/simpleperf/cmd_debug_unwind_test.cpp b/simpleperf/cmd_debug_unwind_test.cpp
index 85964a41..9a6a6fc2 100644
--- a/simpleperf/cmd_debug_unwind_test.cpp
+++ b/simpleperf/cmd_debug_unwind_test.cpp
@@ -116,6 +116,18 @@ TEST(cmd_debug_unwind, unwind_sample_in_unwinding_debug_info_file) {
ASSERT_NE(output.find("symbol_5: android.os.Handler.post"), std::string::npos) << output;
}
+TEST(cmd_debug_unwind, skip_sample_print_option) {
+ std::string input_data = GetTestData(PERF_DATA_NO_UNWIND);
+ CaptureStdout capture;
+
+ ASSERT_TRUE(capture.Start());
+ ASSERT_TRUE(DebugUnwindCmd()->Run({"-i", input_data, "--unwind-sample", "--skip-sample-print"}));
+
+ std::string output = capture.Finish();
+ ASSERT_EQ(output.find("sample_time:"), std::string::npos);
+ ASSERT_NE(output.find("unwinding_sample_count: 8"), std::string::npos);
+}
+
TEST(cmd_debug_unwind, generate_test_file) {
TemporaryFile tmpfile;
close(tmpfile.release());