diff options
author | Treehugger Robot <treehugger-gerrit@google.com> | 2017-05-04 01:43:56 +0000 |
---|---|---|
committer | Gerrit Code Review <noreply-gerritcodereview@google.com> | 2017-05-04 01:43:58 +0000 |
commit | 3fb00aedf278c731f61deb0f36b9b1c92d0a0dcf (patch) | |
tree | 33156f0fbbe1fe1847d12fbc7c294722c378c32d | |
parent | 8ebd2b14a2cbcc42dc7c5fe97f9b4c6be6f701e3 (diff) | |
parent | df6333c5f5a34d4b7853c4671a53fcfd9e5a0b88 (diff) | |
download | extras-android-wear-o-preview-4.tar.gz |
Merge "simpleperf: add META_INFO feature section in perf.data."android-wear-o-preview-4android-wear-o-preview-3android-o-preview-2
-rw-r--r-- | simpleperf/cmd_dumprecord.cpp | 18 | ||||
-rw-r--r-- | simpleperf/cmd_record.cpp | 9 | ||||
-rw-r--r-- | simpleperf/cmd_record_test.cpp | 10 | ||||
-rw-r--r-- | simpleperf/main.cpp | 5 | ||||
-rw-r--r-- | simpleperf/record_file.h | 2 | ||||
-rw-r--r-- | simpleperf/record_file_format.h | 70 | ||||
-rw-r--r-- | simpleperf/record_file_reader.cpp | 17 | ||||
-rw-r--r-- | simpleperf/record_file_test.cpp | 26 | ||||
-rw-r--r-- | simpleperf/record_file_writer.cpp | 22 | ||||
-rw-r--r-- | simpleperf/utils.cpp | 7 | ||||
-rw-r--r-- | simpleperf/utils.h | 2 |
11 files changed, 152 insertions, 36 deletions
diff --git a/simpleperf/cmd_dumprecord.cpp b/simpleperf/cmd_dumprecord.cpp index 191d641c..2ce5295d 100644 --- a/simpleperf/cmd_dumprecord.cpp +++ b/simpleperf/cmd_dumprecord.cpp @@ -49,7 +49,7 @@ class DumpRecordCommand : public Command { void DumpFileHeader(); void DumpAttrSection(); void DumpDataSection(); - void DumpFeatureSection(); + bool DumpFeatureSection(); std::string record_filename_; std::unique_ptr<RecordFileReader> record_file_reader_; @@ -75,7 +75,9 @@ bool DumpRecordCommand::Run(const std::vector<std::string>& args) { DumpFileHeader(); DumpAttrSection(); DumpDataSection(); - DumpFeatureSection(); + if (!DumpFeatureSection()) { + return false; + } return true; } @@ -180,7 +182,7 @@ void DumpRecordCommand::DumpDataSection() { }, false); } -void DumpRecordCommand::DumpFeatureSection() { +bool DumpRecordCommand::DumpFeatureSection() { std::map<int, SectionDesc> section_map = record_file_reader_->FeatureSectionDescriptors(); for (const auto& pair : section_map) { int feature = pair.first; @@ -220,8 +222,18 @@ void DumpRecordCommand::DumpFeatureSection() { symbol.addr, symbol.addr + symbol.len); } } + } else if (feature == FEAT_META_INFO) { + std::unordered_map<std::string, std::string> info_map; + if (!record_file_reader_->ReadMetaInfoFeature(&info_map)) { + return false; + } + PrintIndented(1, "meta_info:\n"); + for (auto& pair : info_map) { + PrintIndented(2, "%s = %s\n", pair.first.c_str(), pair.second.c_str()); + } } } + return true; } void RegisterDumpRecordCommand() { diff --git a/simpleperf/cmd_record.cpp b/simpleperf/cmd_record.cpp index 3376af06..78e0a95d 100644 --- a/simpleperf/cmd_record.cpp +++ b/simpleperf/cmd_record.cpp @@ -941,7 +941,7 @@ bool RecordCommand::DumpAdditionalFeatures( return false; } - size_t feature_count = 4; + size_t feature_count = 5; if (branch_sampling_) { feature_count++; } @@ -984,6 +984,13 @@ bool RecordCommand::DumpAdditionalFeatures( !record_file_writer_->WriteBranchStackFeature()) { return false; } + + std::unordered_map<std::string, std::string> info_map; + info_map["simpleperf_version"] = GetSimpleperfVersion(); + if (!record_file_writer_->WriteMetaInfoFeature(info_map)) { + return false; + } + if (!record_file_writer_->EndWriteFeatures()) { return false; } diff --git a/simpleperf/cmd_record_test.cpp b/simpleperf/cmd_record_test.cpp index 85bbe34b..ec0605a4 100644 --- a/simpleperf/cmd_record_test.cpp +++ b/simpleperf/cmd_record_test.cpp @@ -428,3 +428,13 @@ TEST(record_cmd, start_profiling_fd_option) { close(read_fd); ASSERT_EQ("STARTED", s); } + +TEST(record_cmd, record_meta_info_feature) { + TemporaryFile tmpfile; + ASSERT_TRUE(RunRecordCmd({}, tmpfile.path)); + std::unique_ptr<RecordFileReader> reader = RecordFileReader::CreateInstance(tmpfile.path); + ASSERT_TRUE(reader != nullptr); + std::unordered_map<std::string, std::string> info_map; + ASSERT_TRUE(reader->ReadMetaInfoFeature(&info_map)); + ASSERT_NE(info_map.find("simpleperf_version"), info_map.end()); +} diff --git a/simpleperf/main.cpp b/simpleperf/main.cpp index 07b0e4b3..ae3e6292 100644 --- a/simpleperf/main.cpp +++ b/simpleperf/main.cpp @@ -24,8 +24,6 @@ #include "command.h" #include "utils.h" -constexpr int SIMPLEPERF_VERSION = 1; - int main(int argc, char** argv) { android::base::InitLogging(argv, android::base::StderrLogger); std::vector<std::string> args; @@ -46,8 +44,7 @@ int main(int argc, char** argv) { return 1; } } else if (strcmp(argv[i], "--version") == 0) { - LOG(INFO) << "Simpleperf version " << SIMPLEPERF_VERSION << ", revision " - << SIMPLEPERF_REVISION; + LOG(INFO) << "Simpleperf version " << GetSimpleperfVersion(); return 0; } else { args.push_back(argv[i]); diff --git a/simpleperf/record_file.h b/simpleperf/record_file.h index 51d4f437..32c91fa4 100644 --- a/simpleperf/record_file.h +++ b/simpleperf/record_file.h @@ -56,6 +56,7 @@ class RecordFileWriter { uint32_t file_type, uint64_t min_vaddr, const std::vector<const Symbol*>& symbols); + bool WriteMetaInfoFeature(const std::unordered_map<std::string, std::string>& info_map); bool EndWriteFeatures(); // Normally, Close() should be called after writing. But if something @@ -148,6 +149,7 @@ class RecordFileReader { bool ReadFileFeature(size_t& read_pos, std::string* file_path, uint32_t* file_type, uint64_t* min_vaddr, std::vector<Symbol>* symbols); + bool ReadMetaInfoFeature(std::unordered_map<std::string, std::string>* info_map); void LoadBuildIdAndFileFeatures(ThreadTree& thread_tree); diff --git a/simpleperf/record_file_format.h b/simpleperf/record_file_format.h index efa000cf..f9ed6f32 100644 --- a/simpleperf/record_file_format.h +++ b/simpleperf/record_file_format.h @@ -19,34 +19,47 @@ #include "perf_event.h" -// The file structure of perf.data: -// file_header -// id_section -// attr section -// data section -// feature section -// -// The feature section has the following structure: -// a section descriptor array, each element contains the section information of one add_feature. -// data section of feature 1 -// data section of feature 2 -// .... - -// file feature section: -// file_struct files[]; -// -// struct file_struct { -// uint32_t size; // size of rest fields in file_struct -// char file_path[]; -// uint32_t file_type; -// uint64_t min_vaddr; -// uint32_t symbol_count; -// struct { -// uint64_t start_vaddr; -// uint32_t len; -// char symbol_name[]; -// } symbol_table; -// }; +/* +The file structure of perf.data: + file_header + id_section + attr section + data section + feature section + +The feature section has the following structure: + a section descriptor array, each element contains the section information of one add_feature. + data section of feature 1 + data section of feature 2 + .... + +file feature section: + file_struct files[]; + + struct file_struct { + uint32_t size; // size of rest fields in file_struct + char file_path[]; + uint32_t file_type; + uint64_t min_vaddr; + uint32_t symbol_count; + struct { + uint64_t start_vaddr; + uint32_t len; + char symbol_name[]; + } symbol_table; + }; + +meta_info feature section: + meta_info infos[]; + + struct meta_info { + char key[]; + char value[]; + }; + keys in meta_info feature section include: + simpleperf_version, + +*/ namespace PerfFileFormat { @@ -74,6 +87,7 @@ enum { FEAT_SIMPLEPERF_START = 128, FEAT_FILE = FEAT_SIMPLEPERF_START, + FEAT_META_INFO, FEAT_MAX_NUM = 256, }; diff --git a/simpleperf/record_file_reader.cpp b/simpleperf/record_file_reader.cpp index 0fdb6ddc..67f35bea 100644 --- a/simpleperf/record_file_reader.cpp +++ b/simpleperf/record_file_reader.cpp @@ -434,6 +434,23 @@ bool RecordFileReader::ReadFileFeature(size_t& read_pos, return true; } +bool RecordFileReader::ReadMetaInfoFeature(std::unordered_map<std::string, std::string>* info_map) { + std::vector<char> buf; + if (!ReadFeatureSection(FEAT_META_INFO, &buf)) { + return false; + } + const char* p = buf.data(); + const char* end = buf.data() + buf.size(); + while (p < end) { + const char* key = p; + const char* value = key + strlen(key) + 1; + CHECK(value < end); + (*info_map)[p] = value; + p = value + strlen(value) + 1; + } + return true; +} + void RecordFileReader::LoadBuildIdAndFileFeatures(ThreadTree& thread_tree) { std::vector<BuildIdRecord> records = ReadBuildIdFeature(); std::vector<std::pair<std::string, BuildId>> build_ids; diff --git a/simpleperf/record_file_test.cpp b/simpleperf/record_file_test.cpp index 4fe725b9..530611e8 100644 --- a/simpleperf/record_file_test.cpp +++ b/simpleperf/record_file_test.cpp @@ -157,3 +157,29 @@ TEST_F(RecordFileTest, record_more_than_one_attr) { ASSERT_EQ(attrs[i].ids, attr_ids_[i].ids); } } + +TEST_F(RecordFileTest, write_meta_info_feature_section) { + // Write to a record file. + std::unique_ptr<RecordFileWriter> writer = RecordFileWriter::CreateInstance(tmpfile_.path); + ASSERT_TRUE(writer != nullptr); + AddEventType("cpu-cycles"); + ASSERT_TRUE(writer->WriteAttrSection(attr_ids_)); + + // Write meta_info feature section. + ASSERT_TRUE(writer->BeginWriteFeatures(1)); + std::unordered_map<std::string, std::string> info_map; + for (int i = 0; i < 100; ++i) { + std::string s = std::to_string(i); + info_map[s] = s + s; + } + ASSERT_TRUE(writer->WriteMetaInfoFeature(info_map)); + ASSERT_TRUE(writer->EndWriteFeatures()); + ASSERT_TRUE(writer->Close()); + + // Read from a record file. + std::unique_ptr<RecordFileReader> reader = RecordFileReader::CreateInstance(tmpfile_.path); + ASSERT_TRUE(reader != nullptr); + std::unordered_map<std::string, std::string> read_info_map; + ASSERT_TRUE(reader->ReadMetaInfoFeature(&read_info_map)); + ASSERT_EQ(read_info_map, info_map); +} diff --git a/simpleperf/record_file_writer.cpp b/simpleperf/record_file_writer.cpp index fe62ab58..083a7462 100644 --- a/simpleperf/record_file_writer.cpp +++ b/simpleperf/record_file_writer.cpp @@ -328,6 +328,28 @@ bool RecordFileWriter::WriteFileFeature(const std::string& file_path, return WriteFeatureEnd(FEAT_FILE); } +bool RecordFileWriter::WriteMetaInfoFeature( + const std::unordered_map<std::string, std::string>& info_map) { + uint32_t size = 0u; + for (auto& pair : info_map) { + size += pair.first.size() + 1; + size += pair.second.size() + 1; + } + std::vector<char> buf(size); + char* p = buf.data(); + for (auto& pair : info_map) { + MoveToBinaryFormat(pair.first.c_str(), pair.first.size() + 1, p); + MoveToBinaryFormat(pair.second.c_str(), pair.second.size() + 1, p); + } + if (!WriteFeatureBegin(FEAT_META_INFO)) { + return false; + } + if (!Write(buf.data(), buf.size())) { + return false; + } + return WriteFeatureEnd(FEAT_META_INFO); +} + bool RecordFileWriter::WriteFeatureBegin(int feature) { auto it = features_.find(feature); if (it == features_.end()) { diff --git a/simpleperf/utils.cpp b/simpleperf/utils.cpp index 62a8b63c..1dbe078e 100644 --- a/simpleperf/utils.cpp +++ b/simpleperf/utils.cpp @@ -31,6 +31,7 @@ #include <android-base/file.h> #include <android-base/logging.h> +#include <android-base/stringprintf.h> #include <7zCrc.h> #include <Xz.h> @@ -337,3 +338,9 @@ timeval SecondToTimeval(double time_in_sec) { tv.tv_usec = static_cast<int>((time_in_sec - tv.tv_sec) * 1000000); return tv; } + +constexpr int SIMPLEPERF_VERSION = 1; + +std::string GetSimpleperfVersion() { + return android::base::StringPrintf("%d.%s", SIMPLEPERF_VERSION, SIMPLEPERF_REVISION); +} diff --git a/simpleperf/utils.h b/simpleperf/utils.h index fc21a99f..775fd5c4 100644 --- a/simpleperf/utils.h +++ b/simpleperf/utils.h @@ -169,4 +169,6 @@ uint64_t ConvertBytesToValue(const char* bytes, uint32_t size); timeval SecondToTimeval(double time_in_sec); +std::string GetSimpleperfVersion(); + #endif // SIMPLE_PERF_UTILS_H_ |