summaryrefslogtreecommitdiff
path: root/simpleperf/record_file_reader.cpp
diff options
context:
space:
mode:
authorYabin Cui <yabinc@google.com>2016-04-01 20:22:35 -0700
committerYabin Cui <yabinc@google.com>2016-04-05 16:52:47 -0700
commit2d6efe4b167da4e6b77f168b1820239ee65599e2 (patch)
tree631aced5c7cb30b3c93345c55e67fe329fdf1d1a /simpleperf/record_file_reader.cpp
parent96e12e78722988e912664b7323341799fdd12b9b (diff)
downloadextras-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.cpp66
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);