Add signal events to t2t and trace processor
These events are added into a new table called "instants" for
instantaneous events.
Bug: 118687476
Change-Id: I1ea7953436cbf3e4139fa3a5db3624f9f95c6a6f
diff --git a/src/trace_processor/BUILD.gn b/src/trace_processor/BUILD.gn
index cd90729..124c7cb 100644
--- a/src/trace_processor/BUILD.gn
+++ b/src/trace_processor/BUILD.gn
@@ -47,6 +47,8 @@
"counters_table.h",
"event_tracker.cc",
"event_tracker.h",
+ "instants_table.cc",
+ "instants_table.h",
"process_table.cc",
"process_table.h",
"process_tracker.cc",
diff --git a/src/trace_processor/instants_table.cc b/src/trace_processor/instants_table.cc
new file mode 100644
index 0000000..d5399a9
--- /dev/null
+++ b/src/trace_processor/instants_table.cc
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "src/trace_processor/instants_table.h"
+
+#include "src/trace_processor/storage_cursor.h"
+#include "src/trace_processor/table_utils.h"
+
+namespace perfetto {
+namespace trace_processor {
+
+InstantsTable::InstantsTable(sqlite3*, const TraceStorage* storage)
+ : storage_(storage) {
+ ref_types_.resize(RefType::kMax);
+ ref_types_[RefType::kNoRef] = "";
+ ref_types_[RefType::kUtid] = "utid";
+ ref_types_[RefType::kCpuId] = "cpu";
+ ref_types_[RefType::kIrq] = "irq";
+ ref_types_[RefType::kSoftIrq] = "softirq";
+ ref_types_[RefType::kUpid] = "upid";
+};
+
+void InstantsTable::RegisterTable(sqlite3* db, const TraceStorage* storage) {
+ Table::Register<InstantsTable>(db, storage, "instants");
+}
+
+Table::Schema InstantsTable::CreateSchema(int, const char* const*) {
+ const auto& instants = storage_->instants();
+ std::unique_ptr<StorageSchema::Column> cols[] = {
+ StorageSchema::NumericColumnPtr("ts", &instants.timestamps(),
+ false /* hidden */, true /* ordered */),
+ StorageSchema::StringColumnPtr("name", &instants.name_ids(),
+ &storage_->string_pool()),
+ StorageSchema::NumericColumnPtr("value", &instants.values()),
+ StorageSchema::NumericColumnPtr("ref", &instants.refs()),
+ StorageSchema::StringColumnPtr("ref_type", &instants.types(),
+ &ref_types_)};
+ schema_ = StorageSchema({
+ std::make_move_iterator(std::begin(cols)),
+ std::make_move_iterator(std::end(cols)),
+ });
+ return schema_.ToTableSchema({"name", "ts", "ref"});
+}
+
+std::unique_ptr<Table::Cursor> InstantsTable::CreateCursor(
+ const QueryConstraints& qc,
+ sqlite3_value** argv) {
+ uint32_t count = static_cast<uint32_t>(storage_->instants().instant_count());
+ auto it = table_utils::CreateBestRowIteratorForGenericSchema(schema_, count,
+ qc, argv);
+ return std::unique_ptr<Table::Cursor>(
+ new StorageCursor(std::move(it), schema_.ToColumnReporters()));
+}
+
+int InstantsTable::BestIndex(const QueryConstraints& qc, BestIndexInfo* info) {
+ info->estimated_cost =
+ static_cast<uint32_t>(storage_->counters().counter_count());
+
+ // Only the string columns are handled by SQLite
+ info->order_by_consumed = true;
+ size_t name_index = schema_.ColumnIndexFromName("name");
+ size_t ref_type_index = schema_.ColumnIndexFromName("ref_type");
+ for (size_t i = 0; i < qc.constraints().size(); i++) {
+ info->omit[i] =
+ qc.constraints()[i].iColumn != static_cast<int>(name_index) &&
+ qc.constraints()[i].iColumn != static_cast<int>(ref_type_index);
+ }
+
+ return SQLITE_OK;
+}
+} // namespace trace_processor
+} // namespace perfetto
diff --git a/src/trace_processor/instants_table.h b/src/trace_processor/instants_table.h
new file mode 100644
index 0000000..38379fa
--- /dev/null
+++ b/src/trace_processor/instants_table.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef SRC_TRACE_PROCESSOR_INSTANTS_TABLE_H_
+#define SRC_TRACE_PROCESSOR_INSTANTS_TABLE_H_
+
+#include "src/trace_processor/storage_schema.h"
+#include "src/trace_processor/table.h"
+#include "src/trace_processor/trace_storage.h"
+
+namespace perfetto {
+namespace trace_processor {
+
+class InstantsTable : public Table {
+ public:
+ static void RegisterTable(sqlite3* db, const TraceStorage* storage);
+
+ InstantsTable(sqlite3*, const TraceStorage*);
+
+ // Table implementation.
+ Table::Schema CreateSchema(int argc, const char* const* argv) override;
+ std::unique_ptr<Table::Cursor> CreateCursor(const QueryConstraints&,
+ sqlite3_value**) override;
+ int BestIndex(const QueryConstraints&, BestIndexInfo*) override;
+
+ private:
+ std::deque<std::string> ref_types_;
+ StorageSchema schema_;
+ const TraceStorage* const storage_;
+};
+} // namespace trace_processor
+} // namespace perfetto
+
+#endif // SRC_TRACE_PROCESSOR_INSTANTS_TABLE_H_
diff --git a/src/trace_processor/proto_trace_parser.cc b/src/trace_processor/proto_trace_parser.cc
index 87da1ad..b4db65e 100644
--- a/src/trace_processor/proto_trace_parser.cc
+++ b/src/trace_processor/proto_trace_parser.cc
@@ -124,7 +124,9 @@
cpu_times_softirq_ns_id_(
context->storage->InternString("cpu.times.softirq_ns")),
ion_heap_grow_id_(context->storage->InternString("ion_heap_grow")),
- ion_heap_shrink_id_(context->storage->InternString("ion_heap_shrink")) {
+ ion_heap_shrink_id_(context->storage->InternString("ion_heap_shrink")),
+ signal_deliver_id_(context->storage->InternString("signal_deliver")),
+ signal_generate_id_(context->storage->InternString("signal_generate")) {
for (const auto& name : BuildMeminfoCounterNames()) {
meminfo_strs_id_.emplace_back(context->storage->InternString(name));
}
@@ -546,6 +548,18 @@
ParseIonHeapShrink(timestamp, pid, ftrace.slice(fld_off, fld.size()));
break;
}
+ case protos::FtraceEvent::kSignalGenerate: {
+ PERFETTO_DCHECK(timestamp > 0);
+ const size_t fld_off = ftrace.offset_of(fld.data());
+ ParseSignalGenerate(timestamp, ftrace.slice(fld_off, fld.size()));
+ break;
+ }
+ case protos::FtraceEvent::kSignalDeliver: {
+ PERFETTO_DCHECK(timestamp > 0);
+ const size_t fld_off = ftrace.offset_of(fld.data());
+ ParseSignalDeliver(timestamp, pid, ftrace.slice(fld_off, fld.size()));
+ break;
+ }
default:
break;
@@ -554,6 +568,45 @@
PERFETTO_DCHECK(decoder.IsEndOfBuffer());
}
+void ProtoTraceParser::ParseSignalDeliver(uint64_t timestamp,
+ uint32_t pid,
+ TraceBlobView view) {
+ ProtoDecoder decoder(view.data(), view.length());
+ uint32_t sig = 0;
+ for (auto fld = decoder.ReadField(); fld.id != 0; fld = decoder.ReadField()) {
+ switch (fld.id) {
+ case protos::SignalDeliverFtraceEvent::kSigFieldNumber:
+ sig = fld.as_uint32();
+ break;
+ }
+ }
+ auto* instants = context_->storage->mutable_instants();
+ UniqueTid utid = context_->process_tracker->UpdateThread(timestamp, pid, 0);
+ instants->AddInstantEvent(timestamp, signal_deliver_id_, sig, utid,
+ RefType::kUtid);
+}
+
+void ProtoTraceParser::ParseSignalGenerate(uint64_t timestamp,
+ TraceBlobView view) {
+ ProtoDecoder decoder(view.data(), view.length());
+ uint32_t pid = 0;
+ uint32_t sig = 0;
+ for (auto fld = decoder.ReadField(); fld.id != 0; fld = decoder.ReadField()) {
+ switch (fld.id) {
+ case protos::SignalGenerateFtraceEvent::kPidFieldNumber:
+ pid = fld.as_uint32();
+ break;
+ case protos::SignalGenerateFtraceEvent::kSigFieldNumber:
+ sig = fld.as_uint32();
+ break;
+ }
+ }
+ auto* instants = context_->storage->mutable_instants();
+ UniqueTid utid = context_->process_tracker->UpdateThread(timestamp, pid, 0);
+ instants->AddInstantEvent(timestamp, signal_generate_id_, sig, utid,
+ RefType::kUtid);
+}
+
void ProtoTraceParser::ParseRssStat(uint64_t timestamp,
uint32_t pid,
TraceBlobView view) {
diff --git a/src/trace_processor/proto_trace_parser.h b/src/trace_processor/proto_trace_parser.h
index 75e34f9..5767191 100644
--- a/src/trace_processor/proto_trace_parser.h
+++ b/src/trace_processor/proto_trace_parser.h
@@ -76,6 +76,8 @@
void ParseRssStat(uint64_t ts, uint32_t pid, TraceBlobView);
void ParseIonHeapGrow(uint64_t ts, uint32_t pid, TraceBlobView);
void ParseIonHeapShrink(uint64_t ts, uint32_t pid, TraceBlobView);
+ void ParseSignalDeliver(uint64_t ts, uint32_t pid, TraceBlobView);
+ void ParseSignalGenerate(uint64_t ts, TraceBlobView);
private:
TraceProcessorContext* context_;
@@ -94,6 +96,8 @@
const StringId cpu_times_softirq_ns_id_;
const StringId ion_heap_grow_id_;
const StringId ion_heap_shrink_id_;
+ const StringId signal_deliver_id_;
+ const StringId signal_generate_id_;
std::vector<StringId> meminfo_strs_id_;
std::vector<StringId> vmstat_strs_id_;
std::vector<StringId> rss_members_;
diff --git a/src/trace_processor/trace_processor_impl.cc b/src/trace_processor/trace_processor_impl.cc
index 52aa8a6..571c399 100644
--- a/src/trace_processor/trace_processor_impl.cc
+++ b/src/trace_processor/trace_processor_impl.cc
@@ -22,6 +22,7 @@
#include "perfetto/base/time.h"
#include "src/trace_processor/counters_table.h"
#include "src/trace_processor/event_tracker.h"
+#include "src/trace_processor/instants_table.h"
#include "src/trace_processor/json_trace_parser.h"
#include "src/trace_processor/process_table.h"
#include "src/trace_processor/process_tracker.h"
@@ -65,6 +66,7 @@
CountersTable::RegisterTable(*db_, context_.storage.get());
SpanOperatorTable::RegisterTable(*db_, context_.storage.get());
WindowOperatorTable::RegisterTable(*db_, context_.storage.get());
+ InstantsTable::RegisterTable(*db_, context_.storage.get());
}
TraceProcessorImpl::~TraceProcessorImpl() = default;
diff --git a/src/trace_processor/trace_storage.h b/src/trace_processor/trace_storage.h
index cc59228..57de9ed 100644
--- a/src/trace_processor/trace_storage.h
+++ b/src/trace_processor/trace_storage.h
@@ -229,6 +229,41 @@
std::deque<uint64_t> times_ended_;
};
+ class Instants {
+ public:
+ inline size_t AddInstantEvent(uint64_t timestamp,
+ StringId name_id,
+ double value,
+ int64_t ref,
+ RefType type) {
+ timestamps_.emplace_back(timestamp);
+ name_ids_.emplace_back(name_id);
+ values_.emplace_back(value);
+ refs_.emplace_back(ref);
+ types_.emplace_back(type);
+ return instant_count() - 1;
+ }
+
+ size_t instant_count() const { return timestamps_.size(); }
+
+ const std::deque<uint64_t>& timestamps() const { return timestamps_; }
+
+ const std::deque<StringId>& name_ids() const { return name_ids_; }
+
+ const std::deque<double>& values() const { return values_; }
+
+ const std::deque<int64_t>& refs() const { return refs_; }
+
+ const std::deque<RefType>& types() const { return types_; }
+
+ private:
+ std::deque<uint64_t> timestamps_;
+ std::deque<StringId> name_ids_;
+ std::deque<double> values_;
+ std::deque<int64_t> refs_;
+ std::deque<RefType> types_;
+ };
+
void ResetStorage();
UniqueTid AddEmptyThread(uint32_t tid) {
@@ -287,6 +322,9 @@
const SqlStats& sql_stats() const { return sql_stats_; }
SqlStats* mutable_sql_stats() { return &sql_stats_; }
+ const Instants& instants() const { return instants_; }
+ Instants* mutable_instants() { return &instants_; }
+
const std::deque<std::string>& string_pool() const { return string_pool_; }
// |unique_processes_| always contains at least 1 element becuase the 0th ID
@@ -331,6 +369,10 @@
Counters counters_;
SqlStats sql_stats_;
+ // These are instantaneous events in the trace. They have no duration
+ // and do not have a value that make sense to track over time.
+ // e.g. signal events
+ Instants instants_;
};
} // namespace trace_processor