diff options
author | Yabin Cui <yabinc@google.com> | 2018-03-21 14:34:29 -0700 |
---|---|---|
committer | Yabin Cui <yabinc@google.com> | 2018-03-21 14:44:09 -0700 |
commit | 8cd9233b017d3fd0389c2650fcbbae74ef8ced12 (patch) | |
tree | beb2bcd49628a4015b45af037193fdd6b8065202 | |
parent | 7d2ecc6c0b1c6ecb4c46cc2f981e43461958a6bc (diff) | |
download | extras-8cd9233b017d3fd0389c2650fcbbae74ef8ced12.tar.gz |
simpleperf: add SIMPLE_PERF_RECORD_TRACE_DATA record type.
PERF_RECORD_TRACE_DATA can't have record size >= 64K. This causes
some aborts when recording tracepoint events, as in
https://github.com/android-ndk/ndk/issues/493.
So fix this by adding a custom type SIMPLE_PERF_RECORD_TRACING_DATA,
which isn't limited by 64K.
Also fix an error parsing formats of tracepoing events.
Bug: http://b/75278602
Test: run simpleperf_unit_test.
Change-Id: Ib5ebd0b6f981b00c2a256d17cdfd0e725d75a272
-rw-r--r-- | simpleperf/cmd_kmem.cpp | 3 | ||||
-rw-r--r-- | simpleperf/cmd_report.cpp | 3 | ||||
-rw-r--r-- | simpleperf/cmd_report_test.cpp | 5 | ||||
-rw-r--r-- | simpleperf/cmd_trace_sched.cpp | 3 | ||||
-rw-r--r-- | simpleperf/get_test_data.h | 3 | ||||
-rw-r--r-- | simpleperf/record.cpp | 5 | ||||
-rw-r--r-- | simpleperf/record.h | 1 | ||||
-rw-r--r-- | simpleperf/testdata/perf_with_big_trace_data.data | bin | 0 -> 491147 bytes | |||
-rw-r--r-- | simpleperf/tracing.cpp | 20 |
9 files changed, 34 insertions, 9 deletions
diff --git a/simpleperf/cmd_kmem.cpp b/simpleperf/cmd_kmem.cpp index 6ae908d6..5d58c394 100644 --- a/simpleperf/cmd_kmem.cpp +++ b/simpleperf/cmd_kmem.cpp @@ -611,7 +611,8 @@ bool KmemCommand::ProcessRecord(std::unique_ptr<Record> record) { slab_sample_tree_builder_->ProcessSampleRecord( *static_cast<const SampleRecord*>(record.get())); } - } else if (record->type() == PERF_RECORD_TRACING_DATA) { + } else if (record->type() == PERF_RECORD_TRACING_DATA || + record->type() == SIMPLE_PERF_RECORD_TRACING_DATA) { const auto& r = *static_cast<TracingDataRecord*>(record.get()); ProcessTracingData(std::vector<char>(r.data, r.data + r.data_size)); } diff --git a/simpleperf/cmd_report.cpp b/simpleperf/cmd_report.cpp index 9aee30ac..6a757f09 100644 --- a/simpleperf/cmd_report.cpp +++ b/simpleperf/cmd_report.cpp @@ -882,7 +882,8 @@ bool ReportCommand::ProcessRecord(std::unique_ptr<Record> record) { } else { ProcessSampleRecordInTraceOffCpuMode(std::move(record), attr_id); } - } else if (record->type() == PERF_RECORD_TRACING_DATA) { + } else if (record->type() == PERF_RECORD_TRACING_DATA || + record->type() == SIMPLE_PERF_RECORD_TRACING_DATA) { const auto& r = *static_cast<TracingDataRecord*>(record.get()); if (!ProcessTracingData(std::vector<char>(r.data, r.data + r.data_size))) { return false; diff --git a/simpleperf/cmd_report_test.cpp b/simpleperf/cmd_report_test.cpp index 28f226d2..6ebbf31e 100644 --- a/simpleperf/cmd_report_test.cpp +++ b/simpleperf/cmd_report_test.cpp @@ -486,6 +486,11 @@ TEST_F(ReportCommandTest, report_offcpu_time) { ASSERT_TRUE(found); } +TEST_F(ReportCommandTest, report_big_trace_data) { + Report(PERF_DATA_WITH_BIG_TRACE_DATA); + ASSERT_TRUE(success); +} + #if defined(__linux__) #include "event_selection_set.h" diff --git a/simpleperf/cmd_trace_sched.cpp b/simpleperf/cmd_trace_sched.cpp index 7f9b00fe..afef072d 100644 --- a/simpleperf/cmd_trace_sched.cpp +++ b/simpleperf/cmd_trace_sched.cpp @@ -251,7 +251,8 @@ void TraceSchedCommand::ProcessRecord(Record& record) { child_thread.name = parent_thread.name; break; } - case PERF_RECORD_TRACING_DATA: { + case PERF_RECORD_TRACING_DATA: + case SIMPLE_PERF_RECORD_TRACING_DATA: { const TracingDataRecord& r = *static_cast<const TracingDataRecord*>(&record); Tracing tracing(std::vector<char>(r.data, r.data + r.data_size)); const EventType* event = FindEventTypeByName("sched:sched_stat_runtime"); diff --git a/simpleperf/get_test_data.h b/simpleperf/get_test_data.h index f9a5759d..779afcdf 100644 --- a/simpleperf/get_test_data.h +++ b/simpleperf/get_test_data.h @@ -120,4 +120,7 @@ static const std::string PERF_DATA_NO_UNWIND = "perf_no_unwind.data"; // generated by `simpleperf record -a -e sched:sched_stat_runtime`. static const std::string PERF_DATA_SCHED_STAT_RUNTIME = "perf_sched_stat_runtime.data"; +// generated by `simpleperf record -e (about 200 tracepoint events) sleep 1`. +static const std::string PERF_DATA_WITH_BIG_TRACE_DATA = "perf_with_big_trace_data.data"; + #endif // SIMPLE_PERF_GET_TEST_DATA_H_ diff --git a/simpleperf/record.cpp b/simpleperf/record.cpp index a03f3771..5fd762c7 100644 --- a/simpleperf/record.cpp +++ b/simpleperf/record.cpp @@ -51,6 +51,7 @@ static std::string RecordTypeToString(int record_type) { {SIMPLE_PERF_RECORD_EVENT_ID, "event_id"}, {SIMPLE_PERF_RECORD_CALLCHAIN, "callchain"}, {SIMPLE_PERF_RECORD_UNWINDING_RESULT, "unwinding_result"}, + {SIMPLE_PERF_RECORD_TRACING_DATA, "tracing_data"}, }; auto it = record_type_names.find(record_type); @@ -990,7 +991,7 @@ TracingDataRecord::TracingDataRecord(char* p) : Record(p) { } TracingDataRecord::TracingDataRecord(const std::vector<char>& tracing_data) { - SetTypeAndMisc(PERF_RECORD_TRACING_DATA, 0); + SetTypeAndMisc(SIMPLE_PERF_RECORD_TRACING_DATA, 0); data_size = tracing_data.size(); SetSize(header_size() + sizeof(uint32_t) + Align(tracing_data.size(), 64)); char* new_binary = new char[size()]; @@ -1193,6 +1194,8 @@ std::unique_ptr<Record> ReadRecordFromBuffer(const perf_event_attr& attr, uint32 return std::unique_ptr<Record>(new CallChainRecord(p)); case SIMPLE_PERF_RECORD_UNWINDING_RESULT: return std::unique_ptr<Record>(new UnwindingResultRecord(p)); + case SIMPLE_PERF_RECORD_TRACING_DATA: + return std::unique_ptr<Record>(new TracingDataRecord(p)); default: return std::unique_ptr<Record>(new UnknownRecord(p)); } diff --git a/simpleperf/record.h b/simpleperf/record.h index b862e401..f9041c51 100644 --- a/simpleperf/record.h +++ b/simpleperf/record.h @@ -50,6 +50,7 @@ enum user_record_type { SIMPLE_PERF_RECORD_EVENT_ID, SIMPLE_PERF_RECORD_CALLCHAIN, SIMPLE_PERF_RECORD_UNWINDING_RESULT, + SIMPLE_PERF_RECORD_TRACING_DATA, }; // perf_event_header uses u16 to store record size. However, that is not diff --git a/simpleperf/testdata/perf_with_big_trace_data.data b/simpleperf/testdata/perf_with_big_trace_data.data Binary files differnew file mode 100644 index 00000000..5134ec52 --- /dev/null +++ b/simpleperf/testdata/perf_with_big_trace_data.data diff --git a/simpleperf/tracing.cpp b/simpleperf/tracing.cpp index 966bbd0e..908402b4 100644 --- a/simpleperf/tracing.cpp +++ b/simpleperf/tracing.cpp @@ -24,6 +24,7 @@ #include <android-base/file.h> #include <android-base/logging.h> +#include <android-base/parseint.h> #include <android-base/stringprintf.h> #include <android-base/strings.h> @@ -295,14 +296,23 @@ static TracingField ParseTracingField(const std::string& s) { } else if (s[i] == ';') { value = s.substr(start, i - start); if (name == "field") { - size_t pos = value.find('['); - if (pos == std::string::npos) { + // Parse value with brackets like "comm[16]", or just a field name. + size_t left_bracket_pos = value.find('['); + if (left_bracket_pos == std::string::npos) { field.name = value; field.elem_count = 1; } else { - field.name = value.substr(0, pos); - field.elem_count = - static_cast<size_t>(strtoull(&value[pos + 1], nullptr, 10)); + field.name = value.substr(0, left_bracket_pos); + field.elem_count = 1; + size_t right_bracket_pos = value.find(']', left_bracket_pos); + if (right_bracket_pos != std::string::npos) { + size_t len = right_bracket_pos - left_bracket_pos - 1; + size_t elem_count; + // Array size may not be a number, like field:u32 rates[IEEE80211_NUM_BANDS]. + if (android::base::ParseUint(value.substr(left_bracket_pos + 1, len), &elem_count)) { + field.elem_count = elem_count; + } + } } } else if (name == "offset") { field.offset = |