summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYabin Cui <yabinc@google.com>2021-05-05 11:35:16 -0700
committerYabin Cui <yabinc@google.com>2021-05-05 11:35:16 -0700
commit9dd1642681f51a38395e71ef7caaa82a5728def8 (patch)
tree2530309e8232d73b6b79d083d4f8e02c4d9dab76
parentac2e71ce6971ad3b61bcafb8d0c598fc5f94d043 (diff)
downloadextras-9dd1642681f51a38395e71ef7caaa82a5728def8.tar.gz
simpleperf: improve generating test files.
To extend the use of generating test files in debug-unwind cmd: 1. Support multiple times in --sample-time option. 2. Keep build ids in test files. 3. Remove the requirement that input files should be recorded with --keep-failed-unwinding-debug-info. Bug: none Test: run simpleperf_unit_test. Change-Id: I4a9bb4d978733dd6d761e28d5d0de42cb572d57c
-rw-r--r--simpleperf/cmd_debug_unwind.cpp65
-rw-r--r--simpleperf/cmd_debug_unwind_test.cpp24
2 files changed, 59 insertions, 30 deletions
diff --git a/simpleperf/cmd_debug_unwind.cpp b/simpleperf/cmd_debug_unwind.cpp
index 28d15e89..9370a35e 100644
--- a/simpleperf/cmd_debug_unwind.cpp
+++ b/simpleperf/cmd_debug_unwind.cpp
@@ -215,8 +215,9 @@ static void DumpUnwindingResult(const UnwindingResult& result, FILE* fp) {
class SampleUnwinder : public RecordFileProcessor {
public:
- SampleUnwinder(const std::string& output_filename, uint64_t sample_time)
- : RecordFileProcessor(output_filename, false), sample_time_(sample_time) {}
+ SampleUnwinder(const std::string& output_filename,
+ const std::unordered_set<uint64_t>& sample_times)
+ : RecordFileProcessor(output_filename, false), sample_times_(sample_times) {}
protected:
bool CheckRecordCmd(const std::string& record_cmd) override {
@@ -251,7 +252,7 @@ class SampleUnwinder : public RecordFileProcessor {
if (r->type() == SIMPLE_PERF_RECORD_UNWINDING_RESULT) {
last_unwinding_result_.reset(static_cast<UnwindingResultRecord*>(r.release()));
} else if (r->type() == PERF_RECORD_SAMPLE) {
- if (sample_time_ == 0 || sample_time_ == r->Timestamp()) {
+ if (sample_times_.empty() || sample_times_.count(r->Timestamp())) {
auto& sr = *static_cast<SampleRecord*>(r.get());
const PerfSampleStackUserType* stack = &sr.stack_user_data;
const PerfSampleRegsUserType* regs = &sr.regs_user_data;
@@ -331,7 +332,7 @@ class SampleUnwinder : public RecordFileProcessor {
}
private:
- const uint64_t sample_time_;
+ const std::unordered_set<uint64_t> sample_times_;
std::unique_ptr<Dso> recording_file_dso_;
std::vector<std::unique_ptr<MapEntry>> map_storage_;
UnwindingStat stat_;
@@ -340,21 +341,15 @@ class SampleUnwinder : public RecordFileProcessor {
class TestFileGenerator : public RecordFileProcessor {
public:
- TestFileGenerator(const std::string& output_filename, uint64_t sample_time,
+ TestFileGenerator(const std::string& output_filename,
+ const std::unordered_set<uint64_t>& sample_times,
const std::unordered_set<std::string>& kept_binaries)
: RecordFileProcessor(output_filename, true),
- sample_time_(sample_time),
+ sample_times_(sample_times),
kept_binaries_(kept_binaries) {}
protected:
- bool CheckRecordCmd(const std::string& record_cmd) override {
- if (record_cmd.find("--keep-failed-unwinding-debug-info") == std::string::npos) {
- LOG(ERROR) << "file isn't record with --keep-failed-unwinding-debug-info: "
- << record_filename_;
- return false;
- }
- return true;
- }
+ bool CheckRecordCmd(const std::string&) override { return true; }
bool Process() override {
writer_.reset(new RecordFileWriter(output_filename_, out_fp_, false));
@@ -372,9 +367,9 @@ class TestFileGenerator : public RecordFileProcessor {
thread_tree_.Update(*r);
bool keep_record = false;
if (r->type() == SIMPLE_PERF_RECORD_UNWINDING_RESULT) {
- keep_record = (sample_time_ == r->Timestamp());
+ keep_record = (sample_times_.count(r->Timestamp()) > 0);
} else if (r->type() == PERF_RECORD_SAMPLE) {
- keep_record = (sample_time_ == r->Timestamp());
+ keep_record = (sample_times_.count(r->Timestamp()) > 0);
if (keep_record) {
// Dump maps needed to unwind this sample.
if (!WriteMapsForSample(*static_cast<SampleRecord*>(r.get()))) {
@@ -445,6 +440,17 @@ class TestFileGenerator : public RecordFileProcessor {
return false;
}
}
+ } else if (feat_type == PerfFileFormat::FEAT_BUILD_ID) {
+ std::vector<BuildIdRecord> build_ids = reader_->ReadBuildIdFeature();
+ std::vector<BuildIdRecord> write_build_ids;
+ for (auto& build_id : build_ids) {
+ if (kept_binaries_.count(build_id.filename)) {
+ write_build_ids.emplace_back(std::move(build_id));
+ }
+ }
+ if (!writer_->WriteBuildIdFeature(write_build_ids)) {
+ return false;
+ }
} else if (feature_types_to_copy.count(feat_type)) {
if (!reader_->ReadFeatureSection(feat_type, &buffer) ||
!writer_->WriteFeature(feat_type, buffer.data(), buffer.size())) {
@@ -471,7 +477,7 @@ class TestFileGenerator : public RecordFileProcessor {
}
private:
- const uint64_t sample_time_;
+ const std::unordered_set<uint64_t> sample_times_;
const std::unordered_set<std::string> kept_binaries_;
std::unique_ptr<RecordFileWriter> writer_;
};
@@ -589,9 +595,9 @@ class DebugUnwindCommand : public Command {
"-i <file> Input recording file. Default is perf.data.\n"
"-o <file> Output file. Default is stdout.\n"
"--keep-binaries-in-test-file binary1,binary2... Keep binaries in test file.\n"
-"--sample-time <time> Only process the sample recorded at the selected time.\n"
-"--symfs <dir> Look for files with symbols relative to this directory.\n"
-"--unwind-sample Unwind samples.\n"
+"--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"
"\n"
"Examples:\n"
"1. Unwind a sample.\n"
@@ -600,7 +606,6 @@ class DebugUnwindCommand : public Command {
"2. Generate a test file.\n"
"$ simpleperf debug-unwind -i perf.data --generate-test-file -o test.data --sample-time \\\n"
" 626970493946976 --keep-binaries-in-test-file perf.data_jit_app_cache:255984-259968\n"
-" perf.data should be generated with \"--keep-failed-unwinding-debug-info\".\n"
"3. Generate a failed unwinding report.\n"
"$ simpleperf debug-unwind -i perf.data --generate-report -o report.txt\n"
" perf.data should be generated with \"--keep-failed-unwinding-debug-info\" or \\\n"
@@ -620,7 +625,7 @@ class DebugUnwindCommand : public Command {
bool generate_report_ = false;
bool generate_test_file_;
std::unordered_set<std::string> kept_binaries_in_test_file_;
- uint64_t sample_time_ = 0;
+ std::unordered_set<uint64_t> sample_times_;
};
bool DebugUnwindCommand::Run(const std::vector<std::string>& args) {
@@ -631,11 +636,11 @@ bool DebugUnwindCommand::Run(const std::vector<std::string>& args) {
// 2. Distribute sub commands.
if (unwind_sample_) {
- SampleUnwinder sample_unwinder(output_filename_, sample_time_);
+ SampleUnwinder sample_unwinder(output_filename_, sample_times_);
return sample_unwinder.ProcessFile(input_filename_);
}
if (generate_test_file_) {
- TestFileGenerator test_file_generator(output_filename_, sample_time_,
+ TestFileGenerator test_file_generator(output_filename_, sample_times_,
kept_binaries_in_test_file_);
return test_file_generator.ProcessFile(input_filename_);
}
@@ -653,7 +658,7 @@ bool DebugUnwindCommand::ParseOptions(const std::vector<std::string>& args) {
{"-i", {OptionValueType::STRING, OptionType::SINGLE}},
{"--keep-binaries-in-test-file", {OptionValueType::STRING, OptionType::MULTIPLE}},
{"-o", {OptionValueType::STRING, OptionType::SINGLE}},
- {"--sample-time", {OptionValueType::UINT, OptionType::SINGLE}},
+ {"--sample-time", {OptionValueType::STRING, OptionType::MULTIPLE}},
{"--symfs", {OptionValueType::STRING, OptionType::MULTIPLE}},
{"--unwind-sample", {OptionValueType::NONE, OptionType::SINGLE}},
};
@@ -670,7 +675,13 @@ bool DebugUnwindCommand::ParseOptions(const std::vector<std::string>& args) {
kept_binaries_in_test_file_.insert(binaries.begin(), binaries.end());
}
options.PullStringValue("-o", &output_filename_);
- options.PullUintValue("--sample-time", &sample_time_);
+ for (auto& value : options.PullValues("--sample-time")) {
+ auto times = ParseUintVector<uint64_t>(*value.str_value);
+ if (!times) {
+ return false;
+ }
+ sample_times_.insert(times.value().begin(), times.value().end());
+ }
if (auto value = options.PullValue("--symfs"); value) {
if (!Dso::SetSymFsDir(*value->str_value)) {
return false;
@@ -684,7 +695,7 @@ bool DebugUnwindCommand::ParseOptions(const std::vector<std::string>& args) {
LOG(ERROR) << "no output path for generated test file";
return false;
}
- if (sample_time_ == 0) {
+ if (sample_times_.empty()) {
LOG(ERROR) << "no samples are selected via --sample-time";
return false;
}
diff --git a/simpleperf/cmd_debug_unwind_test.cpp b/simpleperf/cmd_debug_unwind_test.cpp
index c12fd4ef..85964a41 100644
--- a/simpleperf/cmd_debug_unwind_test.cpp
+++ b/simpleperf/cmd_debug_unwind_test.cpp
@@ -49,9 +49,13 @@ TEST(cmd_debug_unwind, sample_time_option) {
CaptureStdout capture;
ASSERT_TRUE(capture.Start());
- ASSERT_TRUE(DebugUnwindCmd()->Run(
- {"-i", input_data, "--unwind-sample", "--sample-time", "1516379654300997"}));
- ASSERT_NE(capture.Finish().find("sample_time: 1516379654300997"), std::string::npos);
+ ASSERT_TRUE(DebugUnwindCmd()->Run({"-i", input_data, "--unwind-sample", "--sample-time",
+ "1516379654300997", "--sample-time",
+ "1516379654363914,1516379655959122"}));
+ std::string output = capture.Finish();
+ ASSERT_NE(output.find("sample_time: 1516379654300997"), std::string::npos);
+ ASSERT_NE(output.find("sample_time: 1516379654363914"), std::string::npos);
+ ASSERT_NE(output.find("sample_time: 1516379655959122"), std::string::npos);
}
TEST(cmd_debug_unwind, output_option) {
@@ -127,6 +131,20 @@ TEST(cmd_debug_unwind, generate_test_file) {
ASSERT_NE(output.find("symbol_2: android.os.Handler.enqueueMessage"), std::string::npos);
}
+TEST(cmd_debug_unwind, generate_test_file_with_build_id) {
+ TemporaryFile tmpfile;
+ close(tmpfile.release());
+ ASSERT_TRUE(DebugUnwindCmd()->Run({"-i", GetTestData("perf_display_bitmaps.data"),
+ "--generate-test-file", "--sample-time", "684943450156904",
+ "-o", tmpfile.path, "--keep-binaries-in-test-file",
+ "/apex/com.android.runtime/lib64/bionic/libc.so"}));
+ auto reader = RecordFileReader::CreateInstance(tmpfile.path);
+ ASSERT_TRUE(reader);
+ auto build_ids = reader->ReadBuildIdFeature();
+ ASSERT_EQ(build_ids.size(), 1);
+ ASSERT_STREQ(build_ids[0].filename, "/apex/com.android.runtime/lib64/bionic/libc.so");
+}
+
TEST(cmd_debug_unwind, generate_report) {
TemporaryFile tmpfile;
close(tmpfile.release());