diff options
author | Yabin Cui <yabinc@google.com> | 2016-04-01 20:22:35 -0700 |
---|---|---|
committer | Yabin Cui <yabinc@google.com> | 2016-04-05 16:52:47 -0700 |
commit | 2d6efe4b167da4e6b77f168b1820239ee65599e2 (patch) | |
tree | 631aced5c7cb30b3c93345c55e67fe329fdf1d1a /simpleperf/record_file_reader.cpp | |
parent | 96e12e78722988e912664b7323341799fdd12b9b (diff) | |
download | extras-2d6efe4b167da4e6b77f168b1820239ee65599e2.tar.gz |
simpleperf: support reporting more than one event type.
When sampling kernel trace points, it is like to sample more than
one even type. Like `simpleperf record -e kmem:mm_page_alloc,kmem:mm_page_free`.
1. change record command to dump event_id for all records.
2. change report command and record reader to support multiple
event attrs.
3. hide record_cache inside EventSelectionSet.
4. add test to report multiple event types.
Bug: 27403614
Change-Id: Ic22a5527d68e7a843e3cf95e85381f8ad6bcb196
Diffstat (limited to 'simpleperf/record_file_reader.cpp')
-rw-r--r-- | simpleperf/record_file_reader.cpp | 66 |
1 files changed, 62 insertions, 4 deletions
diff --git a/simpleperf/record_file_reader.cpp b/simpleperf/record_file_reader.cpp index f126a6b7..1165494c 100644 --- a/simpleperf/record_file_reader.cpp +++ b/simpleperf/record_file_reader.cpp @@ -23,7 +23,7 @@ #include <android-base/logging.h> -#include "perf_event.h" +#include "event_attr.h" #include "record.h" #include "utils.h" @@ -45,7 +45,8 @@ std::unique_ptr<RecordFileReader> RecordFileReader::CreateInstance(const std::st } RecordFileReader::RecordFileReader(const std::string& filename, FILE* fp) - : filename_(filename), record_fp_(fp) { + : filename_(filename), record_fp_(fp), event_id_pos_in_sample_records_(0), + event_id_reverse_pos_in_non_sample_records_(0) { } RecordFileReader::~RecordFileReader() { @@ -102,6 +103,25 @@ bool RecordFileReader::ReadAttrSection() { memcpy(&attr.ids, &buf[perf_event_attr_size], section_desc_size); file_attrs_.push_back(attr); } + if (file_attrs_.size() > 1) { + std::vector<perf_event_attr> attrs; + for (const auto& file_attr : file_attrs_) { + attrs.push_back(file_attr.attr); + } + if (!GetCommonEventIdPositionsForAttrs(attrs, &event_id_pos_in_sample_records_, + &event_id_reverse_pos_in_non_sample_records_)) { + return false; + } + } + for (size_t i = 0; i < file_attrs_.size(); ++i) { + std::vector<uint64_t> ids; + if (!ReadIdsForAttr(file_attrs_[i], &ids)) { + return false; + } + for (auto id : ids) { + event_id_to_attr_map_[id] = &file_attrs_[i].attr; + } + } return true; } @@ -150,9 +170,16 @@ bool RecordFileReader::ReadDataSection(std::function<bool(std::unique_ptr<Record PLOG(ERROR) << "failed to fseek()"; return false; } - RecordCache cache(file_attrs_[0].attr); + bool has_timestamp = true; + for (const auto& attr : file_attrs_) { + if (!IsTimestampSupported(attr.attr)) { + has_timestamp = false; + break; + } + } + RecordCache cache(has_timestamp); for (size_t nbytes_read = 0; nbytes_read < header_.data.size;) { - std::unique_ptr<Record> record = ReadRecordFromFile(file_attrs_[0].attr, record_fp_); + std::unique_ptr<Record> record = ReadRecord(); if (record == nullptr) { return false; } @@ -180,6 +207,37 @@ bool RecordFileReader::ReadDataSection(std::function<bool(std::unique_ptr<Record return true; } +std::unique_ptr<Record> RecordFileReader::ReadRecord() { + std::vector<char> buf(sizeof(perf_event_header)); + if (fread(buf.data(), sizeof(perf_event_header), 1, record_fp_) != 1) { + PLOG(ERROR) << "failed to read file " << filename_; + return nullptr; + } + perf_event_header* header = reinterpret_cast<perf_event_header*>(&buf[0]); + if (buf.size() < header->size) { + buf.resize(header->size); + header = reinterpret_cast<perf_event_header*>(&buf[0]); + } + if (fread(&buf[sizeof(perf_event_header)], buf.size() - sizeof(perf_event_header), 1, record_fp_) != 1) { + PLOG(ERROR) << "failed to read file " << filename_; + return nullptr; + } + const perf_event_attr* attr = &file_attrs_[0].attr; + if (file_attrs_.size() > 1) { + uint64_t event_id; + if (header->type == PERF_RECORD_SAMPLE) { + event_id = *reinterpret_cast<uint64_t*>(&buf[event_id_pos_in_sample_records_]); + } else { + event_id = *reinterpret_cast<uint64_t*>( + &buf[header->size - event_id_reverse_pos_in_non_sample_records_]); + } + auto it = event_id_to_attr_map_.find(event_id); + CHECK(it != event_id_to_attr_map_.end()); + attr = it->second; + } + return ReadRecordFromBuffer(*attr, header); +} + bool RecordFileReader::ReadFeatureSection(int feature, std::vector<char>* data) { const std::map<int, SectionDesc>& section_map = FeatureSectionDescriptors(); auto it = section_map.find(feature); |