Skip to content

Commit

Permalink
Merge "Add support for ARM SPE data" into main
Browse files Browse the repository at this point in the history
  • Loading branch information
carlscabgro authored and Gerrit Code Review committed Sep 29, 2024
2 parents b0c45bb + 87ecfdd commit 06e8c33
Show file tree
Hide file tree
Showing 31 changed files with 1,591 additions and 42 deletions.
7 changes: 7 additions & 0 deletions Android.bp
Original file line number Diff line number Diff line change
Expand Up @@ -12642,6 +12642,8 @@ filegroup {
"src/trace_processor/importers/perf/record_parser.cc",
"src/trace_processor/importers/perf/sample.cc",
"src/trace_processor/importers/perf/sample_id.cc",
"src/trace_processor/importers/perf/spe_record_parser.cc",
"src/trace_processor/importers/perf/spe_tokenizer.cc",
],
}

Expand Down Expand Up @@ -13398,6 +13400,7 @@ python_binary_host {
"src/trace_processor/tables/jit_tables.py",
"src/trace_processor/tables/memory_tables.py",
"src/trace_processor/tables/metadata_tables.py",
"src/trace_processor/tables/perf_tables.py",
"src/trace_processor/tables/profiler_tables.py",
"src/trace_processor/tables/sched_tables.py",
"src/trace_processor/tables/slice_tables.py",
Expand Down Expand Up @@ -13568,6 +13571,7 @@ genrule {
"src/trace_processor/perfetto_sql/stdlib/linux/memory/high_watermark.sql",
"src/trace_processor/perfetto_sql/stdlib/linux/memory/process.sql",
"src/trace_processor/perfetto_sql/stdlib/linux/perf/samples.sql",
"src/trace_processor/perfetto_sql/stdlib/linux/perf/spe.sql",
"src/trace_processor/perfetto_sql/stdlib/linux/threads.sql",
"src/trace_processor/perfetto_sql/stdlib/pkvm/hypervisor.sql",
"src/trace_processor/perfetto_sql/stdlib/prelude/casts.sql",
Expand Down Expand Up @@ -13794,6 +13798,7 @@ genrule {
"src/trace_processor/tables/jit_tables.py",
"src/trace_processor/tables/memory_tables.py",
"src/trace_processor/tables/metadata_tables.py",
"src/trace_processor/tables/perf_tables.py",
"src/trace_processor/tables/profiler_tables.py",
"src/trace_processor/tables/sched_tables.py",
"src/trace_processor/tables/slice_tables.py",
Expand All @@ -13813,6 +13818,7 @@ genrule {
"src/trace_processor/tables/jit_tables_py.h",
"src/trace_processor/tables/memory_tables_py.h",
"src/trace_processor/tables/metadata_tables_py.h",
"src/trace_processor/tables/perf_tables_py.h",
"src/trace_processor/tables/profiler_tables_py.h",
"src/trace_processor/tables/sched_tables_py.h",
"src/trace_processor/tables/slice_tables_py.h",
Expand All @@ -13836,6 +13842,7 @@ python_binary_host {
"src/trace_processor/tables/jit_tables.py",
"src/trace_processor/tables/memory_tables.py",
"src/trace_processor/tables/metadata_tables.py",
"src/trace_processor/tables/perf_tables.py",
"src/trace_processor/tables/profiler_tables.py",
"src/trace_processor/tables/sched_tables.py",
"src/trace_processor/tables/slice_tables.py",
Expand Down
8 changes: 8 additions & 0 deletions BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -1816,6 +1816,11 @@ perfetto_filegroup(
"src/trace_processor/importers/perf/sample.h",
"src/trace_processor/importers/perf/sample_id.cc",
"src/trace_processor/importers/perf/sample_id.h",
"src/trace_processor/importers/perf/spe.h",
"src/trace_processor/importers/perf/spe_record_parser.cc",
"src/trace_processor/importers/perf/spe_record_parser.h",
"src/trace_processor/importers/perf/spe_tokenizer.cc",
"src/trace_processor/importers/perf/spe_tokenizer.h",
"src/trace_processor/importers/perf/time_conv_record.h",
"src/trace_processor/importers/perf/util.h",
],
Expand Down Expand Up @@ -2862,6 +2867,7 @@ perfetto_filegroup(
name = "src_trace_processor_perfetto_sql_stdlib_linux_perf_perf",
srcs = [
"src/trace_processor/perfetto_sql/stdlib/linux/perf/samples.sql",
"src/trace_processor/perfetto_sql/stdlib/linux/perf/spe.sql",
],
)

Expand Down Expand Up @@ -3156,6 +3162,7 @@ perfetto_cc_tp_tables(
"src/trace_processor/tables/jit_tables.py",
"src/trace_processor/tables/memory_tables.py",
"src/trace_processor/tables/metadata_tables.py",
"src/trace_processor/tables/perf_tables.py",
"src/trace_processor/tables/profiler_tables.py",
"src/trace_processor/tables/sched_tables.py",
"src/trace_processor/tables/slice_tables.py",
Expand All @@ -3171,6 +3178,7 @@ perfetto_cc_tp_tables(
"src/trace_processor/tables/jit_tables_py.h",
"src/trace_processor/tables/memory_tables_py.h",
"src/trace_processor/tables/metadata_tables_py.h",
"src/trace_processor/tables/perf_tables_py.h",
"src/trace_processor/tables/profiler_tables_py.h",
"src/trace_processor/tables/sched_tables_py.h",
"src/trace_processor/tables/slice_tables_py.h",
Expand Down
9 changes: 5 additions & 4 deletions src/trace_processor/importers/common/trace_parser.cc
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,13 @@
namespace perfetto {
namespace trace_processor {

ProtoTraceParser::~ProtoTraceParser() = default;
JsonTraceParser::~JsonTraceParser() = default;
AndroidLogEventParser::~AndroidLogEventParser() = default;
FuchsiaRecordParser::~FuchsiaRecordParser() = default;
PerfRecordParser::~PerfRecordParser() = default;
InstrumentsRowParser::~InstrumentsRowParser() = default;
AndroidLogEventParser::~AndroidLogEventParser() = default;
JsonTraceParser::~JsonTraceParser() = default;
PerfRecordParser::~PerfRecordParser() = default;
ProtoTraceParser::~ProtoTraceParser() = default;
SpeRecordParser::~SpeRecordParser() = default;

} // namespace trace_processor
} // namespace perfetto
6 changes: 6 additions & 0 deletions src/trace_processor/importers/common/trace_parser.h
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,12 @@ class PerfRecordParser {
virtual void ParsePerfRecord(int64_t, perf_importer::Record) = 0;
};

class SpeRecordParser {
public:
virtual ~SpeRecordParser();
virtual void ParseSpeRecord(int64_t, TraceBlobView) = 0;
};

class InstrumentsRowParser {
public:
virtual ~InstrumentsRowParser();
Expand Down
5 changes: 5 additions & 0 deletions src/trace_processor/importers/perf/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,11 @@ source_set("perf") {
"sample.h",
"sample_id.cc",
"sample_id.h",
"spe.h",
"spe_record_parser.cc",
"spe_record_parser.h",
"spe_tokenizer.cc",
"spe_tokenizer.h",
"time_conv_record.h",
"util.h",
]
Expand Down
1 change: 1 addition & 0 deletions src/trace_processor/importers/perf/aux_record.cc
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
namespace perfetto::trace_processor::perf_importer {
// static
base::Status AuxRecord::Parse(const Record& record) {
attr = record.attr;
Reader reader(record.payload.copy());
if (!reader.Read(offset) || !reader.Read(size) || !reader.Read(flags)) {
return base::ErrStatus("Failed to parse AUX record");
Expand Down
3 changes: 3 additions & 0 deletions src/trace_processor/importers/perf/aux_record.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@
#include <optional>

#include "perfetto/base/status.h"
#include "perfetto/trace_processor/ref_counted.h"
#include "src/trace_processor/importers/perf/perf_event_attr.h"
#include "src/trace_processor/importers/perf/sample_id.h"

namespace perfetto::trace_processor::perf_importer {
Expand All @@ -30,6 +32,7 @@ struct AuxRecord {
base::Status Parse(const Record& record);
uint64_t end() const { return offset + size; }

RefPtr<PerfEventAttr> attr;
uint64_t offset;
uint64_t size;
uint64_t flags;
Expand Down
5 changes: 5 additions & 0 deletions src/trace_processor/importers/perf/aux_stream_manager.cc
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
#include "src/trace_processor/importers/perf/etm_tokenizer.h"
#include "src/trace_processor/importers/perf/perf_event.h"
#include "src/trace_processor/importers/perf/record.h"
#include "src/trace_processor/importers/perf/spe_tokenizer.h"
#include "src/trace_processor/storage/trace_storage.h"
#include "src/trace_processor/types/trace_processor_context.h"
#include "src/trace_processor/util/status_macros.h"
Expand Down Expand Up @@ -58,6 +59,10 @@ base::Status AuxStreamManager::OnAuxtraceInfoRecord(AuxtraceInfoRecord info) {
CreateEtmTokenizerFactory(std::move(info.payload)));
break;
}
case PERF_AUXTRACE_ARM_SPE: {
tokenizer_factory_ = std::make_unique<SpeTokenizerFactory>();
break;
}
default:
context_->storage->IncrementIndexedStats(stats::perf_unknown_aux_data,
static_cast<int>(info.type));
Expand Down
15 changes: 15 additions & 0 deletions src/trace_processor/importers/perf/aux_stream_manager.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
#include "src/trace_processor/importers/perf/itrace_start_record.h"
#include "src/trace_processor/importers/perf/perf_session.h"
#include "src/trace_processor/importers/perf/time_conv_record.h"
#include "src/trace_processor/storage/stats.h"

namespace perfetto {
namespace trace_processor {
Expand All @@ -58,6 +59,7 @@ class AuxStream {
base::Status OnItraceStartRecord(ItraceStartRecord start) {
return tokenizer_->OnItraceStartRecord(std::move(start));
}
std::optional<uint64_t> ConvertTscToPerfTime(uint64_t cycles);

private:
class AuxtraceDataChunk {
Expand Down Expand Up @@ -109,6 +111,14 @@ class AuxStreamManager {

TraceProcessorContext* context() const { return context_; }

std::optional<uint64_t> ConvertTscToPerfTime(uint64_t cycles) {
if (!time_conv_) {
context_->storage->IncrementStats(stats::perf_no_tsc_data);
return std::nullopt;
}
return time_conv_->ConvertTscToPerfTime(cycles);
}

private:
base::StatusOr<std::reference_wrapper<AuxStream>>
GetOrCreateStreamForSampleId(const std::optional<SampleId>& sample_id);
Expand All @@ -122,6 +132,11 @@ class AuxStreamManager {
std::optional<TimeConvRecord> time_conv_;
};

inline std::optional<uint64_t> AuxStream::ConvertTscToPerfTime(
uint64_t cycles) {
return manager_.ConvertTscToPerfTime(cycles);
}

} // namespace perf_importer
} // namespace trace_processor
} // namespace perfetto
Expand Down
30 changes: 16 additions & 14 deletions src/trace_processor/importers/perf/perf_session.cc
Original file line number Diff line number Diff line change
Expand Up @@ -58,17 +58,20 @@ base::StatusOr<RefPtr<PerfSession>> PerfSession::Builder::Build() {
auto perf_session_id =
context_->storage->mutable_perf_session_table()->Insert({}).id;

PerfEventAttr base_attr(context_, perf_session_id, attr_with_ids_[0].attr);
RefPtr<PerfEventAttr> first_attr;
base::FlatHashMap<uint64_t, RefPtr<PerfEventAttr>> attrs_by_id;
for (const auto& entry : attr_with_ids_) {
RefPtr<PerfEventAttr> attr(
new PerfEventAttr(context_, perf_session_id, entry.attr));
if (base_attr.sample_id_all() != attr->sample_id_all()) {
if (!first_attr) {
first_attr = attr;
}
if (first_attr->sample_id_all() != attr->sample_id_all()) {
return base::ErrStatus(
"perf_event_attr with different sample_id_all values");
}

if (!OffsetsMatch(base_attr, *attr)) {
if (!OffsetsMatch(*first_attr, *attr)) {
return base::ErrStatus("perf_event_attr with different id offsets");
}

Expand All @@ -80,14 +83,14 @@ base::StatusOr<RefPtr<PerfSession>> PerfSession::Builder::Build() {
}
}
if (attr_with_ids_.size() > 1 &&
(!base_attr.id_offset_from_start().has_value() ||
(base_attr.sample_id_all() &&
!base_attr.id_offset_from_end().has_value()))) {
(!first_attr->id_offset_from_start().has_value() ||
(first_attr->sample_id_all() &&
!first_attr->id_offset_from_end().has_value()))) {
return base::ErrStatus("No id offsets for multiple perf_event_attr");
}
return RefPtr<PerfSession>(new PerfSession(context_, perf_session_id,
std::move(attrs_by_id),
attr_with_ids_.size() == 1));
return RefPtr<PerfSession>(
new PerfSession(context_, perf_session_id, std::move(first_attr),
std::move(attrs_by_id), attr_with_ids_.size() == 1));
}

base::StatusOr<RefPtr<PerfEventAttr>> PerfSession::FindAttrForRecord(
Expand All @@ -97,13 +100,12 @@ base::StatusOr<RefPtr<PerfEventAttr>> PerfSession::FindAttrForRecord(
return RefPtr<PerfEventAttr>();
}

RefPtr<PerfEventAttr> first(attrs_by_id_.GetIterator().value().get());
if (has_single_perf_event_attr_) {
return first;
return first_attr_;
}

if (header.type != PERF_RECORD_SAMPLE && !first->sample_id_all()) {
return first;
if (header.type != PERF_RECORD_SAMPLE && !first_attr_->sample_id_all()) {
return first_attr_;
}

uint64_t id;
Expand All @@ -112,7 +114,7 @@ base::StatusOr<RefPtr<PerfEventAttr>> PerfSession::FindAttrForRecord(
}

if (id == 0) {
return first;
return first_attr_;
}

auto it = FindAttrForEventId(id);
Expand Down
4 changes: 4 additions & 0 deletions src/trace_processor/importers/perf/perf_session.h
Original file line number Diff line number Diff line change
Expand Up @@ -109,10 +109,12 @@ class PerfSession : public RefCounted {

PerfSession(TraceProcessorContext* context,
tables::PerfSessionTable::Id perf_session_id,
RefPtr<PerfEventAttr> first_attr,
base::FlatHashMap<uint64_t, RefPtr<PerfEventAttr>> attrs_by_id,
bool has_single_perf_event_attr)
: context_(context),
perf_session_id_(perf_session_id),
first_attr_(std::move(first_attr)),
attrs_by_id_(std::move(attrs_by_id)),
has_single_perf_event_attr_(has_single_perf_event_attr) {}

Expand All @@ -122,7 +124,9 @@ class PerfSession : public RefCounted {

TraceProcessorContext* const context_;
tables::PerfSessionTable::Id perf_session_id_;
RefPtr<PerfEventAttr> first_attr_;
base::FlatHashMap<uint64_t, RefPtr<PerfEventAttr>> attrs_by_id_;

// Multiple ids can map to the same perf_event_attr. This member tells us
// whether there was only one perf_event_attr (with potentially different ids
// associated). This makes the attr lookup given a record trivial and not
Expand Down
Loading

0 comments on commit 06e8c33

Please sign in to comment.