Merge "stdlib: fix _get_frame_table_with_id function failure" into main
diff --git a/Android.bp b/Android.bp
index 9af453a..f1d91c9 100644
--- a/Android.bp
+++ b/Android.bp
@@ -12955,7 +12955,7 @@
"src/trace_processor/metrics/sql/android/unsymbolized_frames.sql",
"src/trace_processor/metrics/sql/android/wattson_app_startup.sql",
"src/trace_processor/metrics/sql/android/wattson_rail_relations.sql",
- "src/trace_processor/metrics/sql/android/wattson_trace_estimate.sql",
+ "src/trace_processor/metrics/sql/android/wattson_trace_rails.sql",
"src/trace_processor/metrics/sql/chrome/actual_power_by_category.sql",
"src/trace_processor/metrics/sql/chrome/actual_power_by_rail_mode.sql",
"src/trace_processor/metrics/sql/chrome/chrome_args_class_names.sql",
@@ -13511,6 +13511,7 @@
filegroup {
name: "perfetto_src_trace_processor_tables_tables",
srcs: [
+ "src/trace_processor/tables/macros_internal.cc",
"src/trace_processor/tables/table_destructors.cc",
],
}
diff --git a/BUILD b/BUILD
index 277a5de..c5ec15a 100644
--- a/BUILD
+++ b/BUILD
@@ -2207,7 +2207,7 @@
"src/trace_processor/metrics/sql/android/unsymbolized_frames.sql",
"src/trace_processor/metrics/sql/android/wattson_app_startup.sql",
"src/trace_processor/metrics/sql/android/wattson_rail_relations.sql",
- "src/trace_processor/metrics/sql/android/wattson_trace_estimate.sql",
+ "src/trace_processor/metrics/sql/android/wattson_trace_rails.sql",
],
)
@@ -3038,6 +3038,7 @@
perfetto_filegroup(
name = "src_trace_processor_tables_tables",
srcs = [
+ "src/trace_processor/tables/macros_internal.cc",
"src/trace_processor/tables/macros_internal.h",
"src/trace_processor/tables/table_destructors.cc",
],
diff --git a/protos/perfetto/config/android/windowmanager_config.proto b/protos/perfetto/config/android/windowmanager_config.proto
index 1b16890..b5ea810 100644
--- a/protos/perfetto/config/android/windowmanager_config.proto
+++ b/protos/perfetto/config/android/windowmanager_config.proto
@@ -28,6 +28,9 @@
// Trace state snapshots every time a transaction is committed.
LOG_FREQUENCY_TRANSACTION = 2;
+
+ // Trace single state snapshots when the data source is started.
+ LOG_FREQUENCY_SINGLE_DUMP = 3;
}
optional LogFrequency log_frequency = 1;
diff --git a/protos/perfetto/config/perfetto_config.proto b/protos/perfetto/config/perfetto_config.proto
index ef84765..702cb98 100644
--- a/protos/perfetto/config/perfetto_config.proto
+++ b/protos/perfetto/config/perfetto_config.proto
@@ -830,6 +830,9 @@
// Trace state snapshots every time a transaction is committed.
LOG_FREQUENCY_TRANSACTION = 2;
+
+ // Trace single state snapshots when the data source is started.
+ LOG_FREQUENCY_SINGLE_DUMP = 3;
}
optional LogFrequency log_frequency = 1;
diff --git a/protos/perfetto/metrics/metrics.proto b/protos/perfetto/metrics/metrics.proto
index 4d6477f..f6d53b8 100644
--- a/protos/perfetto/metrics/metrics.proto
+++ b/protos/perfetto/metrics/metrics.proto
@@ -321,8 +321,8 @@
// Android Wattson app startup metrics.
optional AndroidWattsonTimePeriodMetric wattson_app_startup = 69;
- // Android Wattson estimate for entire trace metrics.
- optional AndroidWattsonTimePeriodMetric wattson_trace_estimate = 70;
+ // Android Wattson rail estimate for duration of entire trace.
+ optional AndroidWattsonTimePeriodMetric wattson_trace_rails = 70;
// Android Anomaly metric
optional AndroidAnomalyMetric android_anomaly = 71;
diff --git a/protos/perfetto/metrics/perfetto_merged_metrics.proto b/protos/perfetto/metrics/perfetto_merged_metrics.proto
index cb01f51..3d91e72 100644
--- a/protos/perfetto/metrics/perfetto_merged_metrics.proto
+++ b/protos/perfetto/metrics/perfetto_merged_metrics.proto
@@ -3174,8 +3174,8 @@
// Android Wattson app startup metrics.
optional AndroidWattsonTimePeriodMetric wattson_app_startup = 69;
- // Android Wattson estimate for entire trace metrics.
- optional AndroidWattsonTimePeriodMetric wattson_trace_estimate = 70;
+ // Android Wattson rail estimate for duration of entire trace.
+ optional AndroidWattsonTimePeriodMetric wattson_trace_rails = 70;
// Android Anomaly metric
optional AndroidAnomalyMetric android_anomaly = 71;
diff --git a/protos/perfetto/trace/perfetto_trace.proto b/protos/perfetto/trace/perfetto_trace.proto
index 9d0d775..eeeacc5 100644
--- a/protos/perfetto/trace/perfetto_trace.proto
+++ b/protos/perfetto/trace/perfetto_trace.proto
@@ -830,6 +830,9 @@
// Trace state snapshots every time a transaction is committed.
LOG_FREQUENCY_TRANSACTION = 2;
+
+ // Trace single state snapshots when the data source is started.
+ LOG_FREQUENCY_SINGLE_DUMP = 3;
}
optional LogFrequency log_frequency = 1;
@@ -12465,7 +12468,6 @@
GESTURE_SCROLL_END = 4;
GESTURE_TAP = 5;
GESTURE_TAP_CANCEL = 6;
- INERTIAL_GESTURE_SCROLL_UPDATE = 7;
}
// The type of input corresponding to this `ChromeLatencyInfo`.
diff --git a/protos/perfetto/trace/track_event/chrome_latency_info.proto b/protos/perfetto/trace/track_event/chrome_latency_info.proto
index 276abea..9f791f5 100644
--- a/protos/perfetto/trace/track_event/chrome_latency_info.proto
+++ b/protos/perfetto/trace/track_event/chrome_latency_info.proto
@@ -94,7 +94,6 @@
GESTURE_SCROLL_END = 4;
GESTURE_TAP = 5;
GESTURE_TAP_CANCEL = 6;
- INERTIAL_GESTURE_SCROLL_UPDATE = 7;
}
// The type of input corresponding to this `ChromeLatencyInfo`.
diff --git a/python/generators/trace_processor_table/serialize.py b/python/generators/trace_processor_table/serialize.py
index 24c243b..c347685 100644
--- a/python/generators/trace_processor_table/serialize.py
+++ b/python/generators/trace_processor_table/serialize.py
@@ -80,7 +80,7 @@
def const_row_ref_getter(self) -> Optional[str]:
return f'''ColumnType::{self.name}::type {self.name}() const {{
- return table_->{self.name}()[row_number_];
+ return table()->{self.name}()[row_number_];
}}'''
def row_ref_getter(self) -> Optional[str]:
@@ -169,7 +169,7 @@
name = self.name
return f'''
ColumnType::{self.name}::type {name}() const {{
- const auto& col = table_->{name}();
+ const auto& col = table()->{name}();
return col.GetAtIdx(
iterator_.StorageIndexForColumn(col.index_in_table()));
}}
@@ -385,7 +385,7 @@
private:
{self.table_name}* mutable_table() const {{
- return const_cast<{self.table_name}*>(table_);
+ return const_cast<{self.table_name}*>(table());
}}
}};
static_assert(std::is_trivially_destructible_v<RowReference>,
@@ -495,17 +495,14 @@
class Iterator : public ConstIterator {{
public:
RowReference row_reference() const {{
- return RowReference(mutable_table_, CurrentRowNumber());
+ return {{const_cast<{self.table_name}*>(table()), CurrentRowNumber()}};
}}
private:
friend class {self.table_name};
explicit Iterator({self.table_name}* table, Table::Iterator iterator)
- : ConstIterator(table, std::move(iterator)),
- mutable_table_(table) {{}}
-
- {self.table_name}* mutable_table_ = nullptr;
+ : ConstIterator(table, std::move(iterator)) {{}}
}};
'''
@@ -518,15 +515,15 @@
ColumnSerializer.extend_parent_param_arg, delimiter=', ')
delim = ',' if params else ''
return f'''
- static std::unique_ptr<Table> ExtendParent(
+ static std::unique_ptr<{self.table_name}> ExtendParent(
const {self.parent_class_name}& parent{delim}
{params}) {{
- return std::unique_ptr<Table>(new {self.table_name}(
+ return std::unique_ptr<{self.table_name}>(new {self.table_name}(
parent.string_pool(), parent, RowMap(0, parent.row_count()){delim}
{args}));
}}
- static std::unique_ptr<Table> SelectAndExtendParent(
+ static std::unique_ptr<{self.table_name}> SelectAndExtendParent(
const {self.parent_class_name}& parent,
std::vector<{self.parent_class_name}::RowNumber> parent_overlay{delim}
{params}) {{
@@ -534,7 +531,7 @@
for (uint32_t i = 0; i < parent_overlay.size(); ++i) {{
prs_untyped[i] = parent_overlay[i].row_number();
}}
- return std::unique_ptr<Table>(new {self.table_name}(
+ return std::unique_ptr<{self.table_name}>(new {self.table_name}(
parent.string_pool(), parent, RowMap(std::move(prs_untyped)){delim}
{args}));
}}
@@ -660,18 +657,28 @@
Iterator IterateRows() {{ return Iterator(this, Table::IterateRows()); }}
ConstIterator FilterToIterator(const Query& q) const {{
- return ConstIterator(
- this, ApplyAndIterateRows(QueryToRowMap(q)));
+ return ConstIterator(this, QueryToIterator(q));
}}
Iterator FilterToIterator(const Query& q) {{
- return Iterator(this, ApplyAndIterateRows(QueryToRowMap(q)));
+ return Iterator(this, QueryToIterator(q));
}}
void ShrinkToFit() {{
{self.foreach_col(ColumnSerializer.shrink_to_fit)}
}}
+ ConstRowReference operator[](uint32_t r) const {{
+ return ConstRowReference(this, r);
+ }}
+ RowReference operator[](uint32_t r) {{ return RowReference(this, r); }}
+ ConstRowReference operator[](RowNumber r) const {{
+ return ConstRowReference(this, r.row_number());
+ }}
+ RowReference operator[](RowNumber r) {{
+ return RowReference(this, r.row_number());
+ }}
+
std::optional<ConstRowReference> FindById(Id find_id) const {{
std::optional<uint32_t> row = id().IndexOf(find_id);
return row ? std::make_optional(ConstRowReference(this, *row))
diff --git a/python/perfetto/trace_processor/metrics.descriptor b/python/perfetto/trace_processor/metrics.descriptor
index cd4ad17..1e2da15 100644
--- a/python/perfetto/trace_processor/metrics.descriptor
+++ b/python/perfetto/trace_processor/metrics.descriptor
Binary files differ
diff --git a/src/trace_processor/BUILD.gn b/src/trace_processor/BUILD.gn
index aba2613..53e8a1c 100644
--- a/src/trace_processor/BUILD.gn
+++ b/src/trace_processor/BUILD.gn
@@ -56,9 +56,12 @@
"../../gn:default_deps",
"../../include/perfetto/ext/trace_processor:export_json",
"../base",
+ "containers",
"importers/json:minimal",
"storage",
+ "tables",
"types",
+ "util",
]
public_deps = [ "../../include/perfetto/ext/trace_processor:export_json" ]
}
@@ -238,6 +241,18 @@
]
}
}
+
+ # Shell target which does not link all the extra libraryes linked by
+ # trace processor shell (e.g. httpd, libprotobuf etc.). Use for binary size
+ # analysis of the trace processor library.
+ executable("trace_processor_minimal_shell") {
+ deps = [
+ ":lib",
+ "../../gn:default_deps",
+ "util",
+ ]
+ sources = [ "minimal_shell.cc" ]
+ }
} # if (enable_perfetto_trace_processor_sqlite)
perfetto_unittest_source_set("top_level_unittests") {
@@ -268,6 +283,7 @@
"importers/common",
"importers/proto:minimal",
"storage",
+ "tables",
"types",
]
}
diff --git a/src/trace_processor/db/column.h b/src/trace_processor/db/column.h
index 0bbd929..1e3016c 100644
--- a/src/trace_processor/db/column.h
+++ b/src/trace_processor/db/column.h
@@ -214,62 +214,6 @@
// Gets the value of the Column at the given |row|.
SqlValue Get(uint32_t row) const { return GetAtIdx(overlay().Get(row)); }
- // Returns the row containing the given value in the Column.
- std::optional<uint32_t> IndexOf(SqlValue value) const {
- switch (type_) {
- // TODO(lalitm): investigate whether we could make this more efficient
- // by first checking the type of the column and comparing explicitly
- // based on that type.
- case ColumnType::kInt32:
- case ColumnType::kUint32:
- case ColumnType::kInt64:
- case ColumnType::kDouble:
- case ColumnType::kString: {
- for (uint32_t i = 0; i < overlay().size(); i++) {
- if (compare::SqlValue(Get(i), value) == 0)
- return i;
- }
- return std::nullopt;
- }
- case ColumnType::kId: {
- if (value.type != SqlValue::Type::kLong)
- return std::nullopt;
- return overlay().RowOf(static_cast<uint32_t>(value.long_value));
- }
- case ColumnType::kDummy:
- PERFETTO_FATAL("IndexOf not allowed on dummy column");
- }
- PERFETTO_FATAL("For GCC");
- }
-
- // Returns the minimum value in this column. Returns std::nullopt if this
- // column is empty.
- std::optional<SqlValue> Min() const {
- if (overlay().empty())
- return std::nullopt;
-
- if (IsSorted())
- return Get(0);
-
- Iterator b(this, 0);
- Iterator e(this, overlay().size());
- return *std::min_element(b, e, &compare::SqlValueComparator);
- }
-
- // Returns the minimum value in this column. Returns std::nullopt if this
- // column is empty.
- std::optional<SqlValue> Max() const {
- if (overlay().empty())
- return std::nullopt;
-
- if (IsSorted())
- return Get(overlay().size() - 1);
-
- Iterator b(this, 0);
- Iterator e(this, overlay().size());
- return *std::max_element(b, e, &compare::SqlValueComparator);
- }
-
// Returns the backing RowMap for this Column.
// This function is defined out of line because of a circular dependency
// between |Table| and |Column|.
diff --git a/src/trace_processor/db/query_executor_benchmark.cc b/src/trace_processor/db/query_executor_benchmark.cc
index 95b64ac..5fe039a 100644
--- a/src/trace_processor/db/query_executor_benchmark.cc
+++ b/src/trace_processor/db/query_executor_benchmark.cc
@@ -103,6 +103,14 @@
return base::SplitString(table_csv, "\n");
}
+template <typename It>
+double CountRows(It it) {
+ double i = 0;
+ for (; it; ++it, ++i) {
+ }
+ return i;
+}
+
StringPool::Id StripAndIntern(StringPool& pool, const std::string& data) {
std::string res = base::StripSuffix(base::StripPrefix(data, "\""), "\"");
return pool.InternString(base::StringView(res));
@@ -237,16 +245,16 @@
Query q;
q.constraints = c;
for (auto _ : state) {
- benchmark::DoNotOptimize(table.table_.QueryToRowMap(q));
+ benchmark::DoNotOptimize(table.table_.FilterToIterator(q));
}
state.counters["s/row"] =
benchmark::Counter(static_cast<double>(table.table_.row_count()),
benchmark::Counter::kIsIterationInvariantRate |
benchmark::Counter::kInvert);
- state.counters["s/out"] = benchmark::Counter(
- static_cast<double>(table.table_.QueryToRowMap(q).size()),
- benchmark::Counter::kIsIterationInvariantRate |
- benchmark::Counter::kInvert);
+ state.counters["s/out"] =
+ benchmark::Counter(CountRows(table.table_.FilterToIterator(q)),
+ benchmark::Counter::kIsIterationInvariantRate |
+ benchmark::Counter::kInvert);
}
void BenchmarkSliceTableSort(benchmark::State& state,
@@ -266,32 +274,32 @@
ExpectedFrameTimelineTableForBenchmark& table,
Query q) {
for (auto _ : state) {
- benchmark::DoNotOptimize(table.table_.QueryToRowMap(q));
+ benchmark::DoNotOptimize(table.table_.FilterToIterator(q));
}
state.counters["s/row"] =
benchmark::Counter(static_cast<double>(table.table_.row_count()),
benchmark::Counter::kIsIterationInvariantRate |
benchmark::Counter::kInvert);
- state.counters["s/out"] = benchmark::Counter(
- static_cast<double>(table.table_.QueryToRowMap(q).size()),
- benchmark::Counter::kIsIterationInvariantRate |
- benchmark::Counter::kInvert);
+ state.counters["s/out"] =
+ benchmark::Counter(CountRows(table.table_.FilterToIterator(q)),
+ benchmark::Counter::kIsIterationInvariantRate |
+ benchmark::Counter::kInvert);
}
void BenchmarkFtraceEventTableQuery(benchmark::State& state,
FtraceEventTableForBenchmark& table,
Query q) {
for (auto _ : state) {
- benchmark::DoNotOptimize(table.table_.QueryToRowMap(q));
+ benchmark::DoNotOptimize(table.table_.FilterToIterator(q));
}
state.counters["s/row"] =
benchmark::Counter(static_cast<double>(table.table_.row_count()),
benchmark::Counter::kIsIterationInvariantRate |
benchmark::Counter::kInvert);
- state.counters["s/out"] = benchmark::Counter(
- static_cast<double>(table.table_.QueryToRowMap(q).size()),
- benchmark::Counter::kIsIterationInvariantRate |
- benchmark::Counter::kInvert);
+ state.counters["s/out"] =
+ benchmark::Counter(CountRows(table.table_.FilterToIterator(q)),
+ benchmark::Counter::kIsIterationInvariantRate |
+ benchmark::Counter::kInvert);
}
void BenchmarkFtraceEventTableSort(benchmark::State& state,
@@ -441,16 +449,16 @@
Query q;
q.constraints = {c};
for (auto _ : state) {
- benchmark::DoNotOptimize(table.table_.QueryToRowMap(q));
+ benchmark::DoNotOptimize(table.table_.FilterToIterator(q));
}
state.counters["s/row"] =
benchmark::Counter(static_cast<double>(table.table_.row_count()),
benchmark::Counter::kIsIterationInvariantRate |
benchmark::Counter::kInvert);
- state.counters["s/out"] = benchmark::Counter(
- static_cast<double>(table.table_.QueryToRowMap(q).size()),
- benchmark::Counter::kIsIterationInvariantRate |
- benchmark::Counter::kInvert);
+ state.counters["s/out"] =
+ benchmark::Counter(CountRows(table.table_.FilterToIterator(q)),
+ benchmark::Counter::kIsIterationInvariantRate |
+ benchmark::Counter::kInvert);
}
BENCHMARK(BM_QEDenseNullFilter);
@@ -461,16 +469,16 @@
Query q;
q.constraints = {c};
for (auto _ : state) {
- benchmark::DoNotOptimize(table.table_.QueryToRowMap(q));
+ benchmark::DoNotOptimize(table.table_.FilterToIterator(q));
}
state.counters["s/row"] =
benchmark::Counter(static_cast<double>(table.table_.row_count()),
benchmark::Counter::kIsIterationInvariantRate |
benchmark::Counter::kInvert);
- state.counters["s/out"] = benchmark::Counter(
- static_cast<double>(table.table_.QueryToRowMap(q).size()),
- benchmark::Counter::kIsIterationInvariantRate |
- benchmark::Counter::kInvert);
+ state.counters["s/out"] =
+ benchmark::Counter(CountRows(table.table_.FilterToIterator(q)),
+ benchmark::Counter::kIsIterationInvariantRate |
+ benchmark::Counter::kInvert);
}
BENCHMARK(BM_QEDenseNullFilterIsNull);
diff --git a/src/trace_processor/db/table.cc b/src/trace_processor/db/table.cc
index 50f383a..d581bc0 100644
--- a/src/trace_processor/db/table.cc
+++ b/src/trace_processor/db/table.cc
@@ -20,10 +20,12 @@
#include <cstdint>
#include <memory>
#include <optional>
+#include <string>
#include <utility>
#include <vector>
#include "perfetto/base/logging.h"
+#include "perfetto/base/status.h"
#include "perfetto/public/compiler.h"
#include "perfetto/trace_processor/basic_types.h"
#include "perfetto/trace_processor/ref_counted.h"
@@ -140,84 +142,6 @@
return {string_pool_, row_count_, std::move(cols), {}};
}
-RowMap Table::TryApplyIndex(const std::vector<Constraint>& c_vec,
- uint32_t& cs_offset) const {
- RowMap rm(0, row_count());
-
- // Prework - use indexes if possible and decide which one.
- std::vector<uint32_t> maybe_idx_cols;
- for (const auto& c : c_vec) {
- // Id columns shouldn't use index.
- if (columns()[c.col_idx].IsId()) {
- break;
- }
- // The operation has to support sorting.
- if (!IsSortingOp(c.op)) {
- break;
- }
- maybe_idx_cols.push_back(c.col_idx);
-
- // For the next col to be able to use index, all previous constraints have
- // to be equality.
- if (c.op != FilterOp::kEq) {
- break;
- }
- }
-
- OrderedIndices o_idxs;
- while (!maybe_idx_cols.empty()) {
- if (auto maybe_idx = GetIndex(maybe_idx_cols)) {
- o_idxs = *maybe_idx;
- break;
- }
- maybe_idx_cols.pop_back();
- }
-
- // If we can't use the index just apply constraints in a standard way.
- if (maybe_idx_cols.empty()) {
- return rm;
- }
-
- for (uint32_t i = 0; i < maybe_idx_cols.size(); i++) {
- const Constraint& c = c_vec[i];
- Range r =
- ChainForColumn(c.col_idx).OrderedIndexSearch(c.op, c.value, o_idxs);
- o_idxs.data += r.start;
- o_idxs.size = r.size();
- }
- cs_offset = static_cast<uint32_t>(maybe_idx_cols.size());
-
- std::vector<uint32_t> res_vec(o_idxs.data, o_idxs.data + o_idxs.size);
- if (res_vec.size() < kIndexVectorThreshold) {
- std::sort(res_vec.begin(), res_vec.end());
- return RowMap(std::move(res_vec));
- }
- return RowMap(BitVector::FromUnsortedIndexVector(res_vec));
-}
-
-RowMap Table::ApplyIdJoinConstraints(const std::vector<Constraint>& cs,
- uint32_t& cs_offset) const {
- uint32_t i = 1;
- uint32_t row = static_cast<uint32_t>(cs.front().value.AsLong());
- if (row >= row_count()) {
- return RowMap();
- }
- for (; i < cs.size(); i++) {
- const Constraint& c = cs[i];
- switch (ChainForColumn(c.col_idx).SingleSearch(c.op, c.value, row)) {
- case SingleSearchResult::kNoMatch:
- return RowMap();
- case SingleSearchResult::kMatch:
- continue;
- case SingleSearchResult::kNeedsFullSearch:
- cs_offset = i;
- return RowMap(row, row + 1);
- }
- }
- cs_offset = static_cast<uint32_t>(cs.size());
- return RowMap(row, row + 1);
-}
-
RowMap Table::QueryToRowMap(const Query& q) const {
// We need to delay creation of the chains to this point because of Chrome
// does not want the binary size overhead of including the chain
@@ -361,6 +285,41 @@
}
}
+base::Status Table::CreateIndex(const std::string& name,
+ std::vector<uint32_t> col_idxs,
+ bool replace) {
+ Query q;
+ for (const auto& c : col_idxs) {
+ q.orders.push_back({c});
+ }
+ std::vector<uint32_t> index = QueryToRowMap(q).TakeAsIndexVector();
+
+ auto it = std::find_if(
+ indexes_.begin(), indexes_.end(),
+ [&name](const ColumnIndex& idx) { return idx.name == name; });
+ if (it == indexes_.end()) {
+ indexes_.push_back({name, std::move(col_idxs), std::move(index)});
+ return base::OkStatus();
+ }
+ if (replace) {
+ it->columns = std::move(col_idxs);
+ it->index = std::move(index);
+ return base::OkStatus();
+ }
+ return base::ErrStatus("Index of this name already exists on this table.");
+}
+
+base::Status Table::DropIndex(const std::string& name) {
+ auto it = std::find_if(
+ indexes_.begin(), indexes_.end(),
+ [&name](const ColumnIndex& idx) { return idx.name == name; });
+ if (it == indexes_.end()) {
+ return base::ErrStatus("Index '%s' not found.", name.c_str());
+ }
+ indexes_.erase(it);
+ return base::OkStatus();
+}
+
void Table::ApplyDistinct(const Query& q, RowMap* rm) const {
const auto& ob = q.orders;
PERFETTO_DCHECK(!ob.empty());
@@ -415,4 +374,82 @@
*rm = RowMap(std::move(idx));
}
+RowMap Table::TryApplyIndex(const std::vector<Constraint>& c_vec,
+ uint32_t& cs_offset) const {
+ RowMap rm(0, row_count());
+
+ // Prework - use indexes if possible and decide which one.
+ std::vector<uint32_t> maybe_idx_cols;
+ for (const auto& c : c_vec) {
+ // Id columns shouldn't use index.
+ if (columns()[c.col_idx].IsId()) {
+ break;
+ }
+ // The operation has to support sorting.
+ if (!IsSortingOp(c.op)) {
+ break;
+ }
+ maybe_idx_cols.push_back(c.col_idx);
+
+ // For the next col to be able to use index, all previous constraints have
+ // to be equality.
+ if (c.op != FilterOp::kEq) {
+ break;
+ }
+ }
+
+ OrderedIndices o_idxs;
+ while (!maybe_idx_cols.empty()) {
+ if (auto maybe_idx = GetIndex(maybe_idx_cols)) {
+ o_idxs = *maybe_idx;
+ break;
+ }
+ maybe_idx_cols.pop_back();
+ }
+
+ // If we can't use the index just apply constraints in a standard way.
+ if (maybe_idx_cols.empty()) {
+ return rm;
+ }
+
+ for (uint32_t i = 0; i < maybe_idx_cols.size(); i++) {
+ const Constraint& c = c_vec[i];
+ Range r =
+ ChainForColumn(c.col_idx).OrderedIndexSearch(c.op, c.value, o_idxs);
+ o_idxs.data += r.start;
+ o_idxs.size = r.size();
+ }
+ cs_offset = static_cast<uint32_t>(maybe_idx_cols.size());
+
+ std::vector<uint32_t> res_vec(o_idxs.data, o_idxs.data + o_idxs.size);
+ if (res_vec.size() < kIndexVectorThreshold) {
+ std::sort(res_vec.begin(), res_vec.end());
+ return RowMap(std::move(res_vec));
+ }
+ return RowMap(BitVector::FromUnsortedIndexVector(res_vec));
+}
+
+RowMap Table::ApplyIdJoinConstraints(const std::vector<Constraint>& cs,
+ uint32_t& cs_offset) const {
+ uint32_t i = 1;
+ uint32_t row = static_cast<uint32_t>(cs.front().value.AsLong());
+ if (row >= row_count()) {
+ return RowMap();
+ }
+ for (; i < cs.size(); i++) {
+ const Constraint& c = cs[i];
+ switch (ChainForColumn(c.col_idx).SingleSearch(c.op, c.value, row)) {
+ case SingleSearchResult::kNoMatch:
+ return RowMap();
+ case SingleSearchResult::kMatch:
+ continue;
+ case SingleSearchResult::kNeedsFullSearch:
+ cs_offset = i;
+ return RowMap(row, row + 1);
+ }
+ }
+ cs_offset = static_cast<uint32_t>(cs.size());
+ return RowMap(row, row + 1);
+}
+
} // namespace perfetto::trace_processor
diff --git a/src/trace_processor/db/table.h b/src/trace_processor/db/table.h
index 44ec7d7..1b6e848 100644
--- a/src/trace_processor/db/table.h
+++ b/src/trace_processor/db/table.h
@@ -141,17 +141,18 @@
Table(Table&& other) noexcept { *this = std::move(other); }
Table& operator=(Table&& other) noexcept;
- // Return a chain corresponding to a given column.
- const column::DataLayerChain& ChainForColumn(uint32_t col_idx) const {
- return *chains_[col_idx];
- }
-
// Filters and sorts the tables with the arguments specified, returning the
// result as a RowMap.
RowMap QueryToRowMap(const Query&) const;
// Applies the RowMap |rm| onto this table and returns an iterator over the
// resulting rows.
+ Iterator QueryToIterator(const Query& q) const {
+ return ApplyAndIterateRows(QueryToRowMap(q));
+ }
+
+ // Do not add any further uses.
+ // TODO(lalitm): make this private.
Iterator ApplyAndIterateRows(RowMap rm) const {
return Iterator(this, std::move(rm));
}
@@ -171,37 +172,13 @@
// Adds an index onto column.
// Returns an error if index already exists and `!replace`.
- base::Status SetIndex(const std::string& name,
- std::vector<uint32_t> col_idxs,
- std::vector<uint32_t> index,
- bool replace = false) {
- auto it = std::find_if(
- indexes_.begin(), indexes_.end(),
- [&name](const ColumnIndex& idx) { return idx.name == name; });
- if (it == indexes_.end()) {
- indexes_.push_back({name, std::move(col_idxs), std::move(index)});
- return base::OkStatus();
- }
- if (replace) {
- it->columns = std::move(col_idxs);
- it->index = std::move(index);
- return base::OkStatus();
- }
- return base::ErrStatus("Index of this name already exists on this table.");
- }
+ base::Status CreateIndex(const std::string& name,
+ std::vector<uint32_t> col_idxs,
+ bool replace);
// Removes index from the table.
// Returns an error if index doesn't exist.
- base::Status DropIndex(const std::string& name) {
- auto it = std::find_if(
- indexes_.begin(), indexes_.end(),
- [&name](const ColumnIndex& idx) { return idx.name == name; });
- if (it == indexes_.end()) {
- return base::ErrStatus("Index '%s' not found.", name.c_str());
- }
- indexes_.erase(it);
- return base::OkStatus();
- }
+ base::Status DropIndex(const std::string& name);
// Sorts the table using the specified order by constraints.
Table Sort(const std::vector<Order>&) const;
@@ -224,8 +201,9 @@
}
uint32_t row_count() const { return row_count_; }
- StringPool* string_pool() const { return string_pool_; }
const std::vector<ColumnLegacy>& columns() const { return columns_; }
+ StringPool* string_pool() const { return string_pool_; }
+
const std::vector<RefPtr<column::StorageLayer>>& storage_layers() const {
return storage_layers_;
}
@@ -233,8 +211,6 @@
return null_layers_;
}
- bool HasNullOrOverlayLayer(uint32_t col_idx) const;
-
protected:
Table(StringPool*,
uint32_t row_count,
@@ -271,6 +247,7 @@
private:
friend class ColumnLegacy;
+ friend class QueryExecutor;
struct ColumnIndex {
std::string name;
@@ -278,6 +255,8 @@
std::vector<uint32_t> index;
};
+ bool HasNullOrOverlayLayer(uint32_t col_idx) const;
+
void CreateChains() const;
Table CopyExceptOverlays() const;
@@ -290,6 +269,10 @@
RowMap ApplyIdJoinConstraints(const std::vector<Constraint>&,
uint32_t& cs_offset) const;
+ const column::DataLayerChain& ChainForColumn(uint32_t col_idx) const {
+ return *chains_[col_idx];
+ }
+
StringPool* string_pool_ = nullptr;
uint32_t row_count_ = 0;
std::vector<ColumnStorageOverlay> overlays_;
diff --git a/src/trace_processor/db/typed_column.h b/src/trace_processor/db/typed_column.h
index 1f6c280..dd5bd13 100644
--- a/src/trace_processor/db/typed_column.h
+++ b/src/trace_processor/db/typed_column.h
@@ -17,11 +17,20 @@
#ifndef SRC_TRACE_PROCESSOR_DB_TYPED_COLUMN_H_
#define SRC_TRACE_PROCESSOR_DB_TYPED_COLUMN_H_
+#include <cstdint>
+#include <optional>
+#include <type_traits>
+#include <vector>
+
+#include "perfetto/base/logging.h"
+#include "perfetto/trace_processor/basic_types.h"
+#include "src/trace_processor/containers/null_term_string_view.h"
#include "src/trace_processor/db/column.h"
+#include "src/trace_processor/db/column/types.h"
+#include "src/trace_processor/db/column_storage.h"
#include "src/trace_processor/db/typed_column_internal.h"
-namespace perfetto {
-namespace trace_processor {
+namespace perfetto::trace_processor {
// TypedColumn<T>
//
@@ -81,22 +90,18 @@
template <bool is_string = TH::is_string>
typename std::enable_if<is_string, NullTermStringView>::type GetString(
uint32_t row) const {
- return GetStringAtIdx(overlay().Get(row));
+ return string_pool().Get(storage().Get((overlay().Get(row))));
}
// Sets the data in the column at index |row|.
void Set(uint32_t row, non_optional_type v) {
- SetAtIdx(overlay().Get(row), v);
+ auto serialized = Serializer::Serialize(v);
+ mutable_storage()->Set(overlay().Get(row), serialized);
}
// Inserts the value at the end of the column.
void Append(T v) { mutable_storage()->Append(Serializer::Serialize(v)); }
- // Returns the row containing the given value in the Column.
- std::optional<uint32_t> IndexOf(sql_value_type v) const {
- return ColumnLegacy::IndexOf(ToSqlValue(v));
- }
-
std::vector<T> ToVectorForTesting() const {
std::vector<T> result(overlay().size());
for (uint32_t i = 0; i < overlay().size(); ++i)
@@ -131,36 +136,6 @@
// Cast a Column to TypedColumn or crash if that is unsafe.
static TypedColumn<T>* FromColumn(ColumnLegacy* column) {
- return FromColumnInternal<TypedColumn<T>>(column);
- }
-
- // Cast a Column to TypedColumn or crash if that is unsafe.
- static const TypedColumn<T>* FromColumn(const ColumnLegacy* column) {
- return FromColumnInternal<const TypedColumn<T>>(column);
- }
-
- // Public for use by macro tables.
- void SetAtIdx(uint32_t idx, non_optional_type v) {
- auto serialized = Serializer::Serialize(v);
- mutable_storage()->Set(idx, serialized);
- }
-
- // Public for use by macro tables.
- T GetAtIdx(uint32_t idx) const {
- return Serializer::Deserialize(TH::Get(storage(), idx));
- }
-
- template <bool is_string = TH::is_string>
- typename std::enable_if<is_string, NullTermStringView>::type GetStringAtIdx(
- uint32_t idx) const {
- return string_pool().Get(storage().Get(idx));
- }
-
- private:
- friend class Table;
-
- template <typename Output, typename Input>
- static Output* FromColumnInternal(Input* column) {
// While casting from a base to derived without constructing as a derived is
// technically UB, in practice, this is at the heart of protozero (see
// Message::BeginNestedMessage) so we use it here.
@@ -169,13 +144,21 @@
if (column->template IsColumnType<stored_type>() &&
(column->IsNullable() == TH::is_optional) && !column->IsId()) {
- return static_cast<Output*>(column);
+ return static_cast<TypedColumn<T>*>(column);
} else {
PERFETTO_FATAL("Unsafe to convert Column TypedColumn (%s)",
column->name());
}
}
+ // Public for use by macro tables.
+ T GetAtIdx(uint32_t idx) const {
+ return Serializer::Deserialize(TH::Get(storage(), idx));
+ }
+
+ private:
+ friend class Table;
+
const ColumnStorage<stored_type>& storage() const {
return ColumnLegacy::storage<stored_type>();
}
@@ -203,23 +186,6 @@
// Public for use by macro tables.
Id GetAtIdx(uint32_t idx) const { return Id(idx); }
- // Static cast a Column to IdColumn or crash if that is likely to be
- // unsafe.
- static const IdColumn<Id>* FromColumn(const ColumnLegacy* column) {
- // While casting from a base to derived without constructing as a derived is
- // technically UB, in practice, this is at the heart of protozero (see
- // Message::BeginNestedMessage) so we use it here.
- static_assert(sizeof(IdColumn<Id>) == sizeof(ColumnLegacy),
- "TypedColumn cannot introduce extra state.");
-
- if (column->IsId()) {
- return static_cast<const IdColumn<Id>*>(column);
- } else {
- PERFETTO_FATAL("Unsafe to convert Column to IdColumn (%s)",
- column->name());
- }
- }
-
// Helper functions to create constraints for the given value.
Constraint eq(uint32_t v) const { return eq_value(SqlValue::Long(v)); }
Constraint gt(uint32_t v) const { return gt_value(SqlValue::Long(v)); }
@@ -232,7 +198,6 @@
friend class Table;
};
-} // namespace trace_processor
-} // namespace perfetto
+} // namespace perfetto::trace_processor
#endif // SRC_TRACE_PROCESSOR_DB_TYPED_COLUMN_H_
diff --git a/src/trace_processor/export_json.cc b/src/trace_processor/export_json.cc
index 3cd3a5d..f0a0479 100644
--- a/src/trace_processor/export_json.cc
+++ b/src/trace_processor/export_json.cc
@@ -15,50 +15,65 @@
*/
#include "perfetto/ext/trace_processor/export_json.h"
-#include "src/trace_processor/export_json.h"
-
-#include <stdio.h>
-#include <sstream>
#include <algorithm>
-#include <cinttypes>
#include <cmath>
+#include <cstdint>
+#include <cstdio>
#include <cstring>
#include <deque>
#include <limits>
+#include <map>
#include <memory>
+#include <optional>
+#include <sstream>
+#include <string>
+#include <tuple>
+#include <unordered_map>
+#include <utility>
+#include <vector>
#include "perfetto/base/build_config.h"
+#include "perfetto/base/logging.h"
+#include "perfetto/base/status.h"
#include "perfetto/ext/base/string_splitter.h"
#include "perfetto/ext/base/string_utils.h"
-#include "src/trace_processor/importers/json/json_utils.h"
+#include "perfetto/public/compiler.h"
+#include "perfetto/trace_processor/basic_types.h"
+#include "src/trace_processor/containers/null_term_string_view.h"
+#include "src/trace_processor/export_json.h"
#include "src/trace_processor/storage/metadata.h"
+#include "src/trace_processor/storage/stats.h"
#include "src/trace_processor/storage/trace_storage.h"
+#include "src/trace_processor/tables/metadata_tables_py.h"
+#include "src/trace_processor/tables/profiler_tables_py.h"
#include "src/trace_processor/trace_processor_storage_impl.h"
#include "src/trace_processor/types/trace_processor_context.h"
+#include "src/trace_processor/types/variadic.h"
+#include "src/trace_processor/util/status_macros.h"
#if PERFETTO_BUILDFLAG(PERFETTO_TP_JSON)
+#include <json/config.h>
#include <json/reader.h>
+#include <json/value.h>
#include <json/writer.h>
#endif
-namespace perfetto {
-namespace trace_processor {
-namespace json {
+namespace perfetto::trace_processor::json {
namespace {
class FileWriter : public OutputWriter {
public:
- FileWriter(FILE* file) : file_(file) {}
+ explicit FileWriter(FILE* file) : file_(file) {}
~FileWriter() override { fflush(file_); }
- util::Status AppendString(const std::string& s) override {
+ base::Status AppendString(const std::string& s) override {
size_t written =
fwrite(s.data(), sizeof(std::string::value_type), s.size(), file_);
if (written != s.size())
- return util::ErrStatus("Error writing to file: %d", ferror(file_));
- return util::OkStatus();
+ return base::ErrStatus("Error writing to file: %d", ferror(file_));
+ return base::OkStatus();
}
private:
@@ -101,54 +116,24 @@
LabelFilterPredicate label_filter)
: storage_(storage),
args_builder_(storage_),
- writer_(output, argument_filter, metadata_filter, label_filter) {}
+ writer_(output,
+ std::move(argument_filter),
+ std::move(metadata_filter),
+ std::move(label_filter)) {}
- util::Status Export() {
- util::Status status = MapUniquePidsAndTids();
- if (!status.ok())
- return status;
-
- status = ExportThreadNames();
- if (!status.ok())
- return status;
-
- status = ExportProcessNames();
- if (!status.ok())
- return status;
-
- status = ExportProcessUptimes();
- if (!status.ok())
- return status;
-
- status = ExportSlices();
- if (!status.ok())
- return status;
-
- status = ExportFlows();
- if (!status.ok())
- return status;
-
- status = ExportRawEvents();
- if (!status.ok())
- return status;
-
- status = ExportCpuProfileSamples();
- if (!status.ok())
- return status;
-
- status = ExportMetadata();
- if (!status.ok())
- return status;
-
- status = ExportStats();
- if (!status.ok())
- return status;
-
- status = ExportMemorySnapshots();
- if (!status.ok())
- return status;
-
- return util::OkStatus();
+ base::Status Export() {
+ RETURN_IF_ERROR(MapUniquePidsAndTids());
+ RETURN_IF_ERROR(ExportThreadNames());
+ RETURN_IF_ERROR(ExportProcessNames());
+ RETURN_IF_ERROR(ExportProcessUptimes());
+ RETURN_IF_ERROR(ExportSlices());
+ RETURN_IF_ERROR(ExportFlows());
+ RETURN_IF_ERROR(ExportRawEvents());
+ RETURN_IF_ERROR(ExportCpuProfileSamples());
+ RETURN_IF_ERROR(ExportMetadata());
+ RETURN_IF_ERROR(ExportStats());
+ RETURN_IF_ERROR(ExportMemorySnapshots());
+ return base::OkStatus();
}
private:
@@ -159,9 +144,9 @@
MetadataFilterPredicate metadata_filter,
LabelFilterPredicate label_filter)
: output_(output),
- argument_filter_(argument_filter),
- metadata_filter_(metadata_filter),
- label_filter_(label_filter),
+ argument_filter_(std::move(argument_filter)),
+ metadata_filter_(std::move(metadata_filter)),
+ label_filter_(std::move(label_filter)),
first_event_(true) {
Json::StreamWriterBuilder b;
b.settings_["indentation"] = "";
@@ -520,12 +505,12 @@
args_sets_.resize(1, empty_value_);
return;
}
- args_sets_.resize(arg_table.arg_set_id()[count - 1] + 1, empty_value_);
+ args_sets_.resize(arg_table[count - 1].arg_set_id() + 1, empty_value_);
- for (uint32_t i = 0; i < count; ++i) {
- ArgSetId set_id = arg_table.arg_set_id()[i];
- const char* key = arg_table.key().GetString(i).c_str();
- Variadic value = storage_->GetArgValue(i);
+ for (auto it = arg_table.IterateRows(); it; ++it) {
+ ArgSetId set_id = it.arg_set_id();
+ const char* key = storage->GetString(it.key()).c_str();
+ Variadic value = storage_->GetArgValue(it.row_number().row_number());
AppendArg(set_id, key, VariadicToJson(value));
}
PostprocessArgs();
@@ -591,11 +576,11 @@
}
std::string key_part = parts.cur_token();
size_t bracketpos = key_part.find('[');
- if (bracketpos == key_part.npos) { // A single item
+ if (bracketpos == std::string::npos) { // A single item
target = &(*target)[key_part];
} else { // A list item
target = &(*target)[key_part.substr(0, bracketpos)];
- while (bracketpos != key_part.npos) {
+ while (bracketpos != std::string::npos) {
// We constructed this string from an int earlier in trace_processor
// so it shouldn't be possible for this (or the StringToUInt32
// below) to fail.
@@ -667,10 +652,11 @@
const Json::Value neg_inf_value_;
};
- util::Status MapUniquePidsAndTids() {
+ base::Status MapUniquePidsAndTids() {
const auto& process_table = storage_->process_table();
- for (UniquePid upid = 0; upid < process_table.row_count(); upid++) {
- uint32_t exported_pid = process_table.pid()[upid];
+ for (auto it = process_table.IterateRows(); it; ++it) {
+ UniquePid upid = it.id().value;
+ uint32_t exported_pid = it.pid();
auto it_and_inserted =
exported_pids_to_upids_.emplace(exported_pid, upid);
if (!it_and_inserted.second) {
@@ -681,16 +667,18 @@
}
const auto& thread_table = storage_->thread_table();
- for (UniqueTid utid = 0; utid < thread_table.row_count(); utid++) {
+ for (auto it = thread_table.IterateRows(); it; ++it) {
+ UniqueTid utid = it.id().value;
+
uint32_t exported_pid = 0;
- std::optional<UniquePid> upid = thread_table.upid()[utid];
+ std::optional<UniquePid> upid = it.upid();
if (upid) {
auto exported_pid_it = upids_to_exported_pids_.find(*upid);
PERFETTO_DCHECK(exported_pid_it != upids_to_exported_pids_.end());
exported_pid = exported_pid_it->second;
}
- uint32_t exported_tid = thread_table.tid()[utid];
+ uint32_t exported_tid = it.tid();
auto it_and_inserted = exported_pids_and_tids_to_utids_.emplace(
std::make_pair(exported_pid, exported_tid), utid);
if (!it_and_inserted.second) {
@@ -701,81 +689,76 @@
utids_to_exported_pids_and_tids_.emplace(
utid, std::make_pair(exported_pid, exported_tid));
}
-
- return util::OkStatus();
+ return base::OkStatus();
}
- util::Status ExportThreadNames() {
+ base::Status ExportThreadNames() {
const auto& thread_table = storage_->thread_table();
- for (UniqueTid utid = 0; utid < thread_table.row_count(); ++utid) {
- auto opt_name = thread_table.name()[utid];
+ for (auto it = thread_table.IterateRows(); it; ++it) {
+ auto opt_name = it.name();
if (opt_name.has_value()) {
+ UniqueTid utid = it.id().value;
const char* thread_name = GetNonNullString(storage_, opt_name);
auto pid_and_tid = UtidToPidAndTid(utid);
writer_.WriteMetadataEvent("thread_name", "name", thread_name,
pid_and_tid.first, pid_and_tid.second);
}
}
- return util::OkStatus();
+ return base::OkStatus();
}
- util::Status ExportProcessNames() {
+ base::Status ExportProcessNames() {
const auto& process_table = storage_->process_table();
- for (UniquePid upid = 0; upid < process_table.row_count(); ++upid) {
- auto opt_name = process_table.name()[upid];
+ for (auto it = process_table.IterateRows(); it; ++it) {
+ auto opt_name = it.name();
if (opt_name.has_value()) {
+ UniquePid upid = it.id().value;
const char* process_name = GetNonNullString(storage_, opt_name);
writer_.WriteMetadataEvent("process_name", "name", process_name,
UpidToPid(upid), /*tid=*/0);
}
}
- return util::OkStatus();
+ return base::OkStatus();
}
// For each process it writes an approximate uptime, based on the process'
// start time and the last slice in the entire trace. This same last slice is
// used with all processes, so the process could have ended earlier.
- util::Status ExportProcessUptimes() {
+ base::Status ExportProcessUptimes() {
int64_t last_timestamp_ns = FindLastSliceTimestamp();
if (last_timestamp_ns <= 0)
- return util::OkStatus();
+ return base::OkStatus();
const auto& process_table = storage_->process_table();
- for (UniquePid upid = 0; upid < process_table.row_count(); ++upid) {
- std::optional<int64_t> start_timestamp_ns =
- process_table.start_ts()[upid];
- if (!start_timestamp_ns.has_value())
+ for (auto it = process_table.IterateRows(); it; ++it) {
+ std::optional<int64_t> start_timestamp_ns = it.start_ts();
+ if (!start_timestamp_ns.has_value()) {
continue;
+ }
+ UniquePid upid = it.id().value;
int64_t process_uptime_seconds =
(last_timestamp_ns - start_timestamp_ns.value()) /
- (1000 * 1000 * 1000);
-
+ (1000l * 1000 * 1000);
writer_.WriteMetadataEvent("process_uptime_seconds", "uptime",
std::to_string(process_uptime_seconds).c_str(),
UpidToPid(upid), /*tid=*/0);
}
- return util::OkStatus();
+ return base::OkStatus();
}
// Returns the last slice's end timestamp for the entire trace. If no slices
// are found 0 is returned.
int64_t FindLastSliceTimestamp() {
int64_t last_ts = 0;
- const auto& slices = storage_->slice_table();
- for (uint32_t i = 0; i < slices.row_count(); ++i) {
- int64_t duration_ns = slices.dur()[i];
- int64_t timestamp_ns = slices.ts()[i];
-
- if (duration_ns + timestamp_ns > last_ts) {
- last_ts = duration_ns + timestamp_ns;
- }
+ for (auto it = storage_->slice_table().IterateRows(); it; ++it) {
+ last_ts = std::max(last_ts, it.ts() + it.dur());
}
return last_ts;
}
- util::Status ExportSlices() {
+ base::Status ExportSlices() {
const auto& slices = storage_->slice_table();
for (auto it = slices.IterateRows(); it; ++it) {
// Skip slices with empty category - these are ftrace/system slices that
@@ -865,11 +848,10 @@
}
}
- auto opt_thread_track_row = thread_track.id().IndexOf(TrackId{track_id});
-
- if (opt_thread_track_row && !is_child_track) {
+ auto tt_rr = thread_track.FindById(track_id);
+ if (tt_rr && !is_child_track) {
// Synchronous (thread) slice or instant event.
- UniqueTid utid = thread_track.utid()[*opt_thread_track_row];
+ UniqueTid utid = tt_rr->utid();
auto pid_and_tid = UtidToPidAndTid(utid);
event["pid"] = Json::Int(pid_and_tid.first);
event["tid"] = Json::Int(pid_and_tid.second);
@@ -915,12 +897,12 @@
} else if (is_child_track ||
(legacy_chrome_track && track_args->isMember("trace_id"))) {
// Async event slice.
- auto opt_process_row = process_track.id().IndexOf(TrackId{track_id});
+ auto pt_rr = process_track.FindById(track_id);
if (legacy_chrome_track) {
// Legacy async tracks are always process-associated and have args.
- PERFETTO_DCHECK(opt_process_row);
+ PERFETTO_DCHECK(pt_rr);
PERFETTO_DCHECK(track_args);
- uint32_t upid = process_track.upid()[*opt_process_row];
+ UniquePid upid = pt_rr->upid();
uint32_t exported_pid = UpidToPid(upid);
event["pid"] = Json::Int(exported_pid);
event["tid"] =
@@ -949,14 +931,14 @@
event["id"] = base::Uint64ToHexString(trace_id);
}
} else {
- if (opt_thread_track_row) {
- UniqueTid utid = thread_track.utid()[*opt_thread_track_row];
+ if (tt_rr) {
+ UniqueTid utid = tt_rr->utid();
auto pid_and_tid = UtidToPidAndTid(utid);
event["pid"] = Json::Int(pid_and_tid.first);
event["tid"] = Json::Int(pid_and_tid.second);
event["id2"]["local"] = base::Uint64ToHexString(track_id.value);
- } else if (opt_process_row) {
- uint32_t upid = process_track.upid()[*opt_process_row];
+ } else if (pt_rr) {
+ uint32_t upid = pt_rr->upid();
uint32_t exported_pid = UpidToPid(upid);
event["pid"] = Json::Int(exported_pid);
event["tid"] =
@@ -1035,9 +1017,9 @@
event["ph"] = legacy_phase;
}
- auto opt_process_row = process_track.id().IndexOf(TrackId{track_id});
- if (opt_process_row.has_value()) {
- uint32_t upid = process_track.upid()[*opt_process_row];
+ auto pt_rr = process_track.FindById(track_id);
+ if (pt_rr.has_value()) {
+ UniquePid upid = pt_rr->upid();
uint32_t exported_pid = UpidToPid(upid);
event["pid"] = Json::Int(exported_pid);
event["tid"] =
@@ -1051,31 +1033,30 @@
}
}
}
- return util::OkStatus();
+ return base::OkStatus();
}
std::optional<Json::Value> CreateFlowEventV1(uint32_t flow_id,
SliceId slice_id,
- std::string name,
- std::string cat,
+ const std::string& name,
+ const std::string& cat,
Json::Value args,
bool flow_begin) {
const auto& slices = storage_->slice_table();
const auto& thread_tracks = storage_->thread_track_table();
- auto opt_slice_idx = slices.id().IndexOf(slice_id);
- if (!opt_slice_idx)
+ auto opt_slice_rr = slices.FindById(slice_id);
+ if (!opt_slice_rr)
return std::nullopt;
- uint32_t slice_idx = opt_slice_idx.value();
+ auto slice_rr = opt_slice_rr.value();
- TrackId track_id = storage_->slice_table().track_id()[slice_idx];
- auto opt_thread_track_idx = thread_tracks.id().IndexOf(track_id);
+ TrackId track_id = slice_rr.track_id();
+ auto opt_ttrr = thread_tracks.FindById(track_id);
// catapult only supports flow events attached to thread-track slices
- if (!opt_thread_track_idx)
+ if (!opt_ttrr)
return std::nullopt;
- UniqueTid utid = thread_tracks.utid()[opt_thread_track_idx.value()];
- auto pid_and_tid = UtidToPidAndTid(utid);
+ auto pid_and_tid = UtidToPidAndTid(opt_ttrr->utid());
Json::Value event;
event["id"] = flow_id;
event["pid"] = Json::Int(pid_and_tid.first);
@@ -1083,7 +1064,7 @@
event["cat"] = cat;
event["name"] = name;
event["ph"] = (flow_begin ? "s" : "f");
- event["ts"] = Json::Int64(slices.ts()[slice_idx] / 1000);
+ event["ts"] = Json::Int64(slice_rr.ts() / 1000);
if (!flow_begin) {
event["bp"] = "e";
}
@@ -1091,13 +1072,13 @@
return std::move(event);
}
- util::Status ExportFlows() {
+ base::Status ExportFlows() {
const auto& flow_table = storage_->flow_table();
const auto& slice_table = storage_->slice_table();
- for (uint32_t i = 0; i < flow_table.row_count(); i++) {
- SliceId slice_out = flow_table.slice_out()[i];
- SliceId slice_in = flow_table.slice_in()[i];
- uint32_t arg_set_id = flow_table.arg_set_id()[i];
+ for (auto it = flow_table.IterateRows(); it; ++it) {
+ SliceId slice_out = it.slice_out();
+ SliceId slice_in = it.slice_in();
+ uint32_t arg_set_id = it.arg_set_id();
std::string cat;
std::string name;
@@ -1110,16 +1091,13 @@
args.removeMember("name");
args.removeMember("cat");
} else {
- auto opt_slice_out_idx = slice_table.id().IndexOf(slice_out);
- PERFETTO_DCHECK(opt_slice_out_idx.has_value());
- std::optional<StringId> cat_id =
- slice_table.category()[opt_slice_out_idx.value()];
- std::optional<StringId> name_id =
- slice_table.name()[opt_slice_out_idx.value()];
- cat = GetNonNullString(storage_, cat_id);
- name = GetNonNullString(storage_, name_id);
+ auto rr = slice_table.FindById(slice_out);
+ PERFETTO_DCHECK(rr.has_value());
+ cat = GetNonNullString(storage_, rr->category());
+ name = GetNonNullString(storage_, rr->name());
}
+ uint32_t i = it.row_number().row_number();
auto out_event = CreateFlowEventV1(i, slice_out, name, cat, args,
/* flow_begin = */ true);
auto in_event = CreateFlowEventV1(i, slice_in, name, cat, std::move(args),
@@ -1130,23 +1108,22 @@
writer_.WriteCommonEvent(in_event.value());
}
}
- return util::OkStatus();
+ return base::OkStatus();
}
- Json::Value ConvertLegacyRawEventToJson(uint32_t index) {
- const auto& events = storage_->raw_table();
-
+ Json::Value ConvertLegacyRawEventToJson(
+ const tables::RawTable::ConstIterator& it) {
Json::Value event;
- event["ts"] = Json::Int64(events.ts()[index] / 1000);
+ event["ts"] = Json::Int64(it.ts() / 1000);
- UniqueTid utid = static_cast<UniqueTid>(events.utid()[index]);
+ UniqueTid utid = static_cast<UniqueTid>(it.utid());
auto pid_and_tid = UtidToPidAndTid(utid);
event["pid"] = Json::Int(pid_and_tid.first);
event["tid"] = Json::Int(pid_and_tid.second);
// Raw legacy events store all other params in the arg set. Make a copy of
// the converted args here, parse, and then remove the legacy params.
- event["args"] = args_builder_.GetArgs(events.arg_set_id()[index]);
+ event["args"] = args_builder_.GetArgs(it.arg_set_id());
const Json::Value& legacy_args = event["args"][kLegacyEventArgsKey];
PERFETTO_DCHECK(legacy_args.isMember(kLegacyEventCategoryKey));
@@ -1210,7 +1187,7 @@
return event;
}
- util::Status ExportRawEvents() {
+ base::Status ExportRawEvents() {
std::optional<StringId> raw_legacy_event_key_id =
storage_->string_pool().GetId("track_event.legacy_event");
std::optional<StringId> raw_legacy_system_trace_event_id =
@@ -1221,34 +1198,40 @@
storage_->string_pool().GetId("chrome_event.metadata");
const auto& events = storage_->raw_table();
- for (uint32_t i = 0; i < events.row_count(); ++i) {
- if (raw_legacy_event_key_id &&
- events.name()[i] == *raw_legacy_event_key_id) {
- Json::Value event = ConvertLegacyRawEventToJson(i);
+ for (auto it = events.IterateRows(); it; ++it) {
+ if (raw_legacy_event_key_id && it.name() == *raw_legacy_event_key_id) {
+ Json::Value event = ConvertLegacyRawEventToJson(it);
writer_.WriteCommonEvent(event);
} else if (raw_legacy_system_trace_event_id &&
- events.name()[i] == *raw_legacy_system_trace_event_id) {
- Json::Value args = args_builder_.GetArgs(events.arg_set_id()[i]);
+ it.name() == *raw_legacy_system_trace_event_id) {
+ Json::Value args = args_builder_.GetArgs(it.arg_set_id());
PERFETTO_DCHECK(args.isMember("data"));
writer_.AddSystemTraceData(args["data"].asString());
} else if (raw_legacy_user_trace_event_id &&
- events.name()[i] == *raw_legacy_user_trace_event_id) {
- Json::Value args = args_builder_.GetArgs(events.arg_set_id()[i]);
+ it.name() == *raw_legacy_user_trace_event_id) {
+ Json::Value args = args_builder_.GetArgs(it.arg_set_id());
PERFETTO_DCHECK(args.isMember("data"));
writer_.AddUserTraceData(args["data"].asString());
} else if (raw_chrome_metadata_event_id &&
- events.name()[i] == *raw_chrome_metadata_event_id) {
- Json::Value args = args_builder_.GetArgs(events.arg_set_id()[i]);
+ it.name() == *raw_chrome_metadata_event_id) {
+ Json::Value args = args_builder_.GetArgs(it.arg_set_id());
writer_.MergeMetadata(args);
}
}
- return util::OkStatus();
+ return base::OkStatus();
}
class MergedProfileSamplesEmitter {
public:
// The TraceFormatWriter must outlive this instance.
- MergedProfileSamplesEmitter(TraceFormatWriter& writer) : writer_(writer) {}
+ explicit MergedProfileSamplesEmitter(TraceFormatWriter& writer)
+ : writer_(writer) {}
+
+ MergedProfileSamplesEmitter(const MergedProfileSamplesEmitter&) = delete;
+ MergedProfileSamplesEmitter& operator=(const MergedProfileSamplesEmitter&) =
+ delete;
+ MergedProfileSamplesEmitter& operator=(
+ MergedProfileSamplesEmitter&& value) = delete;
uint64_t AddEventForUtid(UniqueTid utid,
int64_t ts,
@@ -1290,15 +1273,21 @@
Sample(TraceFormatWriter& writer,
CallsiteId callsite_id,
int64_t ts,
- const Json::Value& event)
+ Json::Value event)
: writer_(writer),
callsite_id_(callsite_id),
begin_ts_(ts),
end_ts_(ts),
- event_(event),
+ event_(std::move(event)),
event_id_(MergedProfileSamplesEmitter::GenerateNewEventId()),
sample_count_(1) {}
+ Sample(const Sample&) = delete;
+ Sample& operator=(const Sample&) = delete;
+
+ Sample(Sample&&) = delete;
+ Sample& operator=(Sample&& value) = delete;
+
~Sample() {
// No point writing a merged event if we only got a single sample
// as ExportCpuProfileSamples will already be writing the instant event.
@@ -1341,11 +1330,6 @@
uint64_t event_id() const { return event_id_; }
CallsiteId callsite_id() const { return callsite_id_; }
- public:
- Sample(const Sample&) = delete;
- Sample& operator=(const Sample&) = delete;
- Sample& operator=(Sample&& value) = delete;
-
TraceFormatWriter& writer_;
CallsiteId callsite_id_;
int64_t begin_ts_;
@@ -1355,26 +1339,20 @@
size_t sample_count_;
};
- MergedProfileSamplesEmitter(const MergedProfileSamplesEmitter&) = delete;
- MergedProfileSamplesEmitter& operator=(const MergedProfileSamplesEmitter&) =
- delete;
- MergedProfileSamplesEmitter& operator=(
- MergedProfileSamplesEmitter&& value) = delete;
-
std::unordered_map<UniqueTid, Sample> current_events_;
TraceFormatWriter& writer_;
};
- util::Status ExportCpuProfileSamples() {
+ base::Status ExportCpuProfileSamples() {
MergedProfileSamplesEmitter merged_sample_emitter(writer_);
const tables::CpuProfileStackSampleTable& samples =
storage_->cpu_profile_stack_sample_table();
- for (uint32_t i = 0; i < samples.row_count(); ++i) {
+ for (auto it = samples.IterateRows(); it; ++it) {
Json::Value event;
- event["ts"] = Json::Int64(samples.ts()[i] / 1000);
+ event["ts"] = Json::Int64(it.ts() / 1000);
- UniqueTid utid = static_cast<UniqueTid>(samples.utid()[i]);
+ UniqueTid utid = static_cast<UniqueTid>(it.utid());
auto pid_and_tid = UtidToPidAndTid(utid);
event["pid"] = Json::Int(pid_and_tid.first);
event["tid"] = Json::Int(pid_and_tid.second);
@@ -1394,38 +1372,38 @@
const auto& mappings = storage_->stack_profile_mapping_table();
std::vector<std::string> callstack;
- std::optional<CallsiteId> opt_callsite_id = samples.callsite_id()[i];
+ std::optional<CallsiteId> opt_callsite_id = it.callsite_id();
while (opt_callsite_id) {
CallsiteId callsite_id = *opt_callsite_id;
- uint32_t callsite_row = *callsites.id().IndexOf(callsite_id);
+ auto callsite_row = *callsites.FindById(callsite_id);
- FrameId frame_id = callsites.frame_id()[callsite_row];
- uint32_t frame_row = *frames.id().IndexOf(frame_id);
+ FrameId frame_id = callsite_row.frame_id();
+ auto frame_row = *frames.FindById(frame_id);
- MappingId mapping_id = frames.mapping()[frame_row];
- uint32_t mapping_row = *mappings.id().IndexOf(mapping_id);
+ MappingId mapping_id = frame_row.mapping();
+ auto mapping_row = *mappings.FindById(mapping_id);
NullTermStringView symbol_name;
- auto opt_symbol_set_id = frames.symbol_set_id()[frame_row];
+ auto opt_symbol_set_id = frame_row.symbol_set_id();
if (opt_symbol_set_id) {
symbol_name = storage_->GetString(
- storage_->symbol_table().name()[*opt_symbol_set_id]);
+ storage_->symbol_table()[*opt_symbol_set_id].name());
}
base::StackString<1024> frame_entry(
"%s - %s [%s]\n",
(symbol_name.empty()
? base::Uint64ToHexString(
- static_cast<uint64_t>(frames.rel_pc()[frame_row]))
+ static_cast<uint64_t>(frame_row.rel_pc()))
.c_str()
: symbol_name.c_str()),
- GetNonNullString(storage_, mappings.name()[mapping_row]),
- GetNonNullString(storage_, mappings.build_id()[mapping_row]));
+ GetNonNullString(storage_, mapping_row.name()),
+ GetNonNullString(storage_, mapping_row.build_id()));
callstack.emplace_back(frame_entry.ToStdString());
- opt_callsite_id = callsites.parent_id()[callsite_row];
+ opt_callsite_id = callsite_row.parent_id();
}
std::string merged_callstack;
@@ -1435,7 +1413,7 @@
}
event["args"]["frames"] = merged_callstack;
- event["args"]["process_priority"] = samples.process_priority()[i];
+ event["args"]["process_priority"] = it.process_priority();
// TODO(oysteine): Used for backwards compatibility with the memlog
// pipeline, should remove once we've switched to looking directly at the
@@ -1446,12 +1424,11 @@
// For now, only do this when the trace has already been symbolized i.e.
// are not directly output by Chrome, to avoid interfering with other
// processing pipelines.
- std::optional<CallsiteId> opt_current_callsite_id =
- samples.callsite_id()[i];
+ std::optional<CallsiteId> opt_current_callsite_id = it.callsite_id();
if (opt_current_callsite_id && storage_->symbol_table().row_count() > 0) {
uint64_t parent_event_id = merged_sample_emitter.AddEventForUtid(
- utid, samples.ts()[i], *opt_current_callsite_id, event);
+ utid, it.ts(), *opt_current_callsite_id, event);
event["id"] = base::Uint64ToHexString(parent_event_id);
} else {
event["id"] = base::Uint64ToHexString(
@@ -1461,14 +1438,11 @@
writer_.WriteCommonEvent(event);
}
- return util::OkStatus();
+ return base::OkStatus();
}
- util::Status ExportMetadata() {
+ base::Status ExportMetadata() {
const auto& trace_metadata = storage_->metadata_table();
- const auto& keys = trace_metadata.name();
- const auto& int_values = trace_metadata.int_value();
- const auto& str_values = trace_metadata.str_value();
// Create a mapping from key string ids to keys.
std::unordered_map<StringId, metadata::KeyId> key_map;
@@ -1477,8 +1451,8 @@
key_map[id] = static_cast<metadata::KeyId>(i);
}
- for (uint32_t pos = 0; pos < trace_metadata.row_count(); pos++) {
- auto key_it = key_map.find(keys[pos]);
+ for (auto it = trace_metadata.IterateRows(); it; ++it) {
+ auto key_it = key_map.find(it.name());
// Skip exporting dynamic entries; the cr-xxx entries that come from
// the ChromeMetadata proto message are already exported from the raw
// table.
@@ -1491,45 +1465,48 @@
switch (static_cast<size_t>(key)) {
case metadata::benchmark_description:
writer_.AppendTelemetryMetadataString(
- "benchmarkDescriptions", str_values.GetString(pos).c_str());
+ "benchmarkDescriptions",
+ storage_->string_pool().Get(*it.str_value()).c_str());
break;
case metadata::benchmark_name:
writer_.AppendTelemetryMetadataString(
- "benchmarks", str_values.GetString(pos).c_str());
+ "benchmarks",
+ storage_->string_pool().Get(*it.str_value()).c_str());
break;
case metadata::benchmark_start_time_us:
writer_.SetTelemetryMetadataTimestamp("benchmarkStart",
- *int_values[pos]);
+ *it.int_value());
break;
case metadata::benchmark_had_failures:
- writer_.AppendTelemetryMetadataBool("hadFailures", *int_values[pos]);
+ writer_.AppendTelemetryMetadataBool("hadFailures", *it.int_value());
break;
case metadata::benchmark_label:
writer_.AppendTelemetryMetadataString(
- "labels", str_values.GetString(pos).c_str());
+ "labels", storage_->string_pool().Get(*it.str_value()).c_str());
break;
case metadata::benchmark_story_name:
writer_.AppendTelemetryMetadataString(
- "stories", str_values.GetString(pos).c_str());
+ "stories", storage_->string_pool().Get(*it.str_value()).c_str());
break;
case metadata::benchmark_story_run_index:
writer_.AppendTelemetryMetadataInt("storysetRepeats",
- *int_values[pos]);
+ *it.int_value());
break;
case metadata::benchmark_story_run_time_us:
- writer_.SetTelemetryMetadataTimestamp("traceStart", *int_values[pos]);
+ writer_.SetTelemetryMetadataTimestamp("traceStart", *it.int_value());
break;
case metadata::benchmark_story_tags: // repeated
writer_.AppendTelemetryMetadataString(
- "storyTags", str_values.GetString(pos).c_str());
+ "storyTags",
+ storage_->string_pool().Get(*it.str_value()).c_str());
break;
default:
@@ -1537,10 +1514,10 @@
break;
}
}
- return util::OkStatus();
+ return base::OkStatus();
}
- util::Status ExportStats() {
+ base::Status ExportStats() {
const auto& stats = storage_->stats();
for (size_t idx = 0; idx < stats::kNumKeys; idx++) {
@@ -1552,59 +1529,54 @@
}
}
- return util::OkStatus();
+ return base::OkStatus();
}
- util::Status ExportMemorySnapshots() {
+ base::Status ExportMemorySnapshots() {
const auto& memory_snapshots = storage_->memory_snapshot_table();
std::optional<StringId> private_footprint_id =
storage_->string_pool().GetId("chrome.private_footprint_kb");
std::optional<StringId> peak_resident_set_id =
storage_->string_pool().GetId("chrome.peak_resident_set_kb");
- for (uint32_t memory_index = 0; memory_index < memory_snapshots.row_count();
- ++memory_index) {
+ for (auto sit = memory_snapshots.IterateRows(); sit; ++sit) {
Json::Value event_base;
event_base["ph"] = "v";
event_base["cat"] = "disabled-by-default-memory-infra";
- auto snapshot_id = memory_snapshots.id()[memory_index].value;
- event_base["id"] = base::Uint64ToHexString(snapshot_id);
- int64_t snapshot_ts = memory_snapshots.timestamp()[memory_index];
+ auto snapshot_id = sit.id();
+ event_base["id"] = base::Uint64ToHexString(snapshot_id.value);
+ int64_t snapshot_ts = sit.timestamp();
event_base["ts"] = Json::Int64(snapshot_ts / 1000);
// TODO(crbug:1116359): Add dump type to the snapshot proto
// to properly fill event_base["name"]
event_base["name"] = "periodic_interval";
- event_base["args"]["dumps"]["level_of_detail"] = GetNonNullString(
- storage_, memory_snapshots.detail_level()[memory_index]);
+ event_base["args"]["dumps"]["level_of_detail"] =
+ GetNonNullString(storage_, sit.detail_level());
// Export OS dump events for processes with relevant data.
const auto& process_table = storage_->process_table();
- for (UniquePid upid = 0; upid < process_table.row_count(); ++upid) {
- Json::Value event =
- FillInProcessEventDetails(event_base, process_table.pid()[upid]);
+ for (auto pit = process_table.IterateRows(); pit; ++pit) {
+ Json::Value event = FillInProcessEventDetails(event_base, pit.pid());
Json::Value& totals = event["args"]["dumps"]["process_totals"];
const auto& process_counters = storage_->process_counter_track_table();
- for (uint32_t counter_index = 0;
- counter_index < process_counters.row_count(); ++counter_index) {
- if (process_counters.upid()[counter_index] != upid)
+ for (auto it = process_counters.IterateRows(); it; ++it) {
+ if (it.upid() != pit.id().value)
continue;
- TrackId track_id = process_counters.id()[counter_index];
- if (private_footprint_id && (process_counters.name()[counter_index] ==
- private_footprint_id)) {
+ TrackId track_id = it.id();
+ if (private_footprint_id && (it.name() == private_footprint_id)) {
totals["private_footprint_bytes"] = base::Uint64ToHexStringNoPrefix(
GetCounterValue(track_id, snapshot_ts));
} else if (peak_resident_set_id &&
- (process_counters.name()[counter_index] ==
- peak_resident_set_id)) {
+ (it.name() == peak_resident_set_id)) {
totals["peak_resident_set_size"] = base::Uint64ToHexStringNoPrefix(
GetCounterValue(track_id, snapshot_ts));
}
}
- auto process_args_id = process_table.arg_set_id()[upid];
+ auto process_args_id = pit.arg_set_id();
if (process_args_id) {
const Json::Value* process_args =
&args_builder_.GetArgs(process_args_id);
@@ -1621,49 +1593,33 @@
smaps_table.row_count() > 0
? &event["args"]["dumps"]["process_mmaps"]["vm_regions"]
: nullptr;
- for (uint32_t smaps_index = 0; smaps_index < smaps_table.row_count();
- ++smaps_index) {
- if (smaps_table.upid()[smaps_index] != upid)
+ for (auto it = smaps_table.IterateRows(); it; ++it) {
+ if (it.upid() != pit.id().value)
continue;
- if (smaps_table.ts()[smaps_index] != snapshot_ts)
+ if (it.ts() != snapshot_ts)
continue;
Json::Value region;
- region["mf"] =
- GetNonNullString(storage_, smaps_table.file_name()[smaps_index]);
- region["pf"] =
- Json::Int64(smaps_table.protection_flags()[smaps_index]);
+ region["mf"] = GetNonNullString(storage_, it.file_name());
+ region["pf"] = Json::Int64(it.protection_flags());
region["sa"] = base::Uint64ToHexStringNoPrefix(
- static_cast<uint64_t>(smaps_table.start_address()[smaps_index]));
+ static_cast<uint64_t>(it.start_address()));
region["sz"] = base::Uint64ToHexStringNoPrefix(
- static_cast<uint64_t>(smaps_table.size_kb()[smaps_index]) * 1024);
- region["ts"] =
- Json::Int64(smaps_table.module_timestamp()[smaps_index]);
- region["id"] = GetNonNullString(
- storage_, smaps_table.module_debugid()[smaps_index]);
- region["df"] = GetNonNullString(
- storage_, smaps_table.module_debug_path()[smaps_index]);
+ static_cast<uint64_t>(it.size_kb()) * 1024);
+ region["ts"] = Json::Int64(it.module_timestamp());
+ region["id"] = GetNonNullString(storage_, it.module_debugid());
+ region["df"] = GetNonNullString(storage_, it.module_debug_path());
region["bs"]["pc"] = base::Uint64ToHexStringNoPrefix(
- static_cast<uint64_t>(
- smaps_table.private_clean_resident_kb()[smaps_index]) *
- 1024);
+ static_cast<uint64_t>(it.private_clean_resident_kb()) * 1024);
region["bs"]["pd"] = base::Uint64ToHexStringNoPrefix(
- static_cast<uint64_t>(
- smaps_table.private_dirty_kb()[smaps_index]) *
- 1024);
+ static_cast<uint64_t>(it.private_dirty_kb()) * 1024);
region["bs"]["pss"] = base::Uint64ToHexStringNoPrefix(
- static_cast<uint64_t>(
- smaps_table.proportional_resident_kb()[smaps_index]) *
- 1024);
+ static_cast<uint64_t>(it.proportional_resident_kb()) * 1024);
region["bs"]["sc"] = base::Uint64ToHexStringNoPrefix(
- static_cast<uint64_t>(
- smaps_table.shared_clean_resident_kb()[smaps_index]) *
- 1024);
+ static_cast<uint64_t>(it.shared_clean_resident_kb()) * 1024);
region["bs"]["sd"] = base::Uint64ToHexStringNoPrefix(
- static_cast<uint64_t>(
- smaps_table.shared_dirty_resident_kb()[smaps_index]) *
- 1024);
+ static_cast<uint64_t>(it.shared_dirty_resident_kb()) * 1024);
region["bs"]["sw"] = base::Uint64ToHexStringNoPrefix(
- static_cast<uint64_t>(smaps_table.swap_kb()[smaps_index]) * 1024);
+ static_cast<uint64_t>(it.swap_kb()) * 1024);
smaps->append(region);
}
@@ -1675,23 +1631,22 @@
// snapshot.
const auto& process_snapshots = storage_->process_memory_snapshot_table();
- for (uint32_t process_index = 0;
- process_index < process_snapshots.row_count(); ++process_index) {
- if (process_snapshots.snapshot_id()[process_index].value != snapshot_id)
+ for (auto psit = process_snapshots.IterateRows(); psit; ++psit) {
+ if (psit.snapshot_id() != snapshot_id)
continue;
- auto process_snapshot_id = process_snapshots.id()[process_index].value;
- uint32_t pid = UpidToPid(process_snapshots.upid()[process_index]);
+ auto process_snapshot_id = psit.id();
+ uint32_t pid = UpidToPid(psit.upid());
// Shared memory nodes are imported into a fake process with pid 0.
// Catapult expects them to be associated with one of the real processes
// of the snapshot, so we choose the first one we can find and replace
// the pid.
if (pid == 0) {
- for (uint32_t i = 0; i < process_snapshots.row_count(); ++i) {
- if (process_snapshots.snapshot_id()[i].value != snapshot_id)
+ for (auto iit = process_snapshots.IterateRows(); iit; ++iit) {
+ if (iit.snapshot_id() != snapshot_id)
continue;
- uint32_t new_pid = UpidToPid(process_snapshots.upid()[i]);
+ uint32_t new_pid = UpidToPid(iit.upid());
if (new_pid != 0) {
pid = new_pid;
break;
@@ -1701,31 +1656,25 @@
Json::Value event = FillInProcessEventDetails(event_base, pid);
- const auto& snapshot_nodes = storage_->memory_snapshot_node_table();
+ const auto& sn = storage_->memory_snapshot_node_table();
- for (uint32_t node_index = 0; node_index < snapshot_nodes.row_count();
- ++node_index) {
- if (snapshot_nodes.process_snapshot_id()[node_index].value !=
- process_snapshot_id) {
+ for (auto it = sn.IterateRows(); it; ++it) {
+ if (it.process_snapshot_id() != process_snapshot_id) {
continue;
}
- const char* path =
- GetNonNullString(storage_, snapshot_nodes.path()[node_index]);
+ const char* path = GetNonNullString(storage_, it.path());
event["args"]["dumps"]["allocators"][path]["guid"] =
base::Uint64ToHexStringNoPrefix(
- static_cast<uint64_t>(snapshot_nodes.id()[node_index].value));
- if (snapshot_nodes.size()[node_index]) {
- AddAttributeToMemoryNode(&event, path, "size",
- snapshot_nodes.size()[node_index],
- "bytes");
+ static_cast<uint64_t>(it.id().value));
+ if (it.size()) {
+ AddAttributeToMemoryNode(&event, path, "size", it.size(), "bytes");
}
- if (snapshot_nodes.effective_size()[node_index]) {
- AddAttributeToMemoryNode(
- &event, path, "effective_size",
- snapshot_nodes.effective_size()[node_index], "bytes");
+ if (it.effective_size()) {
+ AddAttributeToMemoryNode(&event, path, "effective_size",
+ it.effective_size(), "bytes");
}
- auto node_args_id = snapshot_nodes.arg_set_id()[node_index];
+ auto node_args_id = it.arg_set_id();
if (!node_args_id)
continue;
const Json::Value* node_args =
@@ -1748,32 +1697,26 @@
}
const auto& snapshot_edges = storage_->memory_snapshot_edge_table();
+ for (auto it = snapshot_edges.IterateRows(); it; ++it) {
+ SnapshotNodeId source_node_id = it.source_node_id();
+ auto source_node_rr = *sn.FindById(source_node_id);
- for (uint32_t edge_index = 0; edge_index < snapshot_edges.row_count();
- ++edge_index) {
- SnapshotNodeId source_node_id =
- snapshot_edges.source_node_id()[edge_index];
- uint32_t source_node_row =
- *snapshot_nodes.id().IndexOf(source_node_id);
-
- if (snapshot_nodes.process_snapshot_id()[source_node_row].value !=
- process_snapshot_id) {
+ if (source_node_rr.process_snapshot_id() != process_snapshot_id) {
continue;
}
Json::Value edge;
- edge["source"] = base::Uint64ToHexStringNoPrefix(
- snapshot_edges.source_node_id()[edge_index].value);
- edge["target"] = base::Uint64ToHexStringNoPrefix(
- snapshot_edges.target_node_id()[edge_index].value);
- edge["importance"] =
- Json::Int(snapshot_edges.importance()[edge_index]);
+ edge["source"] =
+ base::Uint64ToHexStringNoPrefix(it.source_node_id().value);
+ edge["target"] =
+ base::Uint64ToHexStringNoPrefix(it.target_node_id().value);
+ edge["importance"] = Json::Int(it.importance());
edge["type"] = "ownership";
event["args"]["dumps"]["allocators_graph"].append(edge);
}
writer_.WriteCommonEvent(event);
}
}
- return util::OkStatus();
+ return base::OkStatus();
}
uint32_t UpidToPid(UniquePid upid) {
@@ -1798,33 +1741,32 @@
bool IsValidPidOrTid(uint32_t pid_or_tid) {
const auto& process_table = storage_->process_table();
- for (UniquePid upid = 0; upid < process_table.row_count(); upid++) {
- if (process_table.pid()[upid] == pid_or_tid)
+ for (auto it = process_table.IterateRows(); it; ++it) {
+ if (it.pid() == pid_or_tid)
return true;
}
const auto& thread_table = storage_->thread_table();
- for (UniqueTid utid = 0; utid < thread_table.row_count(); utid++) {
- if (thread_table.tid()[utid] == pid_or_tid)
+ for (auto it = thread_table.IterateRows(); it; ++it) {
+ if (it.tid() == pid_or_tid)
return true;
}
-
return false;
}
- Json::Value FillInProcessEventDetails(const Json::Value& event,
- uint32_t pid) {
+ static Json::Value FillInProcessEventDetails(const Json::Value& event,
+ uint32_t pid) {
Json::Value output = event;
output["pid"] = Json::Int(pid);
output["tid"] = Json::Int(-1);
return output;
}
- void AddAttributeToMemoryNode(Json::Value* event,
- const std::string& path,
- const std::string& key,
- int64_t value,
- const std::string& units) {
+ static void AddAttributeToMemoryNode(Json::Value* event,
+ const std::string& path,
+ const std::string& key,
+ int64_t value,
+ const std::string& units) {
(*event)["args"]["dumps"]["allocators"][path]["attrs"][key]["value"] =
base::Uint64ToHexStringNoPrefix(static_cast<uint64_t>(value));
(*event)["args"]["dumps"]["allocators"][path]["attrs"][key]["type"] =
@@ -1833,11 +1775,11 @@
units;
}
- void AddAttributeToMemoryNode(Json::Value* event,
- const std::string& path,
- const std::string& key,
- const std::string& value,
- const std::string& units = "") {
+ static void AddAttributeToMemoryNode(Json::Value* event,
+ const std::string& path,
+ const std::string& key,
+ const std::string& value,
+ const std::string& units = "") {
(*event)["args"]["dumps"]["allocators"][path]["attrs"][key]["value"] =
value;
(*event)["args"]["dumps"]["allocators"][path]["attrs"][key]["type"] =
@@ -1862,8 +1804,9 @@
for (; it < end; ++it) {
if ((*it).AsLong() != ts)
break;
- if (counter_table.track_id()[it.row()].value == track_id.value)
- return static_cast<uint64_t>(counter_table.value()[it.row()]);
+ if (auto rr = counter_table[it.row()]; rr.track_id() == track_id) {
+ return static_cast<uint64_t>(rr.value());
+ }
}
return 0;
}
@@ -1894,7 +1837,7 @@
OutputWriter::OutputWriter() = default;
OutputWriter::~OutputWriter() = default;
-util::Status ExportJson(const TraceStorage* storage,
+base::Status ExportJson(const TraceStorage* storage,
OutputWriter* output,
ArgumentFilterPredicate argument_filter,
MetadataFilterPredicate metadata_filter,
@@ -1909,11 +1852,11 @@
perfetto::base::ignore_result(argument_filter);
perfetto::base::ignore_result(metadata_filter);
perfetto::base::ignore_result(label_filter);
- return util::ErrStatus("JSON support is not compiled in this build");
+ return base::ErrStatus("JSON support is not compiled in this build");
#endif // PERFETTO_BUILDFLAG(PERFETTO_TP_JSON)
}
-util::Status ExportJson(TraceProcessorStorage* tp,
+base::Status ExportJson(TraceProcessorStorage* tp,
OutputWriter* output,
ArgumentFilterPredicate argument_filter,
MetadataFilterPredicate metadata_filter,
@@ -1921,15 +1864,13 @@
const TraceStorage* storage = reinterpret_cast<TraceProcessorStorageImpl*>(tp)
->context()
->storage.get();
- return ExportJson(storage, output, argument_filter, metadata_filter,
- label_filter);
+ return ExportJson(storage, output, std::move(argument_filter),
+ std::move(metadata_filter), std::move(label_filter));
}
-util::Status ExportJson(const TraceStorage* storage, FILE* output) {
+base::Status ExportJson(const TraceStorage* storage, FILE* output) {
FileWriter writer(output);
return ExportJson(storage, &writer, nullptr, nullptr, nullptr);
}
-} // namespace json
-} // namespace trace_processor
-} // namespace perfetto
+} // namespace perfetto::trace_processor::json
diff --git a/src/trace_processor/export_json_unittest.cc b/src/trace_processor/export_json_unittest.cc
index 90677c2..5a77efd 100644
--- a/src/trace_processor/export_json_unittest.cc
+++ b/src/trace_processor/export_json_unittest.cc
@@ -15,14 +15,24 @@
*/
#include "perfetto/ext/trace_processor/export_json.h"
+#include "perfetto/base/status.h"
+#include "perfetto/ext/base/string_view.h"
+#include "perfetto/trace_processor/status.h"
#include "src/trace_processor/export_json.h"
-#include <string.h>
-
-#include <limits>
-
+#include <json/config.h>
#include <json/reader.h>
#include <json/value.h>
+#include <array>
+#include <cstdint>
+#include <cstdio>
+#include <cstring>
+#include <limits>
+#include <memory>
+#include <optional>
+#include <string>
+#include <utility>
+#include <vector>
#include "perfetto/ext/base/string_utils.h"
#include "perfetto/ext/base/temp_file.h"
@@ -35,14 +45,15 @@
#include "src/trace_processor/importers/common/process_tracker.h"
#include "src/trace_processor/importers/common/track_tracker.h"
#include "src/trace_processor/importers/proto/track_event_tracker.h"
+#include "src/trace_processor/storage/metadata.h"
+#include "src/trace_processor/storage/stats.h"
#include "src/trace_processor/storage/trace_storage.h"
+#include "src/trace_processor/tables/metadata_tables_py.h"
#include "src/trace_processor/types/trace_processor_context.h"
-
+#include "src/trace_processor/types/variadic.h"
#include "test/gtest_and_gmock.h"
-namespace perfetto {
-namespace trace_processor {
-namespace json {
+namespace perfetto::trace_processor::json {
namespace {
std::string ReadFile(FILE* input) {
@@ -51,7 +62,7 @@
char buffer[kBufSize];
size_t ret = fread(buffer, sizeof(char), kBufSize, input);
EXPECT_GT(ret, 0u);
- return std::string(buffer, ret);
+ return {buffer, ret};
}
class StringOutputWriter : public OutputWriter {
@@ -59,9 +70,9 @@
StringOutputWriter() { str_.reserve(1024); }
~StringOutputWriter() override {}
- util::Status AppendString(const std::string& str) override {
+ base::Status AppendString(const std::string& str) override {
str_ += str;
- return util::OkStatus();
+ return base::OkStatus();
}
std::string TakeStr() { return std::move(str_); }
@@ -90,16 +101,16 @@
std::string ToJson(ArgumentFilterPredicate argument_filter = nullptr,
MetadataFilterPredicate metadata_filter = nullptr,
- LabelFilterPredicate label_filter = nullptr) {
+ LabelFilterPredicate label_filter = nullptr) const {
StringOutputWriter writer;
- util::Status status =
- ExportJson(context_.storage.get(), &writer, argument_filter,
- metadata_filter, label_filter);
+ base::Status status =
+ ExportJson(context_.storage.get(), &writer, std::move(argument_filter),
+ std::move(metadata_filter), std::move(label_filter));
EXPECT_TRUE(status.ok());
return writer.TakeStr();
}
- Json::Value ToJsonValue(const std::string& json) {
+ static Json::Value ToJsonValue(const std::string& json) {
Json::CharReaderBuilder b;
auto reader = std::unique_ptr<Json::CharReader>(b.newCharReader());
Json::Value result;
@@ -115,8 +126,8 @@
TEST_F(ExportJsonTest, EmptyStorage) {
base::TempFile temp_file = base::TempFile::Create();
- FILE* output = fopen(temp_file.path().c_str(), "w+");
- util::Status status = ExportJson(context_.storage.get(), output);
+ FILE* output = fopen(temp_file.path().c_str(), "w+e");
+ base::Status status = ExportJson(context_.storage.get(), output);
EXPECT_TRUE(status.ok());
@@ -147,8 +158,8 @@
kThreadInstructionDelta});
base::TempFile temp_file = base::TempFile::Create();
- FILE* output = fopen(temp_file.path().c_str(), "w+");
- util::Status status = ExportJson(context_.storage.get(), output);
+ FILE* output = fopen(temp_file.path().c_str(), "w+e");
+ base::Status status = ExportJson(context_.storage.get(), output);
EXPECT_TRUE(status.ok());
@@ -192,8 +203,8 @@
kThreadInstructionDelta});
base::TempFile temp_file = base::TempFile::Create();
- FILE* output = fopen(temp_file.path().c_str(), "w+");
- util::Status status = ExportJson(context_.storage.get(), output);
+ FILE* output = fopen(temp_file.path().c_str(), "w+e");
+ base::Status status = ExportJson(context_.storage.get(), output);
EXPECT_TRUE(status.ok());
@@ -224,8 +235,8 @@
context_.storage->mutable_thread_table()->Insert(row);
base::TempFile temp_file = base::TempFile::Create();
- FILE* output = fopen(temp_file.path().c_str(), "w+");
- util::Status status = ExportJson(context_.storage.get(), output);
+ FILE* output = fopen(temp_file.path().c_str(), "w+e");
+ base::Status status = ExportJson(context_.storage.get(), output);
EXPECT_TRUE(status.ok());
@@ -251,8 +262,8 @@
{0, 0, track, cat_id, name_id, 0, 0, 0});
base::TempFile temp_file = base::TempFile::Create();
- FILE* output = fopen(temp_file.path().c_str(), "w+");
- util::Status status = ExportJson(context_.storage.get(), output);
+ FILE* output = fopen(temp_file.path().c_str(), "w+e");
+ base::Status status = ExportJson(context_.storage.get(), output);
EXPECT_TRUE(status.ok());
@@ -320,8 +331,8 @@
context_.metadata_tracker->SetDynamicMetadata(dynamic_key_id, had_failures);
base::TempFile temp_file = base::TempFile::Create();
- FILE* output = fopen(temp_file.path().c_str(), "w+");
- util::Status status = ExportJson(context_.storage.get(), output);
+ FILE* output = fopen(temp_file.path().c_str(), "w+e");
+ base::Status status = ExportJson(context_.storage.get(), output);
EXPECT_TRUE(status.ok());
@@ -372,8 +383,8 @@
kFtraceBegin);
base::TempFile temp_file = base::TempFile::Create();
- FILE* output = fopen(temp_file.path().c_str(), "w+");
- util::Status status = ExportJson(context_.storage.get(), output);
+ FILE* output = fopen(temp_file.path().c_str(), "w+e");
+ base::Status status = ExportJson(context_.storage.get(), output);
EXPECT_TRUE(status.ok());
Json::Value result = ToJsonValue(ReadFile(output));
@@ -414,8 +425,8 @@
context_.args_tracker->Flush();
base::TempFile temp_file = base::TempFile::Create();
- FILE* output = fopen(temp_file.path().c_str(), "w+");
- util::Status status = ExportJson(storage, output);
+ FILE* output = fopen(temp_file.path().c_str(), "w+e");
+ base::Status status = ExportJson(storage, output);
EXPECT_TRUE(status.ok());
Json::Value result = ToJsonValue(ReadFile(output));
@@ -449,11 +460,12 @@
arg.key = arg_key_id;
arg.value = Variadic::String(arg_value_id);
ArgSetId args = context_.global_args_tracker->AddArgSet({arg}, 0, 1);
- context_.storage->mutable_slice_table()->mutable_arg_set_id()->Set(0, args);
+ auto& slice = *context_.storage->mutable_slice_table();
+ slice[0].set_arg_set_id(args);
base::TempFile temp_file = base::TempFile::Create();
- FILE* output = fopen(temp_file.path().c_str(), "w+");
- util::Status status = ExportJson(context_.storage.get(), output);
+ FILE* output = fopen(temp_file.path().c_str(), "w+e");
+ base::Status status = ExportJson(context_.storage.get(), output);
EXPECT_TRUE(status.ok());
@@ -487,8 +499,8 @@
storage->mutable_flow_table()->Insert({id1, id2, 0});
base::TempFile temp_file = base::TempFile::Create();
- FILE* output = fopen(temp_file.path().c_str(), "w+");
- util::Status status = ExportJson(storage, output);
+ FILE* output = fopen(temp_file.path().c_str(), "w+e");
+ base::Status status = ExportJson(storage, output);
EXPECT_TRUE(status.ok());
@@ -547,11 +559,12 @@
arg1.key = arg_key1_id;
arg1.value = Variadic::Real(kValues[1]);
ArgSetId args = context_.global_args_tracker->AddArgSet({arg0, arg1}, 0, 2);
- context_.storage->mutable_slice_table()->mutable_arg_set_id()->Set(0, args);
+ auto& slice = *context_.storage->mutable_slice_table();
+ slice[0].set_arg_set_id(args);
base::TempFile temp_file = base::TempFile::Create();
- FILE* output = fopen(temp_file.path().c_str(), "w+");
- util::Status status = ExportJson(context_.storage.get(), output);
+ FILE* output = fopen(temp_file.path().c_str(), "w+e");
+ base::Status status = ExportJson(context_.storage.get(), output);
EXPECT_TRUE(status.ok());
@@ -593,11 +606,12 @@
arg1.key = arg_key1_id;
arg1.value = Variadic::Pointer(kValue1);
ArgSetId args = context_.global_args_tracker->AddArgSet({arg0, arg1}, 0, 2);
- context_.storage->mutable_slice_table()->mutable_arg_set_id()->Set(0, args);
+ auto& slice = *context_.storage->mutable_slice_table();
+ slice[0].set_arg_set_id(args);
base::TempFile temp_file = base::TempFile::Create();
- FILE* output = fopen(temp_file.path().c_str(), "w+");
- util::Status status = ExportJson(context_.storage.get(), output);
+ FILE* output = fopen(temp_file.path().c_str(), "w+e");
+ base::Status status = ExportJson(context_.storage.get(), output);
EXPECT_TRUE(status.ok());
@@ -639,11 +653,12 @@
arg1.key = arg_key1_id;
arg1.value = Variadic::Integer(kValues[1]);
ArgSetId args = context_.global_args_tracker->AddArgSet({arg0, arg1}, 0, 2);
- context_.storage->mutable_slice_table()->mutable_arg_set_id()->Set(0, args);
+ auto& slice = *context_.storage->mutable_slice_table();
+ slice[0].set_arg_set_id(args);
base::TempFile temp_file = base::TempFile::Create();
- FILE* output = fopen(temp_file.path().c_str(), "w+");
- util::Status status = ExportJson(context_.storage.get(), output);
+ FILE* output = fopen(temp_file.path().c_str(), "w+e");
+ base::Status status = ExportJson(context_.storage.get(), output);
EXPECT_TRUE(status.ok());
@@ -686,11 +701,12 @@
arg1.key = arg_key1_id;
arg1.value = Variadic::Integer(kValues[1]);
ArgSetId args = context_.global_args_tracker->AddArgSet({arg0, arg1}, 0, 2);
- context_.storage->mutable_slice_table()->mutable_arg_set_id()->Set(0, args);
+ auto& slice = *context_.storage->mutable_slice_table();
+ slice[0].set_arg_set_id(args);
base::TempFile temp_file = base::TempFile::Create();
- FILE* output = fopen(temp_file.path().c_str(), "w+");
- util::Status status = ExportJson(context_.storage.get(), output);
+ FILE* output = fopen(temp_file.path().c_str(), "w+e");
+ base::Status status = ExportJson(context_.storage.get(), output);
EXPECT_TRUE(status.ok());
@@ -726,11 +742,12 @@
arg.key = arg_key_id;
arg.value = Variadic::Json(arg_value_id);
ArgSetId args = context_.global_args_tracker->AddArgSet({arg}, 0, 1);
- context_.storage->mutable_slice_table()->mutable_arg_set_id()->Set(0, args);
+ auto& slice = *context_.storage->mutable_slice_table();
+ slice[0].set_arg_set_id(args);
base::TempFile temp_file = base::TempFile::Create();
- FILE* output = fopen(temp_file.path().c_str(), "w+");
- util::Status status = ExportJson(context_.storage.get(), output);
+ FILE* output = fopen(temp_file.path().c_str(), "w+e");
+ base::Status status = ExportJson(context_.storage.get(), output);
EXPECT_TRUE(status.ok());
@@ -774,8 +791,8 @@
{kTimestamp3, 0, track3, cat_id, name_id, 0, 0, 0});
base::TempFile temp_file = base::TempFile::Create();
- FILE* output = fopen(temp_file.path().c_str(), "w+");
- util::Status status = ExportJson(context_.storage.get(), output);
+ FILE* output = fopen(temp_file.path().c_str(), "w+e");
+ base::Status status = ExportJson(context_.storage.get(), output);
EXPECT_TRUE(status.ok());
@@ -819,8 +836,8 @@
{kTimestamp, 0, track, cat_id, name_id, 0, 0, 0});
base::TempFile temp_file = base::TempFile::Create();
- FILE* output = fopen(temp_file.path().c_str(), "w+");
- util::Status status = ExportJson(context_.storage.get(), output);
+ FILE* output = fopen(temp_file.path().c_str(), "w+e");
+ base::Status status = ExportJson(context_.storage.get(), output);
EXPECT_TRUE(status.ok());
@@ -858,11 +875,12 @@
ASSERT_NE(utid1b, utid2b);
ASSERT_NE(utid1c, utid2b);
- ASSERT_EQ(upid1, *context_.storage->thread_table().upid()[utid1a]);
- ASSERT_EQ(upid1, *context_.storage->thread_table().upid()[utid1b]);
- ASSERT_EQ(upid1, *context_.storage->thread_table().upid()[utid1c]);
- ASSERT_EQ(upid2, *context_.storage->thread_table().upid()[utid2a]);
- ASSERT_EQ(upid2, *context_.storage->thread_table().upid()[utid2b]);
+ const auto& thread_table = context_.storage->thread_table();
+ ASSERT_EQ(upid1, *thread_table[utid1a].upid());
+ ASSERT_EQ(upid1, *thread_table[utid1b].upid());
+ ASSERT_EQ(upid1, *thread_table[utid1c].upid());
+ ASSERT_EQ(upid2, *thread_table[utid2a].upid());
+ ASSERT_EQ(upid2, *thread_table[utid2b].upid());
TrackId track1a = context_.track_tracker->InternThreadTrack(utid1a);
TrackId track1b = context_.track_tracker->InternThreadTrack(utid1b);
@@ -895,8 +913,8 @@
{50000, 1000, track2b, cat_id, name2b_id, 0, 0, 0});
base::TempFile temp_file = base::TempFile::Create();
- FILE* output = fopen(temp_file.path().c_str(), "w+");
- util::Status status = ExportJson(context_.storage.get(), output);
+ FILE* output = fopen(temp_file.path().c_str(), "w+e");
+ base::Status status = ExportJson(context_.storage.get(), output);
EXPECT_TRUE(status.ok());
@@ -965,11 +983,11 @@
constexpr int64_t kSourceId = 235;
TrackId track = context_.track_tracker->InternLegacyChromeAsyncTrack(
- name_id, upid, kSourceId, /*source_id_is_process_scoped=*/true,
+ name_id, upid, kSourceId, /*trace_id_is_process_scoped=*/true,
/*source_scope=*/kNullStringId);
constexpr int64_t kSourceId2 = 236;
TrackId track2 = context_.track_tracker->InternLegacyChromeAsyncTrack(
- name3_id, upid, kSourceId2, /*source_id_is_process_scoped=*/true,
+ name3_id, upid, kSourceId2, /*trace_id_is_process_scoped=*/true,
/*source_scope=*/kNullStringId);
context_.args_tracker->Flush(); // Flush track args.
@@ -982,7 +1000,8 @@
arg.key = arg_key_id;
arg.value = Variadic::Integer(kArgValue);
ArgSetId args = context_.global_args_tracker->AddArgSet({arg}, 0, 1);
- context_.storage->mutable_slice_table()->mutable_arg_set_id()->Set(0, args);
+ auto& slice = *context_.storage->mutable_slice_table();
+ slice[0].set_arg_set_id(args);
// Child event with same timestamps as first one.
context_.storage->mutable_slice_table()->Insert(
@@ -993,8 +1012,8 @@
{kTimestamp3, kDuration3, track2, cat_id, name3_id, 0, 0, 0});
base::TempFile temp_file = base::TempFile::Create();
- FILE* output = fopen(temp_file.path().c_str(), "w+");
- util::Status status = ExportJson(context_.storage.get(), output);
+ FILE* output = fopen(temp_file.path().c_str(), "w+e");
+ base::Status status = ExportJson(context_.storage.get(), output);
EXPECT_TRUE(status.ok());
@@ -1111,11 +1130,11 @@
constexpr int64_t kSourceId = 235;
TrackId track = context_.track_tracker->InternLegacyChromeAsyncTrack(
- name_id, upid, kSourceId, /*source_id_is_process_scoped=*/true,
+ name_id, upid, kSourceId, /*trace_id_is_process_scoped=*/true,
/*source_scope=*/kNullStringId);
constexpr int64_t kSourceId2 = 236;
TrackId track2 = context_.track_tracker->InternLegacyChromeAsyncTrack(
- name3_id, upid, kSourceId2, /*source_id_is_process_scoped=*/true,
+ name3_id, upid, kSourceId2, /*trace_id_is_process_scoped=*/true,
/*source_scope=*/kNullStringId);
context_.args_tracker->Flush(); // Flush track args.
@@ -1125,8 +1144,8 @@
arg_inserter("arg1", "value1", args1);
arg_inserter("legacy_event.phase", "S", args1);
ArgSetId arg_id1 = context_.global_args_tracker->AddArgSet(args1, 0, 2);
- context_.storage->mutable_slice_table()->mutable_arg_set_id()->Set(0,
- arg_id1);
+ auto& slice = *context_.storage->mutable_slice_table();
+ slice[0].set_arg_set_id(arg_id1);
// Step event with first event as parent.
context_.storage->mutable_slice_table()->Insert(
@@ -1136,8 +1155,7 @@
arg_inserter("legacy_event.phase", "T", step_args);
arg_inserter("debug.step", "Step1", step_args);
ArgSetId arg_id2 = context_.global_args_tracker->AddArgSet(step_args, 0, 3);
- context_.storage->mutable_slice_table()->mutable_arg_set_id()->Set(1,
- arg_id2);
+ slice[1].set_arg_set_id(arg_id2);
// Another overlapping async event on a different track.
context_.storage->mutable_slice_table()->Insert(
@@ -1145,12 +1163,11 @@
std::vector<Arg> args3;
arg_inserter("legacy_event.phase", "S", args3);
ArgSetId arg_id3 = context_.global_args_tracker->AddArgSet(args3, 0, 1);
- context_.storage->mutable_slice_table()->mutable_arg_set_id()->Set(2,
- arg_id3);
+ slice[2].set_arg_set_id(arg_id3);
base::TempFile temp_file = base::TempFile::Create();
- FILE* output = fopen(temp_file.path().c_str(), "w+");
- util::Status status = ExportJson(context_.storage.get(), output);
+ FILE* output = fopen(temp_file.path().c_str(), "w+e");
+ base::Status status = ExportJson(context_.storage.get(), output);
EXPECT_TRUE(status.ok());
@@ -1236,7 +1253,7 @@
constexpr int64_t kSourceId = 235;
TrackId track = context_.track_tracker->InternLegacyChromeAsyncTrack(
- name_id, upid, kSourceId, /*source_id_is_process_scoped=*/true,
+ name_id, upid, kSourceId, /*trace_id_is_process_scoped=*/true,
/*source_scope=*/kNullStringId);
context_.args_tracker->Flush(); // Flush track args.
@@ -1247,8 +1264,8 @@
id_and_row.id, kThreadTimestamp, kThreadDuration, 0, 0);
base::TempFile temp_file = base::TempFile::Create();
- FILE* output = fopen(temp_file.path().c_str(), "w+");
- util::Status status = ExportJson(context_.storage.get(), output);
+ FILE* output = fopen(temp_file.path().c_str(), "w+e");
+ base::Status status = ExportJson(context_.storage.get(), output);
EXPECT_TRUE(status.ok());
@@ -1292,7 +1309,7 @@
constexpr int64_t kSourceId = 235;
TrackId track = context_.track_tracker->InternLegacyChromeAsyncTrack(
- name_id, upid, kSourceId, /*source_id_is_process_scoped=*/true,
+ name_id, upid, kSourceId, /*trace_id_is_process_scoped=*/true,
/*source_scope=*/kNullStringId);
context_.args_tracker->Flush(); // Flush track args.
@@ -1304,8 +1321,8 @@
slice_id, kThreadTimestamp, kThreadDuration, 0, 0);
base::TempFile temp_file = base::TempFile::Create();
- FILE* output = fopen(temp_file.path().c_str(), "w+");
- util::Status status = ExportJson(context_.storage.get(), output);
+ FILE* output = fopen(temp_file.path().c_str(), "w+e");
+ base::Status status = ExportJson(context_.storage.get(), output);
EXPECT_TRUE(status.ok());
@@ -1337,7 +1354,7 @@
constexpr int64_t kSourceId = 235;
TrackId track = context_.track_tracker->InternLegacyChromeAsyncTrack(
- name_id, upid, kSourceId, /*source_id_is_process_scoped=*/true,
+ name_id, upid, kSourceId, /*trace_id_is_process_scoped=*/true,
/*source_scope=*/kNullStringId);
context_.args_tracker->Flush(); // Flush track args.
@@ -1350,11 +1367,12 @@
arg.key = arg_key_id;
arg.value = Variadic::Integer(kArgValue);
ArgSetId args = context_.global_args_tracker->AddArgSet({arg}, 0, 1);
- context_.storage->mutable_slice_table()->mutable_arg_set_id()->Set(0, args);
+ auto& slice = *context_.storage->mutable_slice_table();
+ slice[0].set_arg_set_id(args);
base::TempFile temp_file = base::TempFile::Create();
- FILE* output = fopen(temp_file.path().c_str(), "w+");
- util::Status status = ExportJson(context_.storage.get(), output);
+ FILE* output = fopen(temp_file.path().c_str(), "w+e");
+ base::Status status = ExportJson(context_.storage.get(), output);
EXPECT_TRUE(status.ok());
@@ -1394,7 +1412,9 @@
UniqueTid utid = context_.process_tracker->GetOrCreateThread(kThreadID);
UniquePid upid = context_.process_tracker->GetOrCreateProcess(kProcessID);
- context_.storage->mutable_thread_table()->mutable_upid()->Set(utid, upid);
+
+ auto& tt = *context_.storage->mutable_thread_table();
+ tt[utid].set_upid(upid);
auto ucpu = context_.cpu_tracker->GetOrCreateCpu(0);
auto id_and_row = storage->mutable_raw_table()->Insert(
@@ -1437,8 +1457,8 @@
context_.args_tracker->Flush();
base::TempFile temp_file = base::TempFile::Create();
- FILE* output = fopen(temp_file.path().c_str(), "w+");
- util::Status status = ExportJson(storage, output);
+ FILE* output = fopen(temp_file.path().c_str(), "w+e");
+ base::Status status = ExportJson(storage, output);
EXPECT_TRUE(status.ok());
@@ -1493,8 +1513,8 @@
context_.args_tracker->Flush();
base::TempFile temp_file = base::TempFile::Create();
- FILE* output = fopen(temp_file.path().c_str(), "w+");
- util::Status status = ExportJson(storage, output);
+ FILE* output = fopen(temp_file.path().c_str(), "w+e");
+ base::Status status = ExportJson(storage, output);
EXPECT_TRUE(status.ok());
@@ -1516,10 +1536,12 @@
UniqueTid utid = context_.process_tracker->GetOrCreateThread(kThreadID);
UniquePid upid = context_.process_tracker->GetOrCreateProcess(kProcessID);
- context_.storage->mutable_thread_table()->mutable_upid()->Set(utid, upid);
+
+ auto& tt = *context_.storage->mutable_thread_table();
+ tt[utid].set_upid(upid);
auto* mappings = storage->mutable_stack_profile_mapping_table();
- auto* frames = storage->mutable_stack_profile_frame_table();
+ auto& frames = *storage->mutable_stack_profile_frame_table();
auto* callsites = storage->mutable_stack_profile_callsite_table();
auto module_1 =
@@ -1534,22 +1556,22 @@
// stack_profile_frame.symbol_set_id remove this hack
storage->mutable_symbol_table()->Insert({0, kNullStringId, kNullStringId, 0});
- auto frame_1 = frames->Insert({/*name_id=*/kNullStringId, module_1.id, 0x42});
+ auto frame_1 = frames.Insert({/*in_name=*/kNullStringId, module_1.id, 0x42});
uint32_t symbol_set_id = storage->symbol_table().row_count();
storage->mutable_symbol_table()->Insert(
{symbol_set_id, storage->InternString("foo_func"),
storage->InternString("foo_file"), 66});
- frames->mutable_symbol_set_id()->Set(frame_1.row, symbol_set_id);
+ frames[frame_1.row].set_symbol_set_id(symbol_set_id);
auto frame_2 =
- frames->Insert({/*name_id=*/kNullStringId, module_2.id, 0x4242});
+ frames.Insert({/*in_name=*/kNullStringId, module_2.id, 0x4242});
symbol_set_id = storage->symbol_table().row_count();
storage->mutable_symbol_table()->Insert(
{symbol_set_id, storage->InternString("bar_func"),
storage->InternString("bar_file"), 77});
- frames->mutable_symbol_set_id()->Set(frame_2.row, symbol_set_id);
+ frames[frame_2.row].set_symbol_set_id(symbol_set_id);
auto frame_callsite_1 = callsites->Insert({0, std::nullopt, frame_1.id});
@@ -1566,8 +1588,8 @@
{kTimestamp + 20000, frame_callsite_1.id, utid, kProcessPriority});
base::TempFile temp_file = base::TempFile::Create();
- FILE* output = fopen(temp_file.path().c_str(), "w+");
- util::Status status = ExportJson(storage, output);
+ FILE* output = fopen(temp_file.path().c_str(), "w+e");
+ base::Status status = ExportJson(storage, output);
EXPECT_TRUE(status.ok());
@@ -1647,7 +1669,8 @@
if (strcmp(event_name, "name1") == 0) {
// Filter all args for name1.
return false;
- } else if (strcmp(event_name, "name2") == 0) {
+ }
+ if (strcmp(event_name, "name2") == 0) {
// Filter only the second arg for name2.
*arg_name_filter = [](const char* arg_name) {
if (strcmp(arg_name, "arg1") == 0) {
@@ -1821,8 +1844,8 @@
0, kProportionalResidentKb});
base::TempFile temp_file = base::TempFile::Create();
- FILE* output = fopen(temp_file.path().c_str(), "w+");
- util::Status status = ExportJson(context_.storage.get(), output);
+ FILE* output = fopen(temp_file.path().c_str(), "w+e");
+ base::Status status = ExportJson(context_.storage.get(), output);
EXPECT_TRUE(status.ok());
@@ -1947,8 +1970,8 @@
{node1_id, node2_id, kImportance});
base::TempFile temp_file = base::TempFile::Create();
- FILE* output = fopen(temp_file.path().c_str(), "w+");
- util::Status status = ExportJson(context_.storage.get(), output);
+ FILE* output = fopen(temp_file.path().c_str(), "w+e");
+ base::Status status = ExportJson(context_.storage.get(), output);
EXPECT_TRUE(status.ok());
@@ -2016,6 +2039,4 @@
}
} // namespace
-} // namespace json
-} // namespace trace_processor
-} // namespace perfetto
+} // namespace perfetto::trace_processor::json
diff --git a/src/trace_processor/importers/android_bugreport/android_dumpstate_reader.cc b/src/trace_processor/importers/android_bugreport/android_dumpstate_reader.cc
index 48d9135..2dd2e63 100644
--- a/src/trace_processor/importers/android_bugreport/android_dumpstate_reader.cc
+++ b/src/trace_processor/importers/android_bugreport/android_dumpstate_reader.cc
@@ -16,7 +16,15 @@
#include "src/trace_processor/importers/android_bugreport/android_dumpstate_reader.h"
+#include <cstddef>
+#include <cstdint>
+#include <utility>
+#include <vector>
+
#include "perfetto/base/status.h"
+#include "perfetto/ext/base/string_view.h"
+#include "src/trace_processor/importers/android_bugreport/android_log_reader.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"
@@ -26,12 +34,11 @@
TraceProcessorContext* context,
int32_t year,
std::vector<TimestampedAndroidLogEvent> logcat_events)
- : context_(context),
- log_reader_(context, std::move(year), std::move(logcat_events)) {}
+ : context_(context), log_reader_(context, year, std::move(logcat_events)) {}
AndroidDumpstateReader::~AndroidDumpstateReader() = default;
-util::Status AndroidDumpstateReader::ParseLine(base::StringView line) {
+base::Status AndroidDumpstateReader::ParseLine(base::StringView line) {
// Dumpstate is organized in a two level hierarchy, beautifully flattened into
// one text file with load bearing ----- markers:
// 1. Various dumpstate sections, examples:
diff --git a/src/trace_processor/importers/android_bugreport/android_dumpstate_reader.h b/src/trace_processor/importers/android_bugreport/android_dumpstate_reader.h
index 32abd85..54a19db 100644
--- a/src/trace_processor/importers/android_bugreport/android_dumpstate_reader.h
+++ b/src/trace_processor/importers/android_bugreport/android_dumpstate_reader.h
@@ -35,7 +35,7 @@
std::vector<TimestampedAndroidLogEvent> logcat_events);
~AndroidDumpstateReader() override;
- util::Status ParseLine(base::StringView line) override;
+ base::Status ParseLine(base::StringView line) override;
void EndOfStream(base::StringView leftovers) override;
private:
diff --git a/src/trace_processor/importers/common/BUILD.gn b/src/trace_processor/importers/common/BUILD.gn
index 1a22292..c2f61da 100644
--- a/src/trace_processor/importers/common/BUILD.gn
+++ b/src/trace_processor/importers/common/BUILD.gn
@@ -141,6 +141,7 @@
"../../../../protos/perfetto/trace:zero",
"../../../base",
"../../storage",
+ "../../tables",
"../../types",
]
}
diff --git a/src/trace_processor/importers/common/args_tracker.cc b/src/trace_processor/importers/common/args_tracker.cc
index d02d9ce..2454728 100644
--- a/src/trace_processor/importers/common/args_tracker.cc
+++ b/src/trace_processor/importers/common/args_tracker.cc
@@ -17,9 +17,15 @@
#include "src/trace_processor/importers/common/args_tracker.h"
#include <algorithm>
+#include <cstddef>
#include <cstdint>
+#include <optional>
+#include <tuple>
+#include "perfetto/base/logging.h"
+#include "perfetto/ext/base/small_vector.h"
#include "src/trace_processor/db/column.h"
+#include "src/trace_processor/db/typed_column.h"
#include "src/trace_processor/importers/common/args_translation_table.h"
#include "src/trace_processor/storage/trace_storage.h"
#include "src/trace_processor/types/trace_processor_context.h"
@@ -113,8 +119,8 @@
// Apply permutation of entries[].index to args.
base::SmallVector<Arg, 16> sorted_args;
- for (uint32_t i = 0; i < entries.size(); i++) {
- sorted_args.emplace_back(args_[entries[i].index]);
+ for (auto& entry : entries) {
+ sorted_args.emplace_back(args_[entry.index]);
}
// Insert args.
@@ -130,8 +136,8 @@
next_rid_idx++;
}
- ArgSetId set_id = context_->global_args_tracker->AddArgSet(&sorted_args[0],
- i, next_rid_idx);
+ ArgSetId set_id = context_->global_args_tracker->AddArgSet(
+ sorted_args.data(), i, next_rid_idx);
if (col->IsNullable()) {
TypedColumn<std::optional<uint32_t>>::FromColumn(col)->Set(row, set_id);
} else {
diff --git a/src/trace_processor/importers/common/args_tracker.h b/src/trace_processor/importers/common/args_tracker.h
index 81d19f6..912d574 100644
--- a/src/trace_processor/importers/common/args_tracker.h
+++ b/src/trace_processor/importers/common/args_tracker.h
@@ -17,6 +17,7 @@
#ifndef SRC_TRACE_PROCESSOR_IMPORTERS_COMMON_ARGS_TRACKER_H_
#define SRC_TRACE_PROCESSOR_IMPORTERS_COMMON_ARGS_TRACKER_H_
+#include <cstdint>
#include "perfetto/ext/base/small_vector.h"
#include "src/trace_processor/importers/common/global_args_tracker.h"
#include "src/trace_processor/storage/trace_storage.h"
@@ -169,8 +170,7 @@
}
BoundInserter AddArgsTo(tables::AndroidKeyEventsTable::Id id) {
- return AddArgsTo(context_->storage->mutable_android_key_events_table(),
- id);
+ return AddArgsTo(context_->storage->mutable_android_key_events_table(), id);
}
BoundInserter AddArgsTo(tables::AndroidMotionEventsTable::Id id) {
@@ -185,13 +185,13 @@
BoundInserter AddArgsTo(MetadataId id) {
auto* table = context_->storage->mutable_metadata_table();
- uint32_t row = *table->id().IndexOf(id);
+ uint32_t row = table->FindById(id)->ToRowNumber().row_number();
return BoundInserter(this, table->mutable_int_value(), row);
}
BoundInserter AddArgsTo(TrackId id) {
auto* table = context_->storage->mutable_track_table();
- uint32_t row = *table->id().IndexOf(id);
+ uint32_t row = table->FindById(id)->ToRowNumber().row_number();
return BoundInserter(this, table->mutable_source_arg_set_id(), row);
}
@@ -232,7 +232,7 @@
private:
template <typename Table>
BoundInserter AddArgsTo(Table* table, typename Table::Id id) {
- uint32_t row = *table->id().IndexOf(id);
+ uint32_t row = table->FindById(id)->ToRowNumber().row_number();
return BoundInserter(this, table->mutable_arg_set_id(), row);
}
diff --git a/src/trace_processor/importers/common/async_track_set_tracker_unittest.cc b/src/trace_processor/importers/common/async_track_set_tracker_unittest.cc
index 173fd89..49c625b 100644
--- a/src/trace_processor/importers/common/async_track_set_tracker_unittest.cc
+++ b/src/trace_processor/importers/common/async_track_set_tracker_unittest.cc
@@ -69,19 +69,19 @@
ASSERT_EQ(begin, end);
- uint32_t row = *storage_->process_track_table().id().IndexOf(begin);
- ASSERT_EQ(storage_->process_track_table().upid()[row], 1u);
- ASSERT_EQ(storage_->process_track_table().name()[row],
- storage_->InternString("test"));
+ const auto& process = storage_->process_track_table();
+ auto rr = *process.FindById(begin);
+ ASSERT_EQ(rr.upid(), 1u);
+ ASSERT_EQ(rr.name(), storage_->string_pool().GetId("test"));
}
TEST_F(AsyncTrackSetTrackerUnittest, EndFirst) {
auto end = tracker_->End(nestable_id_, 1);
- uint32_t row = *storage_->process_track_table().id().IndexOf(end);
- ASSERT_EQ(storage_->process_track_table().upid()[row], 1u);
- ASSERT_EQ(storage_->process_track_table().name()[row],
- storage_->InternString("test"));
+ const auto& process = storage_->process_track_table();
+ auto rr = *process.FindById(end);
+ ASSERT_EQ(rr.upid(), 1u);
+ ASSERT_EQ(rr.name(), storage_->string_pool().GetId("test"));
}
TEST_F(AsyncTrackSetTrackerUnittest, LegacySaturating) {
diff --git a/src/trace_processor/importers/common/cpu_tracker.h b/src/trace_processor/importers/common/cpu_tracker.h
index 3e2edc5..466fa92 100644
--- a/src/trace_processor/importers/common/cpu_tracker.h
+++ b/src/trace_processor/importers/common/cpu_tracker.h
@@ -18,7 +18,12 @@
#define SRC_TRACE_PROCESSOR_IMPORTERS_COMMON_CPU_TRACKER_H_
#include <bitset>
+#include <cstdint>
+#include <optional>
+#include "perfetto/base/logging.h"
+#include "perfetto/ext/base/string_view.h"
+#include "perfetto/public/compiler.h"
#include "src/trace_processor/storage/trace_storage.h"
#include "src/trace_processor/tables/metadata_tables_py.h"
#include "src/trace_processor/types/trace_processor_context.h"
@@ -46,10 +51,11 @@
auto ucpu = ucpu_offset_ + cpu;
if (PERFETTO_LIKELY(cpu_ids_[cpu]))
return tables::CpuTable::Id(ucpu);
-
cpu_ids_.set(cpu);
+
// Populate the optional |cpu| column.
- context_->storage->mutable_cpu_table()->mutable_cpu()->Set(ucpu, cpu);
+ auto& cpu_table = *context_->storage->mutable_cpu_table();
+ cpu_table[ucpu].set_cpu(cpu);
return tables::CpuTable::Id(ucpu);
}
diff --git a/src/trace_processor/importers/common/event_tracker.cc b/src/trace_processor/importers/common/event_tracker.cc
index a38d776..4b7e817 100644
--- a/src/trace_processor/importers/common/event_tracker.cc
+++ b/src/trace_processor/importers/common/event_tracker.cc
@@ -39,10 +39,11 @@
double value,
StringId name_id,
UniqueTid utid) {
+ const auto& counter = context_->storage->counter_table();
auto opt_id = PushCounter(timestamp, value, kInvalidTrackId);
if (opt_id) {
PendingUpidResolutionCounter pending;
- pending.row = *context_->storage->counter_table().id().IndexOf(*opt_id);
+ pending.row = counter.FindById(*opt_id)->ToRowNumber().row_number();
pending.utid = utid;
pending.name_id = name_id;
pending_upid_resolution_counter_.emplace_back(pending);
@@ -83,7 +84,7 @@
const auto& thread_table = context_->storage->thread_table();
for (const auto& pending_counter : pending_upid_resolution_counter_) {
UniqueTid utid = pending_counter.utid;
- std::optional<UniquePid> upid = thread_table.upid()[utid];
+ std::optional<UniquePid> upid = thread_table[utid].upid();
TrackId track_id = kInvalidTrackId;
if (upid.has_value()) {
@@ -96,8 +97,8 @@
track_id = context_->track_tracker->InternThreadCounterTrack(
pending_counter.name_id, utid);
}
- context_->storage->mutable_counter_table()->mutable_track_id()->Set(
- pending_counter.row, track_id);
+ auto& counter = *context_->storage->mutable_counter_table();
+ counter[pending_counter.row].set_track_id(track_id);
}
pending_upid_resolution_counter_.clear();
}
diff --git a/src/trace_processor/importers/common/event_tracker_unittest.cc b/src/trace_processor/importers/common/event_tracker_unittest.cc
index da559b0..64a3bdc 100644
--- a/src/trace_processor/importers/common/event_tracker_unittest.cc
+++ b/src/trace_processor/importers/common/event_tracker_unittest.cc
@@ -63,15 +63,20 @@
ASSERT_EQ(context.storage->counter_track_table().row_count(), 1ul);
- ASSERT_EQ(context.storage->counter_table().row_count(), 4ul);
- ASSERT_EQ(context.storage->counter_table().ts()[0], timestamp);
- ASSERT_DOUBLE_EQ(context.storage->counter_table().value()[0], 1000);
+ const auto& counter = context.storage->counter_table();
+ ASSERT_EQ(counter.row_count(), 4ul);
- ASSERT_EQ(context.storage->counter_table().ts()[1], timestamp + 1);
- ASSERT_DOUBLE_EQ(context.storage->counter_table().value()[1], 4000);
+ auto rr = counter[0];
+ ASSERT_EQ(rr.ts(), timestamp);
+ ASSERT_DOUBLE_EQ(rr.value(), 1000);
- ASSERT_EQ(context.storage->counter_table().ts()[2], timestamp + 3);
- ASSERT_DOUBLE_EQ(context.storage->counter_table().value()[2], 5000);
+ rr = counter[1];
+ ASSERT_EQ(rr.ts(), timestamp + 1);
+ ASSERT_DOUBLE_EQ(rr.value(), 4000);
+
+ rr = counter[2];
+ ASSERT_EQ(rr.ts(), timestamp + 3);
+ ASSERT_DOUBLE_EQ(rr.value(), 5000);
}
} // namespace
diff --git a/src/trace_processor/importers/common/flow_tracker_unittest.cc b/src/trace_processor/importers/common/flow_tracker_unittest.cc
index 9040734..82bbf40 100644
--- a/src/trace_processor/importers/common/flow_tracker_unittest.cc
+++ b/src/trace_processor/importers/common/flow_tracker_unittest.cc
@@ -70,8 +70,10 @@
const auto& flows = context_.storage->flow_table();
EXPECT_EQ(flows.row_count(), 1u);
- EXPECT_EQ(flows.slice_out()[0], out_slice_id);
- EXPECT_EQ(flows.slice_in()[0], in_slice_id);
+
+ auto f = flows[0];
+ EXPECT_EQ(f.slice_out(), out_slice_id);
+ EXPECT_EQ(f.slice_in(), in_slice_id);
}
TEST_F(FlowTrackerTest, SingleFlowEventWaitForNextSlice) {
@@ -103,8 +105,10 @@
slice_tracker->End(160, track_2, StringId::Raw(2), StringId::Raw(2));
EXPECT_EQ(flows.row_count(), 1u);
- EXPECT_EQ(flows.slice_out()[0], out_slice_id);
- EXPECT_EQ(flows.slice_in()[0], in_slice_id);
+
+ auto f = flows[0];
+ EXPECT_EQ(f.slice_out(), out_slice_id);
+ EXPECT_EQ(f.slice_in(), in_slice_id);
}
TEST_F(FlowTrackerTest, SingleFlowEventWaitForNextSliceScoped) {
@@ -135,8 +139,10 @@
SliceId in_slice_id = slice_tracker->GetTopmostSliceOnTrack(track_2).value();
EXPECT_EQ(flows.row_count(), 1u);
- EXPECT_EQ(flows.slice_out()[0], out_slice_id);
- EXPECT_EQ(flows.slice_in()[0], in_slice_id);
+
+ auto f = flows[0];
+ EXPECT_EQ(f.slice_out(), out_slice_id);
+ EXPECT_EQ(f.slice_in(), in_slice_id);
}
TEST_F(FlowTrackerTest, TwoFlowEventsWaitForNextSlice) {
@@ -180,10 +186,14 @@
slice_tracker->End(170, track_2, StringId::Raw(3), StringId::Raw(3));
EXPECT_EQ(flows.row_count(), 2u);
- EXPECT_EQ(flows.slice_out()[0], out_slice1_id);
- EXPECT_EQ(flows.slice_in()[0], in_slice_id);
- EXPECT_EQ(flows.slice_out()[1], out_slice2_id);
- EXPECT_EQ(flows.slice_in()[1], in_slice_id);
+
+ auto f = flows[0];
+ EXPECT_EQ(f.slice_out(), out_slice1_id);
+ EXPECT_EQ(f.slice_in(), in_slice_id);
+
+ f = flows[1];
+ EXPECT_EQ(f.slice_out(), out_slice2_id);
+ EXPECT_EQ(f.slice_in(), in_slice_id);
}
TEST_F(FlowTrackerTest, TwoFlowEventsSliceInSlice) {
@@ -227,10 +237,14 @@
const auto& flows = context_.storage->flow_table();
EXPECT_EQ(flows.row_count(), 2u);
- EXPECT_EQ(flows.slice_out()[0], out_slice2_id);
- EXPECT_EQ(flows.slice_in()[0], in_slice_id);
- EXPECT_EQ(flows.slice_out()[1], out_slice1_id);
- EXPECT_EQ(flows.slice_in()[1], in_slice_id);
+
+ auto f = flows[0];
+ EXPECT_EQ(f.slice_out(), out_slice2_id);
+ EXPECT_EQ(f.slice_in(), in_slice_id);
+
+ f = flows[1];
+ EXPECT_EQ(f.slice_out(), out_slice1_id);
+ EXPECT_EQ(f.slice_in(), in_slice_id);
}
TEST_F(FlowTrackerTest, FlowEventsWithStep) {
@@ -268,10 +282,14 @@
const auto& flows = context_.storage->flow_table();
EXPECT_EQ(flows.row_count(), 2u);
- EXPECT_EQ(flows.slice_out()[0], out_slice1_id);
- EXPECT_EQ(flows.slice_in()[0], inout_slice2_id);
- EXPECT_EQ(flows.slice_out()[1], inout_slice2_id);
- EXPECT_EQ(flows.slice_in()[1], in_slice_id);
+
+ auto f = flows[0];
+ EXPECT_EQ(f.slice_out(), out_slice1_id);
+ EXPECT_EQ(f.slice_in(), inout_slice2_id);
+
+ f = flows[1];
+ EXPECT_EQ(f.slice_out(), inout_slice2_id);
+ EXPECT_EQ(f.slice_in(), in_slice_id);
}
} // namespace
diff --git a/src/trace_processor/importers/common/global_args_tracker.h b/src/trace_processor/importers/common/global_args_tracker.h
index f94d2de..78bae43 100644
--- a/src/trace_processor/importers/common/global_args_tracker.h
+++ b/src/trace_processor/importers/common/global_args_tracker.h
@@ -17,10 +17,15 @@
#ifndef SRC_TRACE_PROCESSOR_IMPORTERS_COMMON_GLOBAL_ARGS_TRACKER_H_
#define SRC_TRACE_PROCESSOR_IMPORTERS_COMMON_GLOBAL_ARGS_TRACKER_H_
+#include <cstdint>
+#include <type_traits>
+#include <vector>
#include "perfetto/ext/base/flat_hash_map.h"
#include "perfetto/ext/base/hash.h"
#include "perfetto/ext/base/small_vector.h"
+#include "src/trace_processor/db/column.h"
#include "src/trace_processor/storage/trace_storage.h"
+#include "src/trace_processor/tables/metadata_tables_py.h"
#include "src/trace_processor/types/variadic.h"
namespace perfetto {
@@ -123,19 +128,19 @@
hash.Update(ArgHasher()(args[i]));
}
- auto* arg_table = storage_->mutable_arg_table();
+ auto& arg_table = *storage_->mutable_arg_table();
ArgSetHash digest = hash.digest();
auto it_and_inserted =
- arg_row_for_hash_.Insert(digest, arg_table->row_count());
+ arg_row_for_hash_.Insert(digest, arg_table.row_count());
if (!it_and_inserted.second) {
// Already inserted.
- return arg_table->arg_set_id()[*it_and_inserted.first];
+ return arg_table[*it_and_inserted.first].arg_set_id();
}
// Taking size() after the Insert() ensures that nothing has an id == 0
// (0 == kInvalidArgSetId).
- ArgSetId id = static_cast<uint32_t>(arg_row_for_hash_.size());
+ auto id = static_cast<uint32_t>(arg_row_for_hash_.size());
for (uint32_t i : valid_indexes) {
const auto& arg = args[i];
@@ -169,7 +174,7 @@
break;
}
row.value_type = storage_->GetIdForVariadicType(arg.value.type);
- arg_table->Insert(row);
+ arg_table.Insert(row);
}
return id;
}
diff --git a/src/trace_processor/importers/common/metadata_tracker.cc b/src/trace_processor/importers/common/metadata_tracker.cc
index 743e115..9ff55e5 100644
--- a/src/trace_processor/importers/common/metadata_tracker.cc
+++ b/src/trace_processor/importers/common/metadata_tracker.cc
@@ -15,18 +15,23 @@
*/
#include "src/trace_processor/importers/common/metadata_tracker.h"
+#include <cstddef>
+#include <cstdint>
+#include <optional>
+#include "perfetto/base/logging.h"
#include "perfetto/ext/base/crash_keys.h"
+#include "perfetto/trace_processor/basic_types.h"
#include "src/trace_processor/storage/metadata.h"
+#include "src/trace_processor/storage/trace_storage.h"
+#include "src/trace_processor/tables/metadata_tables_py.h"
#include "src/trace_processor/types/trace_processor_context.h"
+#include "src/trace_processor/types/variadic.h"
-namespace perfetto {
-namespace trace_processor {
+namespace perfetto::trace_processor {
namespace {
-
base::CrashKey g_crash_key_uuid("trace_uuid");
-
}
MetadataTracker::MetadataTracker(TraceStorage* storage) : storage_(storage) {
@@ -49,20 +54,23 @@
g_crash_key_uuid.Set(uuid_string_view);
}
- auto* metadata_table = storage_->mutable_metadata_table();
- uint32_t key_idx = static_cast<uint32_t>(key);
- std::optional<uint32_t> opt_row =
- metadata_table->name().IndexOf(metadata::kNames[key_idx]);
- if (opt_row) {
- WriteValue(*opt_row, value);
- return metadata_table->id()[*opt_row];
+ auto& metadata_table = *storage_->mutable_metadata_table();
+ auto key_idx = static_cast<uint32_t>(key);
+ auto name_id = storage_->string_pool().GetId(metadata::kNames[key_idx]);
+ if (name_id) {
+ for (auto it = metadata_table.IterateRows(); it; ++it) {
+ if (it.name() == *name_id) {
+ WriteValue(it.row_number().row_number(), value);
+ return it.id();
+ }
+ }
}
tables::MetadataTable::Row row;
row.name = key_ids_[key_idx];
row.key_type = key_type_ids_[static_cast<size_t>(metadata::KeyType::kSingle)];
- auto id_and_row = metadata_table->Insert(row);
+ auto id_and_row = metadata_table.Insert(row);
WriteValue(id_and_row.row, value);
return id_and_row.id;
}
@@ -71,19 +79,32 @@
// KeyType::kMulti not yet supported by this method:
PERFETTO_CHECK(metadata::kKeyTypes[key] == metadata::KeyType::kSingle);
- auto* metadata_table = storage_->mutable_metadata_table();
- uint32_t key_idx = static_cast<uint32_t>(key);
- std::optional<uint32_t> row =
- metadata_table->name().IndexOf(metadata::kNames[key_idx]);
- if (!row.has_value())
+ auto& metadata_table = *storage_->mutable_metadata_table();
+ auto key_idx = static_cast<uint32_t>(key);
+
+ auto key_id = storage_->string_pool().GetId(metadata::kNames[key_idx]);
+ if (!key_id) {
+ return std::nullopt;
+ }
+
+ std::optional<tables::MetadataTable::RowReference> row;
+ for (auto it = metadata_table.IterateRows(); it; ++it) {
+ if (key_id == it.name()) {
+ row = it.row_reference();
+ break;
+ }
+ }
+ if (!row.has_value()) {
return {};
+ }
auto value_type = metadata::kValueTypes[key];
switch (value_type) {
- case Variadic::kInt:
- return metadata_table->mutable_int_value()->Get(*row);
+ case Variadic::kInt: {
+ return SqlValue::Long(*row->int_value());
+ }
case Variadic::kString:
- return metadata_table->mutable_str_value()->Get(*row);
+ return SqlValue::String(storage_->GetString(*row->str_value()).c_str());
case Variadic::kNull:
return SqlValue();
case Variadic::kJson:
@@ -125,16 +146,17 @@
}
void MetadataTracker::WriteValue(uint32_t row, Variadic value) {
- auto* metadata_table = storage_->mutable_metadata_table();
+ auto& metadata_table = *storage_->mutable_metadata_table();
+ auto rr = metadata_table[row];
switch (value.type) {
case Variadic::Type::kInt:
- metadata_table->mutable_int_value()->Set(row, value.int_value);
+ rr.set_int_value(value.int_value);
break;
case Variadic::Type::kString:
- metadata_table->mutable_str_value()->Set(row, value.string_value);
+ rr.set_str_value(value.string_value);
break;
case Variadic::Type::kJson:
- metadata_table->mutable_str_value()->Set(row, value.json_value);
+ rr.set_str_value(value.json_value);
break;
case Variadic::Type::kBool:
case Variadic::Type::kPointer:
@@ -145,5 +167,4 @@
}
}
-} // namespace trace_processor
-} // namespace perfetto
+} // namespace perfetto::trace_processor
diff --git a/src/trace_processor/importers/common/process_tracker.cc b/src/trace_processor/importers/common/process_tracker.cc
index e292801..e1f9c6d 100644
--- a/src/trace_processor/importers/common/process_tracker.cc
+++ b/src/trace_processor/importers/common/process_tracker.cc
@@ -90,8 +90,8 @@
}
void ProcessTracker::EndThread(int64_t timestamp, uint32_t tid) {
- auto* thread_table = context_->storage->mutable_thread_table();
- auto* process_table = context_->storage->mutable_process_table();
+ auto& thread_table = *context_->storage->mutable_thread_table();
+ auto& process_table = *context_->storage->mutable_process_table();
// Don't bother creating a new thread if we're just going to
// end it straight away.
@@ -106,21 +106,28 @@
return;
UniqueTid utid = *opt_utid;
- thread_table->mutable_end_ts()->Set(utid, timestamp);
+
+ auto td = thread_table[utid];
+ td.set_end_ts(timestamp);
// Remove the thread from the list of threads being tracked as any event after
// this one should be ignored.
auto& vector = tids_[tid];
vector.erase(std::remove(vector.begin(), vector.end(), utid), vector.end());
- auto opt_upid = thread_table->upid()[utid];
- if (!opt_upid.has_value() || process_table->pid()[*opt_upid] != tid)
+ auto opt_upid = td.upid();
+ if (!opt_upid) {
return;
+ }
+ auto ps = process_table[*opt_upid];
+ if (ps.pid() != tid) {
+ return;
+ }
// If the process pid and thread tid are equal then, as is the main thread
// of the process, we should also finish the process itself.
- PERFETTO_DCHECK(thread_table->is_main_thread()[utid].value());
- process_table->mutable_end_ts()->Set(*opt_upid, timestamp);
+ PERFETTO_DCHECK(*td.is_main_thread());
+ ps.set_end_ts(timestamp);
pids_.Erase(tid);
}
@@ -129,16 +136,17 @@
if (!opt_utid)
return std::nullopt;
- auto* threads = context_->storage->mutable_thread_table();
+ auto& threads = *context_->storage->mutable_thread_table();
UniqueTid utid = *opt_utid;
+ auto rr = threads[utid];
// Ensure that the tid matches the tid we were looking for.
- PERFETTO_DCHECK(threads->tid()[utid] == tid);
+ PERFETTO_DCHECK(rr.tid() == tid);
// Ensure that the thread's machine ID matches the context's machine ID.
- PERFETTO_DCHECK(threads->machine_id()[utid] == context_->machine_id());
+ PERFETTO_DCHECK(rr.machine_id() == context_->machine_id());
// If the thread is being tracked by the process tracker, it should not be
// known to have ended.
- PERFETTO_DCHECK(!threads->end_ts()[utid].has_value());
+ PERFETTO_DCHECK(!rr.end_ts().has_value());
return utid;
}
@@ -162,7 +170,7 @@
if (thread_name_id.is_null())
return;
- auto* thread_table = context_->storage->mutable_thread_table();
+ auto& thread_table = *context_->storage->mutable_thread_table();
if (PERFETTO_UNLIKELY(thread_name_priorities_.size() <= utid)) {
// This condition can happen in a multi-machine tracing session:
// Machine 1 gets utid 0, 1
@@ -171,31 +179,33 @@
thread_name_priorities_.resize(utid + 1);
}
if (priority >= thread_name_priorities_[utid]) {
- thread_table->mutable_name()->Set(utid, thread_name_id);
+ thread_table[utid].set_name(thread_name_id);
thread_name_priorities_[utid] = priority;
}
}
bool ProcessTracker::IsThreadAlive(UniqueTid utid) {
- auto* threads = context_->storage->mutable_thread_table();
- auto* processes = context_->storage->mutable_process_table();
+ auto& threads = *context_->storage->mutable_thread_table();
+ auto& processes = *context_->storage->mutable_process_table();
// If the thread has an end ts, it's certainly dead.
- if (threads->end_ts()[utid].has_value())
+ auto rr = threads[utid];
+ if (rr.end_ts().has_value())
return false;
// If we don't know the parent process, we have to consider this thread alive.
- auto opt_current_upid = threads->upid()[utid];
+ auto opt_current_upid = rr.upid();
if (!opt_current_upid)
return true;
// If the process is already dead, the thread can't be alive.
UniquePid current_upid = *opt_current_upid;
- if (processes->end_ts()[current_upid].has_value())
+ auto prr = processes[current_upid];
+ if (prr.end_ts().has_value())
return false;
// If the process has been replaced in |pids_|, this thread is dead.
- uint32_t current_pid = processes->pid()[current_upid];
+ uint32_t current_pid = prr.pid();
auto* pid_it = pids_.Find(current_pid);
return !pid_it || *pid_it == current_upid;
}
@@ -203,8 +213,8 @@
std::optional<UniqueTid> ProcessTracker::GetThreadOrNull(
uint32_t tid,
std::optional<uint32_t> pid) {
- auto* threads = context_->storage->mutable_thread_table();
- auto* processes = context_->storage->mutable_process_table();
+ auto& threads = *context_->storage->mutable_thread_table();
+ auto& processes = *context_->storage->mutable_process_table();
auto* vector_it = tids_.Find(tid);
if (!vector_it)
@@ -215,22 +225,24 @@
const auto& vector = *vector_it;
for (auto it = vector.rbegin(); it != vector.rend(); it++) {
UniqueTid current_utid = *it;
+ auto rr = threads[current_utid];
// If we finished this thread, we should have removed it from the vector
// entirely.
- PERFETTO_DCHECK(!threads->end_ts()[current_utid].has_value());
+ PERFETTO_DCHECK(!rr.end_ts().has_value());
// If the thread is dead, ignore it.
if (!IsThreadAlive(current_utid))
continue;
// If we don't know the parent process, we have to choose this thread.
- auto opt_current_upid = threads->upid()[current_utid];
+ auto opt_current_upid = rr.upid();
if (!opt_current_upid)
return current_utid;
// We found a thread that matches both the tid and its parent pid.
- uint32_t current_pid = processes->pid()[*opt_current_upid];
+ auto prr = processes[*opt_current_upid];
+ uint32_t current_pid = prr.pid();
if (!pid || current_pid == *pid)
return current_utid;
}
@@ -238,24 +250,23 @@
}
UniqueTid ProcessTracker::UpdateThread(uint32_t tid, uint32_t pid) {
- auto* thread_table = context_->storage->mutable_thread_table();
+ auto& thread_table = *context_->storage->mutable_thread_table();
// Try looking for a thread that matches both tid and thread group id (pid).
std::optional<UniqueTid> opt_utid = GetThreadOrNull(tid, pid);
// If no matching thread was found, create a new one.
UniqueTid utid = opt_utid ? *opt_utid : StartNewThread(std::nullopt, tid);
- PERFETTO_DCHECK(thread_table->tid()[utid] == tid);
+ auto rr = thread_table[utid];
+ PERFETTO_DCHECK(rr.tid() == tid);
// Ensure that the thread's machine ID matches the context's machine ID.
- PERFETTO_DCHECK(thread_table->machine_id()[utid] == context_->machine_id());
+ PERFETTO_DCHECK(rr.machine_id() == context_->machine_id());
// Find matching process or create new one.
- if (!thread_table->upid()[utid].has_value()) {
+ if (!rr.upid().has_value()) {
AssociateThreadToProcess(utid, GetOrCreateProcess(pid));
}
-
- ResolvePendingAssociations(utid, *thread_table->upid()[utid]);
-
+ ResolvePendingAssociations(utid, *rr.upid());
return utid;
}
@@ -321,22 +332,23 @@
// process.
UniquePid upid = GetOrCreateProcess(pid);
- auto* process_table = context_->storage->mutable_process_table();
- auto* thread_table = context_->storage->mutable_thread_table();
+ auto& process_table = *context_->storage->mutable_process_table();
+ auto& thread_table = *context_->storage->mutable_thread_table();
- PERFETTO_DCHECK(!process_table->name()[upid].has_value());
- PERFETTO_DCHECK(!process_table->start_ts()[upid].has_value());
+ auto prr = process_table[upid];
+ PERFETTO_DCHECK(!prr.name().has_value());
+ PERFETTO_DCHECK(!prr.start_ts().has_value());
if (timestamp) {
- process_table->mutable_start_ts()->Set(upid, *timestamp);
+ prr.set_start_ts(*timestamp);
}
- process_table->mutable_name()->Set(upid, main_thread_name);
+ prr.set_name(main_thread_name);
if (parent_tid) {
UniqueTid parent_utid = GetOrCreateThread(*parent_tid);
- auto opt_parent_upid = thread_table->upid()[parent_utid];
+ auto opt_parent_upid = thread_table[parent_utid].upid();
if (opt_parent_upid.has_value()) {
- process_table->mutable_parent_upid()->Set(upid, *opt_parent_upid);
+ prr.set_parent_upid(*opt_parent_upid);
} else {
pending_parent_assocs_.emplace_back(parent_utid, upid);
}
@@ -354,13 +366,13 @@
}
UniquePid upid = GetOrCreateProcess(pid);
- auto* process_table = context_->storage->mutable_process_table();
+ auto& process_table = *context_->storage->mutable_process_table();
// If we both know the previous and current parent pid and the two are not
// matching, we must have died and restarted: create a new process.
+ auto prr = process_table[upid];
if (pupid) {
- std::optional<UniquePid> prev_parent_upid =
- process_table->parent_upid()[upid];
+ std::optional<UniquePid> prev_parent_upid = prr.parent_upid();
if (prev_parent_upid && prev_parent_upid != pupid) {
upid = StartNewProcess(std::nullopt, ppid, pid, kNullStringId,
ThreadNamePriority::kOther);
@@ -368,61 +380,68 @@
}
StringId proc_name_id = context_->storage->InternString(name);
- process_table->mutable_name()->Set(upid, proc_name_id);
- process_table->mutable_cmdline()->Set(
- upid, context_->storage->InternString(cmdline));
- if (pupid)
- process_table->mutable_parent_upid()->Set(upid, *pupid);
-
+ prr.set_name(proc_name_id);
+ prr.set_cmdline(context_->storage->InternString(cmdline));
+ if (pupid) {
+ prr.set_parent_upid(*pupid);
+ }
return upid;
}
void ProcessTracker::SetProcessUid(UniquePid upid, uint32_t uid) {
- auto* process_table = context_->storage->mutable_process_table();
- process_table->mutable_uid()->Set(upid, uid);
+ auto& process_table = *context_->storage->mutable_process_table();
+ auto rr = process_table[upid];
+ rr.set_uid(uid);
// The notion of the app ID (as derived from the uid) is defined in
// frameworks/base/core/java/android/os/UserHandle.java
- process_table->mutable_android_appid()->Set(upid, uid % 100000);
+ rr.set_android_appid(uid % 100000);
}
void ProcessTracker::SetProcessNameIfUnset(UniquePid upid,
StringId process_name_id) {
- auto* process_table = context_->storage->mutable_process_table();
- if (!process_table->name()[upid].has_value())
- process_table->mutable_name()->Set(upid, process_name_id);
+ auto& pt = *context_->storage->mutable_process_table();
+ if (auto rr = pt[upid]; !rr.name().has_value()) {
+ rr.set_name(process_name_id);
+ }
}
void ProcessTracker::SetStartTsIfUnset(UniquePid upid,
int64_t start_ts_nanoseconds) {
- auto* process_table = context_->storage->mutable_process_table();
- if (!process_table->start_ts()[upid].has_value())
- process_table->mutable_start_ts()->Set(upid, start_ts_nanoseconds);
+ auto& pt = *context_->storage->mutable_process_table();
+ if (auto rr = pt[upid]; !rr.start_ts().has_value()) {
+ rr.set_start_ts(start_ts_nanoseconds);
+ }
}
void ProcessTracker::UpdateThreadNameAndMaybeProcessName(
uint32_t tid,
StringId thread_name,
ThreadNamePriority priority) {
- auto* thread_table = context_->storage->mutable_thread_table();
- auto* process_table = context_->storage->mutable_process_table();
+ auto& tt = *context_->storage->mutable_thread_table();
+ auto& pt = *context_->storage->mutable_process_table();
UniqueTid utid = UpdateThreadName(tid, thread_name, priority);
- std::optional<UniquePid> opt_upid = thread_table->upid()[utid];
- if (opt_upid.has_value() && process_table->pid()[*opt_upid] == tid) {
- PERFETTO_DCHECK(thread_table->is_main_thread()[utid]);
- process_table->mutable_name()->Set(*opt_upid, thread_name);
+ auto trr = tt[utid];
+ std::optional<UniquePid> opt_upid = trr.upid();
+ if (!opt_upid.has_value()) {
+ return;
+ }
+ auto prr = pt[*opt_upid];
+ if (prr.pid() == tid) {
+ PERFETTO_DCHECK(trr.is_main_thread());
+ prr.set_name(thread_name);
}
}
UniquePid ProcessTracker::GetOrCreateProcess(uint32_t pid) {
- auto* process_table = context_->storage->mutable_process_table();
+ auto& process_table = *context_->storage->mutable_process_table();
// If the insertion succeeds, we'll fill the upid below.
auto it_and_ins = pids_.Insert(pid, UniquePid{0});
if (!it_and_ins.second) {
// Ensure that the process has not ended.
- PERFETTO_DCHECK(!process_table->end_ts()[*it_and_ins.first].has_value());
+ PERFETTO_DCHECK(!process_table[*it_and_ins.first].end_ts().has_value());
return *it_and_ins.first;
}
@@ -430,7 +449,7 @@
row.pid = pid;
row.machine_id = context_->machine_id();
- UniquePid upid = process_table->Insert(row).row;
+ UniquePid upid = process_table.Insert(row).row;
*it_and_ins.first = upid; // Update the newly inserted hashmap entry.
// Create an entry for the main thread.
@@ -442,14 +461,16 @@
}
void ProcessTracker::AssociateThreads(UniqueTid utid1, UniqueTid utid2) {
- auto* tt = context_->storage->mutable_thread_table();
+ auto& tt = *context_->storage->mutable_thread_table();
// First of all check if one of the two threads is already bound to a process.
// If that is the case, map the other thread to the same process and resolve
// recursively any associations pending on the other thread.
- auto opt_upid1 = tt->upid()[utid1];
- auto opt_upid2 = tt->upid()[utid2];
+ auto rr1 = tt[utid1];
+ auto rr2 = tt[utid2];
+ auto opt_upid1 = rr1.upid();
+ auto opt_upid2 = rr2.upid();
if (opt_upid1.has_value() && !opt_upid2.has_value()) {
AssociateThreadToProcess(utid2, *opt_upid1);
@@ -466,7 +487,7 @@
if (opt_upid1.has_value() && opt_upid1 != opt_upid2) {
// Cannot associate two threads that belong to two different processes.
PERFETTO_ELOG("Process tracker failure. Cannot associate threads %u, %u",
- tt->tid()[utid1], tt->tid()[utid2]);
+ rr1.tid(), rr2.tid());
context_->storage->IncrementStats(stats::process_tracker_errors);
return;
}
@@ -476,9 +497,11 @@
void ProcessTracker::ResolvePendingAssociations(UniqueTid utid_arg,
UniquePid upid) {
- auto* tt = context_->storage->mutable_thread_table();
- auto* pt = context_->storage->mutable_process_table();
- PERFETTO_DCHECK(tt->upid()[utid_arg] == upid);
+ auto& tt = *context_->storage->mutable_thread_table();
+ auto& pt = *context_->storage->mutable_process_table();
+
+ auto trr = tt[utid_arg];
+ PERFETTO_DCHECK(trr.upid() == upid);
std::vector<UniqueTid> resolved_utids;
resolved_utids.emplace_back(utid_arg);
@@ -498,9 +521,9 @@
PERFETTO_DCHECK(child_upid != upid);
// Set the parent pid of the other process
- PERFETTO_DCHECK(!pt->parent_upid()[child_upid] ||
- pt->parent_upid()[child_upid] == upid);
- pt->mutable_parent_upid()->Set(child_upid, upid);
+ auto crr = pt[child_upid];
+ PERFETTO_DCHECK(!crr.parent_upid() || crr.parent_upid() == upid);
+ crr.set_parent_upid(upid);
// Erase the pair. The |pending_parent_assocs_| vector is not sorted and
// swapping a std::pair<uint32_t, uint32_t> is cheap.
@@ -523,8 +546,8 @@
PERFETTO_DCHECK(other_utid != utid);
// Update the other thread and associated it to the same process.
- PERFETTO_DCHECK(!tt->upid()[other_utid] ||
- tt->upid()[other_utid] == upid);
+ auto orr = tt[other_utid];
+ PERFETTO_DCHECK(!orr.upid() || orr.upid() == upid);
AssociateThreadToProcess(other_utid, upid);
// Swap the current element to the end of the list and move the end
@@ -545,11 +568,13 @@
}
void ProcessTracker::AssociateThreadToProcess(UniqueTid utid, UniquePid upid) {
- auto* thread_table = context_->storage->mutable_thread_table();
- thread_table->mutable_upid()->Set(utid, upid);
- auto* process_table = context_->storage->mutable_process_table();
- bool main_thread = thread_table->tid()[utid] == process_table->pid()[upid];
- thread_table->mutable_is_main_thread()->Set(utid, main_thread);
+ auto& thread_table = *context_->storage->mutable_thread_table();
+ auto& process_table = *context_->storage->mutable_process_table();
+
+ auto trr = thread_table[utid];
+ auto prr = process_table[upid];
+ trr.set_upid(upid);
+ trr.set_is_main_thread(trr.tid() == prr.pid());
}
void ProcessTracker::SetPidZeroIsUpidZeroIdleProcess() {
diff --git a/src/trace_processor/importers/common/process_tracker_unittest.cc b/src/trace_processor/importers/common/process_tracker_unittest.cc
index e4f06ce..361d388 100644
--- a/src/trace_processor/importers/common/process_tracker_unittest.cc
+++ b/src/trace_processor/importers/common/process_tracker_unittest.cc
@@ -16,15 +16,17 @@
#include "src/trace_processor/importers/common/process_tracker.h"
+#include <memory>
#include <optional>
-#include "perfetto/base/logging.h"
+#include "perfetto/ext/base/string_view.h"
#include "src/trace_processor/importers/common/args_tracker.h"
#include "src/trace_processor/importers/common/event_tracker.h"
+#include "src/trace_processor/importers/common/global_args_tracker.h"
+#include "src/trace_processor/storage/trace_storage.h"
#include "test/gtest_and_gmock.h"
-namespace perfetto {
-namespace trace_processor {
+namespace perfetto::trace_processor {
namespace {
using ::testing::_;
@@ -34,12 +36,12 @@
class ProcessTrackerTest : public ::testing::Test {
public:
ProcessTrackerTest() {
- context.storage.reset(new TraceStorage());
- context.global_args_tracker.reset(
- new GlobalArgsTracker(context.storage.get()));
- context.args_tracker.reset(new ArgsTracker(&context));
- context.process_tracker.reset(new ProcessTracker(&context));
- context.event_tracker.reset(new EventTracker(&context));
+ context.storage = std::make_shared<TraceStorage>();
+ context.global_args_tracker =
+ std::make_unique<GlobalArgsTracker>(context.storage.get());
+ context.args_tracker = std::make_unique<ArgsTracker>(&context);
+ context.process_tracker = std::make_unique<ProcessTracker>(&context);
+ context.event_tracker = std::make_unique<EventTracker>(&context);
}
protected:
@@ -62,7 +64,7 @@
auto upid = context.process_tracker->StartNewProcess(
1000, 0u, 123, kNullStringId, ThreadNamePriority::kFtrace);
ASSERT_EQ(context.process_tracker->GetOrCreateProcess(123), upid);
- ASSERT_EQ(context.storage->process_table().start_ts()[upid], 1000);
+ ASSERT_EQ(context.storage->process_table()[upid].start_ts(), 1000);
}
TEST_F(ProcessTrackerTest, PushTwoProcessEntries_SamePidAndName) {
@@ -88,9 +90,8 @@
TEST_F(ProcessTrackerTest, AddProcessEntry_CorrectName) {
context.process_tracker->SetProcessMetadata(1, std::nullopt, "test",
base::StringView());
- auto name = context.storage->process_table().name().GetString(1);
-
- ASSERT_EQ(name, "test");
+ auto name = context.storage->process_table()[1].name();
+ ASSERT_EQ(context.storage->GetString(*name), "test");
}
TEST_F(ProcessTrackerTest, UpdateThreadCreate) {
@@ -101,7 +102,7 @@
auto tid_it = context.process_tracker->UtidsForTidForTesting(12);
ASSERT_NE(tid_it.first, tid_it.second);
- ASSERT_EQ(context.storage->thread_table().upid()[1].value(), 1u);
+ ASSERT_EQ(context.storage->thread_table()[1].upid().value(), 1u);
auto opt_upid = context.process_tracker->UpidForPidForTesting(2);
ASSERT_TRUE(opt_upid.has_value());
ASSERT_EQ(context.storage->process_table().row_count(), 2u);
@@ -130,8 +131,8 @@
TEST_F(ProcessTrackerTest, Cmdline) {
UniquePid upid = context.process_tracker->SetProcessMetadata(
1, std::nullopt, "test", "cmdline blah");
- ASSERT_EQ(context.storage->process_table().cmdline().GetString(upid),
- "cmdline blah");
+ auto cmdline = *context.storage->process_table()[upid].cmdline();
+ ASSERT_EQ(context.storage->GetString(cmdline), "cmdline blah");
}
TEST_F(ProcessTrackerTest, UpdateThreadName) {
@@ -142,19 +143,19 @@
context.process_tracker->UpdateThreadName(1, name1,
ThreadNamePriority::kFtrace);
ASSERT_EQ(context.storage->thread_table().row_count(), 2u);
- ASSERT_EQ(context.storage->thread_table().name()[1], name1);
+ ASSERT_EQ(context.storage->thread_table()[1].name(), name1);
context.process_tracker->UpdateThreadName(1, name2,
ThreadNamePriority::kProcessTree);
// The priority is higher: the name should change.
ASSERT_EQ(context.storage->thread_table().row_count(), 2u);
- ASSERT_EQ(context.storage->thread_table().name()[1], name2);
+ ASSERT_EQ(context.storage->thread_table()[1].name(), name2);
context.process_tracker->UpdateThreadName(1, name3,
ThreadNamePriority::kFtrace);
// The priority is lower: the name should stay the same.
ASSERT_EQ(context.storage->thread_table().row_count(), 2u);
- ASSERT_EQ(context.storage->thread_table().name()[1], name2);
+ ASSERT_EQ(context.storage->thread_table()[1].name(), name2);
}
TEST_F(ProcessTrackerTest, SetStartTsIfUnset) {
@@ -162,10 +163,10 @@
/*timestamp=*/std::nullopt, 0u, 123, kNullStringId,
ThreadNamePriority::kFtrace);
context.process_tracker->SetStartTsIfUnset(upid, 1000);
- ASSERT_EQ(context.storage->process_table().start_ts()[upid], 1000);
+ ASSERT_EQ(context.storage->process_table()[upid].start_ts(), 1000);
context.process_tracker->SetStartTsIfUnset(upid, 3000);
- ASSERT_EQ(context.storage->process_table().start_ts()[upid], 1000);
+ ASSERT_EQ(context.storage->process_table()[upid].start_ts(), 1000);
}
TEST_F(ProcessTrackerTest, PidReuseAfterExplicitEnd) {
@@ -264,5 +265,4 @@
}
} // namespace
-} // namespace trace_processor
-} // namespace perfetto
+} // namespace perfetto::trace_processor
diff --git a/src/trace_processor/importers/common/sched_event_tracker.h b/src/trace_processor/importers/common/sched_event_tracker.h
index ff4f537..7a632eb 100644
--- a/src/trace_processor/importers/common/sched_event_tracker.h
+++ b/src/trace_processor/importers/common/sched_event_tracker.h
@@ -17,15 +17,17 @@
#ifndef SRC_TRACE_PROCESSOR_IMPORTERS_COMMON_SCHED_EVENT_TRACKER_H_
#define SRC_TRACE_PROCESSOR_IMPORTERS_COMMON_SCHED_EVENT_TRACKER_H_
-#include "src/trace_processor/importers/common/event_tracker.h"
+#include <cstdint>
+#include "perfetto/base/logging.h"
+#include "perfetto/public/compiler.h"
#include "src/trace_processor/importers/common/cpu_tracker.h"
+#include "src/trace_processor/importers/common/event_tracker.h"
#include "src/trace_processor/storage/trace_storage.h"
#include "src/trace_processor/types/destructible.h"
#include "src/trace_processor/types/trace_processor_context.h"
-namespace perfetto {
-namespace trace_processor {
+namespace perfetto::trace_processor {
// Tracks per-cpu scheduling events, storing them as slices in the |sched|
// table.
@@ -51,7 +53,7 @@
auto row_and_id = sched->Insert(
{ts, /* duration */ -1, next_utid, kNullStringId, next_prio, ucpu});
SchedId sched_id = row_and_id.id;
- return *sched->id().IndexOf(sched_id);
+ return sched->FindById(sched_id)->ToRowNumber().row_number();
}
PERFETTO_ALWAYS_INLINE
@@ -75,21 +77,15 @@
int64_t ts,
StringId prev_state) {
auto* slices = context_->storage->mutable_sched_slice_table();
-
- int64_t duration = ts - slices->ts()[pending_slice_idx];
- slices->mutable_dur()->Set(pending_slice_idx, duration);
-
- // We store the state as a uint16 as we only consider values up to 2048
- // when unpacking the information inside; this allows savings of 48 bits
- // per slice.
- slices->mutable_end_state()->Set(pending_slice_idx, prev_state);
+ auto r = (*slices)[pending_slice_idx];
+ r.set_dur(ts - r.ts());
+ r.set_end_state(prev_state);
}
private:
TraceProcessorContext* const context_;
};
-} // namespace trace_processor
-} // namespace perfetto
+} // namespace perfetto::trace_processor
#endif // SRC_TRACE_PROCESSOR_IMPORTERS_COMMON_SCHED_EVENT_TRACKER_H_
diff --git a/src/trace_processor/importers/common/slice_tracker_unittest.cc b/src/trace_processor/importers/common/slice_tracker_unittest.cc
index 73fa8bf..b999ca1 100644
--- a/src/trace_processor/importers/common/slice_tracker_unittest.cc
+++ b/src/trace_processor/importers/common/slice_tracker_unittest.cc
@@ -14,7 +14,11 @@
* limitations under the License.
*/
+#include <cstdint>
#include <memory>
+#include <optional>
+#include <ostream>
+#include <tuple>
#include <vector>
#include "src/trace_processor/importers/common/args_tracker.h"
@@ -22,11 +26,12 @@
#include "src/trace_processor/importers/common/slice_tracker.h"
#include "src/trace_processor/importers/common/slice_translation_table.h"
#include "src/trace_processor/storage/trace_storage.h"
+#include "src/trace_processor/tables/slice_tables_py.h"
#include "src/trace_processor/types/trace_processor_context.h"
+#include "src/trace_processor/types/variadic.h"
#include "test/gtest_and_gmock.h"
-namespace perfetto {
-namespace trace_processor {
+namespace perfetto::trace_processor {
namespace {
using ::testing::ElementsAre;
@@ -47,8 +52,8 @@
std::vector<SliceInfo> ToSliceInfo(const tables::SliceTable& slices) {
std::vector<SliceInfo> infos;
- for (uint32_t i = 0; i < slices.row_count(); i++) {
- infos.emplace_back(SliceInfo{slices.ts()[i], slices.dur()[i]});
+ for (auto it = slices.IterateRows(); it; ++it) {
+ infos.emplace_back(SliceInfo{it.ts(), it.dur()});
}
return infos;
}
@@ -80,13 +85,13 @@
const auto& slices = context_.storage->slice_table();
EXPECT_EQ(slices.row_count(), 1u);
- EXPECT_EQ(slices.ts()[0], 2);
- EXPECT_EQ(slices.dur()[0], 8);
- EXPECT_EQ(slices.track_id()[0], track);
- EXPECT_EQ(slices.category()[0].value_or(kNullStringId).raw_id(), 0u);
- EXPECT_EQ(slices.name()[0].value_or(kNullStringId).raw_id(), 1u);
- EXPECT_EQ(slices.depth()[0], 0u);
- EXPECT_EQ(slices.arg_set_id()[0], kInvalidArgSetId);
+ EXPECT_EQ(slices[0].ts(), 2);
+ EXPECT_EQ(slices[0].dur(), 8);
+ EXPECT_EQ(slices[0].track_id(), track);
+ EXPECT_EQ(slices[0].category().value_or(kNullStringId).raw_id(), 0u);
+ EXPECT_EQ(slices[0].name().value_or(kNullStringId).raw_id(), 1u);
+ EXPECT_EQ(slices[0].depth(), 0u);
+ EXPECT_EQ(slices[0].arg_set_id(), kInvalidArgSetId);
}
TEST_F(SliceTrackerTest, OneSliceDetailedWithTranslatedName) {
@@ -103,14 +108,14 @@
const auto& slices = context_.storage->slice_table();
EXPECT_EQ(slices.row_count(), 1u);
- EXPECT_EQ(slices.ts()[0], 2);
- EXPECT_EQ(slices.dur()[0], 8);
- EXPECT_EQ(slices.track_id()[0], track);
- EXPECT_EQ(slices.category()[0].value_or(kNullStringId).raw_id(), 0u);
- EXPECT_EQ(slices.name()[0].value_or(kNullStringId).raw_id(),
+ EXPECT_EQ(slices[0].ts(), 2);
+ EXPECT_EQ(slices[0].dur(), 8);
+ EXPECT_EQ(slices[0].track_id(), track);
+ EXPECT_EQ(slices[0].category().value_or(kNullStringId).raw_id(), 0u);
+ EXPECT_EQ(slices[0].name().value_or(kNullStringId).raw_id(),
mapped_name.raw_id());
- EXPECT_EQ(slices.depth()[0], 0u);
- EXPECT_EQ(slices.arg_set_id()[0], kInvalidArgSetId);
+ EXPECT_EQ(slices[0].depth(), 0u);
+ EXPECT_EQ(slices[0].arg_set_id(), kInvalidArgSetId);
}
TEST_F(SliceTrackerTest, NegativeTimestamps) {
@@ -124,13 +129,15 @@
const auto& slices = context_.storage->slice_table();
EXPECT_EQ(slices.row_count(), 1u);
- EXPECT_EQ(slices.ts()[0], -1000);
- EXPECT_EQ(slices.dur()[0], 499);
- EXPECT_EQ(slices.track_id()[0], track);
- EXPECT_EQ(slices.category()[0].value_or(kNullStringId).raw_id(), 0u);
- EXPECT_EQ(slices.name()[0].value_or(kNullStringId).raw_id(), 1u);
- EXPECT_EQ(slices.depth()[0], 0u);
- EXPECT_EQ(slices.arg_set_id()[0], kInvalidArgSetId);
+
+ auto rr = slices[0];
+ EXPECT_EQ(rr.ts(), -1000);
+ EXPECT_EQ(rr.dur(), 499);
+ EXPECT_EQ(rr.track_id(), track);
+ EXPECT_EQ(rr.category().value_or(kNullStringId).raw_id(), 0u);
+ EXPECT_EQ(rr.name().value_or(kNullStringId).raw_id(), 1u);
+ EXPECT_EQ(rr.depth(), 0u);
+ EXPECT_EQ(rr.arg_set_id(), kInvalidArgSetId);
}
TEST_F(SliceTrackerTest, OneSliceWithArgs) {
@@ -142,35 +149,39 @@
[](ArgsTracker::BoundInserter* inserter) {
inserter->AddArg(/*flat_key=*/StringId::Raw(1),
/*key=*/StringId::Raw(2),
- /*value=*/Variadic::Integer(10));
+ /*v=*/Variadic::Integer(10));
});
tracker.End(10 /*ts*/, track, kNullStringId /*cat*/,
StringId::Raw(1) /*name*/,
[](ArgsTracker::BoundInserter* inserter) {
inserter->AddArg(/*flat_key=*/StringId::Raw(3),
/*key=*/StringId::Raw(4),
- /*value=*/Variadic::Integer(20));
+ /*v=*/Variadic::Integer(20));
});
const auto& slices = context_.storage->slice_table();
EXPECT_EQ(slices.row_count(), 1u);
- EXPECT_EQ(slices.ts()[0], 2);
- EXPECT_EQ(slices.dur()[0], 8);
- EXPECT_EQ(slices.track_id()[0], track);
- EXPECT_EQ(slices.category()[0].value_or(kNullStringId).raw_id(), 0u);
- EXPECT_EQ(slices.name()[0].value_or(kNullStringId).raw_id(), 1u);
- EXPECT_EQ(slices.depth()[0], 0u);
- auto set_id = slices.arg_set_id()[0];
+
+ auto sr = slices[0];
+ EXPECT_EQ(sr.ts(), 2);
+ EXPECT_EQ(sr.dur(), 8);
+ EXPECT_EQ(sr.track_id(), track);
+ EXPECT_EQ(sr.category().value_or(kNullStringId).raw_id(), 0u);
+ EXPECT_EQ(sr.name().value_or(kNullStringId).raw_id(), 1u);
+ EXPECT_EQ(sr.depth(), 0u);
+ auto set_id = sr.arg_set_id();
const auto& args = context_.storage->arg_table();
- EXPECT_EQ(args.arg_set_id()[0], set_id);
- EXPECT_EQ(args.flat_key()[0].raw_id(), 1u);
- EXPECT_EQ(args.key()[0].raw_id(), 2u);
- EXPECT_EQ(args.int_value()[0], 10);
- EXPECT_EQ(args.arg_set_id()[1], set_id);
- EXPECT_EQ(args.flat_key()[1].raw_id(), 3u);
- EXPECT_EQ(args.key()[1].raw_id(), 4u);
- EXPECT_EQ(args.int_value()[1], 20);
+ auto ar0 = args[0];
+ auto ar1 = args[1];
+ EXPECT_EQ(ar0.arg_set_id(), set_id);
+ EXPECT_EQ(ar0.flat_key().raw_id(), 1u);
+ EXPECT_EQ(ar0.key().raw_id(), 2u);
+ EXPECT_EQ(ar0.int_value(), 10);
+ EXPECT_EQ(ar1.arg_set_id(), set_id);
+ EXPECT_EQ(ar1.flat_key().raw_id(), 3u);
+ EXPECT_EQ(ar1.key().raw_id(), 4u);
+ EXPECT_EQ(ar1.int_value(), 20);
}
TEST_F(SliceTrackerTest, OneSliceWithArgsWithTranslatedName) {
@@ -186,35 +197,38 @@
[](ArgsTracker::BoundInserter* inserter) {
inserter->AddArg(/*flat_key=*/StringId::Raw(1),
/*key=*/StringId::Raw(2),
- /*value=*/Variadic::Integer(10));
+ /*v=*/Variadic::Integer(10));
});
tracker.End(10 /*ts*/, track, kNullStringId /*cat*/, raw_name /*name*/,
[](ArgsTracker::BoundInserter* inserter) {
inserter->AddArg(/*flat_key=*/StringId::Raw(3),
/*key=*/StringId::Raw(4),
- /*value=*/Variadic::Integer(20));
+ /*v=*/Variadic::Integer(20));
});
const auto& slices = context_.storage->slice_table();
EXPECT_EQ(slices.row_count(), 1u);
- EXPECT_EQ(slices.ts()[0], 2);
- EXPECT_EQ(slices.dur()[0], 8);
- EXPECT_EQ(slices.track_id()[0], track);
- EXPECT_EQ(slices.category()[0].value_or(kNullStringId).raw_id(), 0u);
- EXPECT_EQ(slices.name()[0].value_or(kNullStringId).raw_id(),
- mapped_name.raw_id());
- EXPECT_EQ(slices.depth()[0], 0u);
- auto set_id = slices.arg_set_id()[0];
+
+ auto sr = slices[0];
+ EXPECT_EQ(sr.ts(), 2);
+ EXPECT_EQ(sr.dur(), 8);
+ EXPECT_EQ(sr.track_id(), track);
+ EXPECT_EQ(sr.category().value_or(kNullStringId).raw_id(), 0u);
+ EXPECT_EQ(sr.name().value_or(kNullStringId).raw_id(), mapped_name.raw_id());
+ EXPECT_EQ(sr.depth(), 0u);
+ auto set_id = sr.arg_set_id();
const auto& args = context_.storage->arg_table();
- EXPECT_EQ(args.arg_set_id()[0], set_id);
- EXPECT_EQ(args.flat_key()[0].raw_id(), 1u);
- EXPECT_EQ(args.key()[0].raw_id(), 2u);
- EXPECT_EQ(args.int_value()[0], 10);
- EXPECT_EQ(args.arg_set_id()[1], set_id);
- EXPECT_EQ(args.flat_key()[1].raw_id(), 3u);
- EXPECT_EQ(args.key()[1].raw_id(), 4u);
- EXPECT_EQ(args.int_value()[1], 20);
+ auto ar0 = args[0];
+ auto ar1 = args[1];
+ EXPECT_EQ(ar0.arg_set_id(), set_id);
+ EXPECT_EQ(ar0.flat_key().raw_id(), 1u);
+ EXPECT_EQ(ar0.key().raw_id(), 2u);
+ EXPECT_EQ(ar0.int_value(), 10);
+ EXPECT_EQ(ar1.arg_set_id(), set_id);
+ EXPECT_EQ(ar1.flat_key().raw_id(), 3u);
+ EXPECT_EQ(ar1.key().raw_id(), 4u);
+ EXPECT_EQ(ar1.int_value(), 20);
}
TEST_F(SliceTrackerTest, TwoSliceDetailed) {
@@ -232,24 +246,25 @@
EXPECT_EQ(slices.row_count(), 2u);
- uint32_t idx = 0;
- EXPECT_EQ(slices.ts()[idx], 2);
- EXPECT_EQ(slices.dur()[idx], 8);
- EXPECT_EQ(slices.track_id()[idx], track);
- EXPECT_EQ(slices.category()[idx].value_or(kNullStringId).raw_id(), 0u);
- EXPECT_EQ(slices.name()[idx].value_or(kNullStringId).raw_id(), 1u);
- EXPECT_EQ(slices.depth()[idx++], 0u);
+ auto sr0 = slices[0];
+ EXPECT_EQ(sr0.ts(), 2);
+ EXPECT_EQ(sr0.dur(), 8);
+ EXPECT_EQ(sr0.track_id(), track);
+ EXPECT_EQ(sr0.category().value_or(kNullStringId).raw_id(), 0u);
+ EXPECT_EQ(sr0.name().value_or(kNullStringId).raw_id(), 1u);
+ EXPECT_EQ(sr0.depth(), 0u);
+ EXPECT_EQ(sr0.parent_stack_id(), 0);
- EXPECT_EQ(slices.ts()[idx], 3);
- EXPECT_EQ(slices.dur()[idx], 2);
- EXPECT_EQ(slices.track_id()[idx], track);
- EXPECT_EQ(slices.category()[idx].value_or(kNullStringId).raw_id(), 0u);
- EXPECT_EQ(slices.name()[idx].value_or(kNullStringId).raw_id(), 2u);
- EXPECT_EQ(slices.depth()[idx], 1u);
+ auto sr1 = slices[1];
+ EXPECT_EQ(sr1.ts(), 3);
+ EXPECT_EQ(sr1.dur(), 2);
+ EXPECT_EQ(sr1.track_id(), track);
+ EXPECT_EQ(sr1.category().value_or(kNullStringId).raw_id(), 0u);
+ EXPECT_EQ(sr1.name().value_or(kNullStringId).raw_id(), 2u);
+ EXPECT_EQ(sr1.depth(), 1u);
+ EXPECT_NE(sr1.stack_id(), 0);
- EXPECT_EQ(slices.parent_stack_id()[0], 0);
- EXPECT_EQ(slices.stack_id()[0], slices.parent_stack_id()[1]);
- EXPECT_NE(slices.stack_id()[1], 0);
+ EXPECT_EQ(sr0.stack_id(), sr1.parent_stack_id());
}
TEST_F(SliceTrackerTest, Scoped) {
@@ -297,8 +312,8 @@
tracker.End(150, track);
tracker.End(200, track);
- SliceId parent = context_.storage->slice_table().id()[0];
- SliceId child = context_.storage->slice_table().id()[1];
+ SliceId parent = context_.storage->slice_table()[0].id();
+ SliceId child = context_.storage->slice_table()[1].id();
EXPECT_THAT(context_.storage->slice_table().parent_id().ToVectorForTesting(),
ElementsAre(std::nullopt, parent, child));
}
@@ -352,16 +367,17 @@
tracker.End(10 /*ts*/, track_a);
tracker.FlushPendingSlices();
- auto slices = ToSliceInfo(context_.storage->slice_table());
+ const auto& table = context_.storage->slice_table();
+ auto slices = ToSliceInfo(table);
EXPECT_THAT(slices,
ElementsAre(SliceInfo{0, 10}, SliceInfo{2, 6}, SliceInfo{3, 4}));
- EXPECT_EQ(context_.storage->slice_table().track_id()[0], track_a);
- EXPECT_EQ(context_.storage->slice_table().track_id()[1], track_b);
- EXPECT_EQ(context_.storage->slice_table().track_id()[2], track_b);
- EXPECT_EQ(context_.storage->slice_table().depth()[0], 0u);
- EXPECT_EQ(context_.storage->slice_table().depth()[1], 0u);
- EXPECT_EQ(context_.storage->slice_table().depth()[2], 1u);
+ EXPECT_EQ(table[0].track_id(), track_a);
+ EXPECT_EQ(table[1].track_id(), track_b);
+ EXPECT_EQ(table[2].track_id(), track_b);
+ EXPECT_EQ(table[0].depth(), 0u);
+ EXPECT_EQ(table[1].depth(), 0u);
+ EXPECT_EQ(table[2].depth(), 1u);
}
TEST_F(SliceTrackerTest, EndEventOutOfOrder) {
@@ -401,15 +417,16 @@
tracker.FlushPendingSlices();
- auto slices = ToSliceInfo(context_.storage->slice_table());
+ const auto& st = context_.storage->slice_table();
+ auto slices = ToSliceInfo(st);
EXPECT_THAT(slices, ElementsAre(SliceInfo{50, 100}, SliceInfo{100, 50},
SliceInfo{450, 100}, SliceInfo{800, 200},
SliceInfo{1100, -1}, SliceInfo{1300, 0 - 1}));
- EXPECT_EQ(context_.storage->slice_table().depth()[0], 0u);
- EXPECT_EQ(context_.storage->slice_table().depth()[1], 1u);
- EXPECT_EQ(context_.storage->slice_table().depth()[2], 0u);
- EXPECT_EQ(context_.storage->slice_table().depth()[3], 0u);
+ EXPECT_EQ(st[0].depth(), 0u);
+ EXPECT_EQ(st[1].depth(), 1u);
+ EXPECT_EQ(st[2].depth(), 0u);
+ EXPECT_EQ(st[3].depth(), 0u);
}
TEST_F(SliceTrackerTest, GetTopmostSliceOnTrack) {
@@ -421,12 +438,12 @@
EXPECT_EQ(tracker.GetTopmostSliceOnTrack(track), std::nullopt);
tracker.Begin(100, track, StringId::Raw(11), StringId::Raw(11));
- SliceId slice1 = context_.storage->slice_table().id()[0];
+ SliceId slice1 = context_.storage->slice_table()[0].id();
EXPECT_EQ(tracker.GetTopmostSliceOnTrack(track).value(), slice1);
tracker.Begin(120, track, StringId::Raw(22), StringId::Raw(22));
- SliceId slice2 = context_.storage->slice_table().id()[1];
+ SliceId slice2 = context_.storage->slice_table()[1].id();
EXPECT_EQ(tracker.GetTopmostSliceOnTrack(track).value(), slice2);
@@ -458,22 +475,21 @@
EXPECT_TRUE(slice_records.empty());
tracker.Begin(100, track1, StringId::Raw(11), StringId::Raw(11));
- SliceId slice1 = context_.storage->slice_table().id()[0];
+ SliceId slice1 = context_.storage->slice_table()[0].id();
EXPECT_THAT(track_records, ElementsAre(TrackId{1u}));
EXPECT_THAT(slice_records, ElementsAre(slice1));
tracker.Begin(120, track2, StringId::Raw(22), StringId::Raw(22));
- SliceId slice2 = context_.storage->slice_table().id()[1];
+ SliceId slice2 = context_.storage->slice_table()[1].id();
EXPECT_THAT(track_records, ElementsAre(TrackId{1u}, TrackId{2u}));
EXPECT_THAT(slice_records, ElementsAre(slice1, slice2));
tracker.Begin(330, track1, StringId::Raw(33), StringId::Raw(33));
- SliceId slice3 = context_.storage->slice_table().id()[2];
+ SliceId slice3 = context_.storage->slice_table()[2].id();
EXPECT_THAT(track_records,
ElementsAre(TrackId{1u}, TrackId{2u}, TrackId{1u}));
EXPECT_THAT(slice_records, ElementsAre(slice1, slice2, slice3));
}
} // namespace
-} // namespace trace_processor
-} // namespace perfetto
+} // namespace perfetto::trace_processor
diff --git a/src/trace_processor/importers/common/track_tracker.cc b/src/trace_processor/importers/common/track_tracker.cc
index 5f74ad5..9d32e04 100644
--- a/src/trace_processor/importers/common/track_tracker.cc
+++ b/src/trace_processor/importers/common/track_tracker.cc
@@ -16,14 +16,18 @@
#include "src/trace_processor/importers/common/track_tracker.h"
+#include <cstdint>
#include <optional>
+#include <utility>
#include "src/trace_processor/importers/common/args_tracker.h"
#include "src/trace_processor/importers/common/cpu_tracker.h"
#include "src/trace_processor/importers/common/process_track_translation_table.h"
#include "src/trace_processor/storage/trace_storage.h"
#include "src/trace_processor/tables/profiler_tables_py.h"
+#include "src/trace_processor/tables/track_tables_py.h"
#include "src/trace_processor/types/trace_processor_context.h"
+#include "src/trace_processor/types/variadic.h"
namespace perfetto {
namespace trace_processor {
@@ -164,10 +168,11 @@
if (name != kNullStringId) {
// The track may have been created for an end event without name. In that
// case, update it with this event's name.
- auto* tracks = context_->storage->mutable_track_table();
- uint32_t track_row = *tracks->id().IndexOf(it->second);
- if (tracks->name()[track_row] == kNullStringId)
- tracks->mutable_name()->Set(track_row, name);
+ auto& tracks = *context_->storage->mutable_track_table();
+ auto rr = *tracks.FindById(it->second);
+ if (rr.name() == kNullStringId) {
+ rr.set_name(name);
+ }
}
return it->second;
}
diff --git a/src/trace_processor/importers/ftrace/binder_tracker.cc b/src/trace_processor/importers/ftrace/binder_tracker.cc
index 48cdf58..831d466 100644
--- a/src/trace_processor/importers/ftrace/binder_tracker.cc
+++ b/src/trace_processor/importers/ftrace/binder_tracker.cc
@@ -15,14 +15,20 @@
*/
#include "src/trace_processor/importers/ftrace/binder_tracker.h"
+#include <cstdint>
+#include <optional>
+#include <string>
+#include <utility>
#include "perfetto/base/compiler.h"
#include "perfetto/ext/base/string_utils.h"
+#include "perfetto/ext/base/string_view.h"
#include "src/trace_processor/importers/common/flow_tracker.h"
#include "src/trace_processor/importers/common/process_tracker.h"
#include "src/trace_processor/importers/common/slice_tracker.h"
#include "src/trace_processor/importers/common/track_tracker.h"
#include "src/trace_processor/storage/trace_storage.h"
#include "src/trace_processor/types/trace_processor_context.h"
+#include "src/trace_processor/types/variadic.h"
// Binder tracker: displays slices for binder transactions and other operations.
// =============================================================================
@@ -268,7 +274,7 @@
if (is_reply) {
UniqueTid utid = context_->process_tracker->GetOrCreateThread(
static_cast<uint32_t>(dest_tid));
- auto dest_thread_name = context_->storage->thread_table().name()[utid];
+ auto dest_thread_name = context_->storage->thread_table()[utid].name();
auto dest_args_inserter = [this, dest_tid, &dest_thread_name](
ArgsTracker::BoundInserter* inserter) {
inserter->AddArg(dest_thread_, Variadic::Integer(dest_tid));
@@ -363,7 +369,7 @@
auto args_inserter = [this, utid,
pid](ArgsTracker::BoundInserter* inserter) {
inserter->AddArg(dest_thread_, Variadic::UnsignedInteger(pid));
- auto dest_thread_name = context_->storage->thread_table().name()[utid];
+ auto dest_thread_name = context_->storage->thread_table()[utid].name();
if (dest_thread_name.has_value()) {
inserter->AddArg(dest_name_, Variadic::String(*dest_thread_name));
}
diff --git a/src/trace_processor/importers/ftrace/binder_tracker_unittest.cc b/src/trace_processor/importers/ftrace/binder_tracker_unittest.cc
index 7fab0e5..16b57b4 100644
--- a/src/trace_processor/importers/ftrace/binder_tracker_unittest.cc
+++ b/src/trace_processor/importers/ftrace/binder_tracker_unittest.cc
@@ -16,11 +16,13 @@
#include "src/trace_processor/importers/ftrace/binder_tracker.h"
-#include "perfetto/base/logging.h"
+#include <cstdint>
+
#include "src/trace_processor/importers/common/args_tracker.h"
#include "src/trace_processor/importers/common/args_translation_table.h"
#include "src/trace_processor/importers/common/event_tracker.h"
#include "src/trace_processor/importers/common/flow_tracker.h"
+#include "src/trace_processor/importers/common/global_args_tracker.h"
#include "src/trace_processor/importers/common/process_tracker.h"
#include "src/trace_processor/importers/common/slice_tracker.h"
#include "src/trace_processor/importers/common/slice_translation_table.h"
@@ -28,8 +30,7 @@
#include "src/trace_processor/storage/trace_storage.h"
#include "test/gtest_and_gmock.h"
-namespace perfetto {
-namespace trace_processor {
+namespace perfetto::trace_processor {
namespace {
constexpr int kOneWay = 0x01;
@@ -83,22 +84,21 @@
ASSERT_EQ(slice.row_count(), 2u);
auto tid_for_slice = [&](uint32_t row) {
- TrackId track_id = slice.track_id()[row];
- UniqueTid utid = track.utid()[*track.id().IndexOf(track_id)];
- return thread.tid()[utid];
+ auto rr = track.FindById(slice[row].track_id());
+ return thread[rr->utid()].tid();
};
- ASSERT_EQ(slice.ts()[0], req_ts);
- ASSERT_EQ(slice.dur()[0], rep_recv_ts - req_ts);
+ ASSERT_EQ(slice[0].ts(), req_ts);
+ ASSERT_EQ(slice[0].dur(), rep_recv_ts - req_ts);
ASSERT_EQ(tid_for_slice(0), req_tid);
- ASSERT_EQ(slice.ts()[1], req_recv_ts);
- ASSERT_EQ(slice.dur()[1], rep_ts - req_recv_ts);
+ ASSERT_EQ(slice[1].ts(), req_recv_ts);
+ ASSERT_EQ(slice[1].dur(), rep_ts - req_recv_ts);
ASSERT_EQ(tid_for_slice(1), rep_tid);
ASSERT_EQ(flow.row_count(), 1u);
- ASSERT_EQ(flow.slice_out()[0], slice.id()[0]);
- ASSERT_EQ(flow.slice_in()[0], slice.id()[1]);
+ ASSERT_EQ(flow[0].slice_out(), slice[0].id());
+ ASSERT_EQ(flow[0].slice_in(), slice[1].id());
EXPECT_TRUE(binder_tracker->utid_stacks_empty());
}
@@ -123,22 +123,22 @@
ASSERT_EQ(slice.row_count(), 2u);
auto tid_for_slice = [&](uint32_t row) {
- TrackId track_id = slice.track_id()[row];
- UniqueTid utid = track.utid()[*track.id().IndexOf(track_id)];
- return thread.tid()[utid];
+ TrackId track_id = slice[row].track_id();
+ auto rr = track.FindById(track_id);
+ return thread[rr->utid()].tid();
};
- ASSERT_EQ(slice.ts()[0], sen_ts);
- ASSERT_EQ(slice.dur()[0], 0);
+ ASSERT_EQ(slice[0].ts(), sen_ts);
+ ASSERT_EQ(slice[0].dur(), 0);
ASSERT_EQ(tid_for_slice(0), sen_tid);
- ASSERT_EQ(slice.ts()[1], rec_ts);
- ASSERT_EQ(slice.dur()[1], 0);
+ ASSERT_EQ(slice[1].ts(), rec_ts);
+ ASSERT_EQ(slice[1].dur(), 0);
ASSERT_EQ(tid_for_slice(1), rec_tid);
ASSERT_EQ(flow.row_count(), 1u);
- ASSERT_EQ(flow.slice_out()[0], slice.id()[0]);
- ASSERT_EQ(flow.slice_in()[0], slice.id()[1]);
+ ASSERT_EQ(flow[0].slice_out(), slice[0].id());
+ ASSERT_EQ(flow[0].slice_in(), slice[1].id());
EXPECT_TRUE(binder_tracker->utid_stacks_empty());
}
@@ -170,8 +170,8 @@
const auto& slice = context.storage->slice_table();
ASSERT_EQ(slice.row_count(), 2u);
- EXPECT_NE(slice.dur()[0], -1);
- EXPECT_NE(slice.dur()[1], -1);
+ EXPECT_NE(slice[0].dur(), -1);
+ EXPECT_NE(slice[1].dur(), -1);
EXPECT_TRUE(binder_tracker->utid_stacks_empty());
}
@@ -207,7 +207,7 @@
const auto& slice = context.storage->slice_table();
ASSERT_EQ(slice.row_count(), 1u);
- EXPECT_NE(slice.dur()[0], -1);
+ EXPECT_NE(slice[0].dur(), -1);
EXPECT_TRUE(binder_tracker->utid_stacks_empty());
}
@@ -236,8 +236,8 @@
const auto& slice = context.storage->slice_table();
ASSERT_EQ(slice.row_count(), 2u);
- EXPECT_NE(slice.dur()[0], -1);
- EXPECT_NE(slice.dur()[1], -1);
+ EXPECT_NE(slice[0].dur(), -1);
+ EXPECT_NE(slice[1].dur(), -1);
EXPECT_TRUE(binder_tracker->utid_stacks_empty());
}
@@ -269,8 +269,8 @@
const auto& slice = context.storage->slice_table();
ASSERT_EQ(slice.row_count(), 2u);
- EXPECT_NE(slice.dur()[0], -1);
- EXPECT_NE(slice.dur()[1], -1);
+ EXPECT_NE(slice[0].dur(), -1);
+ EXPECT_NE(slice[1].dur(), -1);
EXPECT_TRUE(binder_tracker->utid_stacks_empty());
}
@@ -294,8 +294,8 @@
const auto& slice = context.storage->slice_table();
ASSERT_EQ(slice.row_count(), 2u);
- EXPECT_EQ(slice.dur()[0], 0);
- EXPECT_EQ(slice.dur()[1], 0);
+ EXPECT_EQ(slice[0].dur(), 0);
+ EXPECT_EQ(slice[1].dur(), 0);
EXPECT_TRUE(binder_tracker->utid_stacks_empty());
}
@@ -331,11 +331,10 @@
const auto& slice = context.storage->slice_table();
ASSERT_EQ(slice.row_count(), 1u);
- EXPECT_EQ(slice.dur()[0], 0);
+ EXPECT_EQ(slice[0].dur(), 0);
EXPECT_TRUE(binder_tracker->utid_stacks_empty());
}
} // namespace
-} // namespace trace_processor
-} // namespace perfetto
+} // namespace perfetto::trace_processor
diff --git a/src/trace_processor/importers/ftrace/ftrace_parser.cc b/src/trace_processor/importers/ftrace/ftrace_parser.cc
index 40d1730..1ef8874 100644
--- a/src/trace_processor/importers/ftrace/ftrace_parser.cc
+++ b/src/trace_processor/importers/ftrace/ftrace_parser.cc
@@ -15,6 +15,7 @@
*/
#include "src/trace_processor/importers/ftrace/ftrace_parser.h"
+#include <optional>
#include "perfetto/base/logging.h"
#include "perfetto/base/status.h"
@@ -711,7 +712,7 @@
if (PERFETTO_UNLIKELY(ts < drop_ftrace_data_before_ts_)) {
context_->storage->IncrementStats(
stats::ftrace_packet_before_tracing_start);
- return util::OkStatus();
+ return base::OkStatus();
}
using protos::pbzero::FtraceEvent;
const TraceBlobView& event = data.packet;
@@ -736,7 +737,7 @@
// not associated with any pid. The rest of trace parsing logic for
// hypervisor events will use the pid 0.
if (no_pid && !PkvmHypervisorCpuTracker::IsPkvmHypervisorEvent(fld.id())) {
- return util::ErrStatus("Pid field not found in ftrace packet");
+ return base::ErrStatus("Pid field not found in ftrace packet");
}
ConstBytes fld_bytes = fld.as_bytes();
@@ -1305,7 +1306,7 @@
}
PERFETTO_DCHECK(!decoder.bytes_left());
- return util::OkStatus();
+ return base::OkStatus();
}
base::Status FtraceParser::ParseInlineSchedSwitch(
@@ -1319,7 +1320,7 @@
if (ts < drop_ftrace_data_before_ts_) {
context_->storage->IncrementStats(
stats::ftrace_packet_before_tracing_start);
- return util::OkStatus();
+ return base::OkStatus();
}
}
@@ -1329,7 +1330,7 @@
ftrace_sched_tracker->PushSchedSwitchCompact(
cpu, ts, data.prev_state, static_cast<uint32_t>(data.next_pid),
data.next_prio, data.next_comm, parse_only_into_raw);
- return util::OkStatus();
+ return base::OkStatus();
}
base::Status FtraceParser::ParseInlineSchedWaking(
@@ -1343,7 +1344,7 @@
if (ts < drop_ftrace_data_before_ts_) {
context_->storage->IncrementStats(
stats::ftrace_packet_before_tracing_start);
- return util::OkStatus();
+ return base::OkStatus();
}
}
@@ -1353,7 +1354,7 @@
ftrace_sched_tracker->PushSchedWakingCompact(
cpu, ts, static_cast<uint32_t>(data.pid), data.target_cpu, data.prio,
data.comm, data.common_flags, parse_only_into_raw);
- return util::OkStatus();
+ return base::OkStatus();
}
void FtraceParser::MaybeOnFirstFtraceEvent() {
@@ -1895,9 +1896,7 @@
// id
TrackId track = context_->track_tracker->InternGlobalCounterTrack(
TrackTracker::Group::kBatteryMitigation, bcl_irq_id_);
- context_->event_tracker->PushCounter(ts,
- throttle ? bcl.id() : -1,
- track);
+ context_->event_tracker->PushCounter(ts, throttle ? bcl.id() : -1, track);
// throttle
track = context_->track_tracker->InternGlobalCounterTrack(
TrackTracker::Group::kBatteryMitigation, bcl_irq_throttle_);
@@ -1905,32 +1904,27 @@
// cpu0_limit
track = context_->track_tracker->InternGlobalCounterTrack(
TrackTracker::Group::kBatteryMitigation, bcl_irq_cpu0_);
- context_->event_tracker->PushCounter(ts,
- throttle ? bcl.cpu0_limit() : 0,
+ context_->event_tracker->PushCounter(ts, throttle ? bcl.cpu0_limit() : 0,
track);
// cpu1_limit
track = context_->track_tracker->InternGlobalCounterTrack(
TrackTracker::Group::kBatteryMitigation, bcl_irq_cpu1_);
- context_->event_tracker->PushCounter(ts,
- throttle ? bcl.cpu1_limit() : 0,
+ context_->event_tracker->PushCounter(ts, throttle ? bcl.cpu1_limit() : 0,
track);
// cpu2_limit
track = context_->track_tracker->InternGlobalCounterTrack(
TrackTracker::Group::kBatteryMitigation, bcl_irq_cpu2_);
- context_->event_tracker->PushCounter(ts,
- throttle ? bcl.cpu2_limit() : 0,
+ context_->event_tracker->PushCounter(ts, throttle ? bcl.cpu2_limit() : 0,
track);
// tpu_limit
track = context_->track_tracker->InternGlobalCounterTrack(
TrackTracker::Group::kBatteryMitigation, bcl_irq_tpu_);
- context_->event_tracker->PushCounter(ts,
- throttle ? bcl.tpu_limit(): 0,
+ context_->event_tracker->PushCounter(ts, throttle ? bcl.tpu_limit() : 0,
track);
// gpu_limit
track = context_->track_tracker->InternGlobalCounterTrack(
TrackTracker::Group::kBatteryMitigation, bcl_irq_gpu_);
- context_->event_tracker->PushCounter(ts,
- throttle ? bcl.gpu_limit() : 0,
+ context_->event_tracker->PushCounter(ts, throttle ? bcl.gpu_limit() : 0,
track);
// voltage
track = context_->track_tracker->InternGlobalCounterTrack(
@@ -2584,8 +2578,8 @@
PERFETTO_DCHECK(updated_utid == *opt_utid);
// UpdateThread above should ensure this is always set.
- UniquePid upid = *context_->storage->thread_table().upid()[*opt_utid];
- PERFETTO_DCHECK(context_->storage->process_table().pid()[upid] == pid);
+ UniquePid upid = *context_->storage->thread_table()[*opt_utid].upid();
+ PERFETTO_DCHECK(context_->storage->process_table()[upid].pid() == pid);
track = context_->track_tracker->InternProcessCounterTrack(
gpu_mem_total_name_id_, upid, gpu_mem_total_unit_id_,
diff --git a/src/trace_processor/importers/ftrace/ftrace_sched_event_tracker.cc b/src/trace_processor/importers/ftrace/ftrace_sched_event_tracker.cc
index feb616c..832ca7f 100644
--- a/src/trace_processor/importers/ftrace/ftrace_sched_event_tracker.cc
+++ b/src/trace_processor/importers/ftrace/ftrace_sched_event_tracker.cc
@@ -28,6 +28,7 @@
#include "src/trace_processor/importers/common/thread_state_tracker.h"
#include "src/trace_processor/importers/ftrace/ftrace_descriptors.h"
#include "src/trace_processor/storage/stats.h"
+#include "src/trace_processor/storage/trace_storage.h"
#include "src/trace_processor/types/task_state.h"
#include "src/trace_processor/types/trace_processor_context.h"
#include "src/trace_processor/types/variadic.h"
@@ -66,14 +67,14 @@
FtraceSchedEventTracker::~FtraceSchedEventTracker() = default;
void FtraceSchedEventTracker::PushSchedSwitch(uint32_t cpu,
- int64_t ts,
- uint32_t prev_pid,
- base::StringView prev_comm,
- int32_t prev_prio,
- int64_t prev_state,
- uint32_t next_pid,
- base::StringView next_comm,
- int32_t next_prio) {
+ int64_t ts,
+ uint32_t prev_pid,
+ base::StringView prev_comm,
+ int32_t prev_prio,
+ int64_t prev_state,
+ uint32_t next_pid,
+ base::StringView next_comm,
+ int32_t next_prio) {
if (!context_->sched_event_tracker->UpdateEventTrackerTimestamp(
ts, "sched_switch", stats::sched_switch_out_of_order)) {
return;
@@ -95,7 +96,7 @@
prev_pid_match_prev_next_pid = prev_pid == pending_sched->last_pid;
if (PERFETTO_LIKELY(prev_pid_match_prev_next_pid)) {
context_->sched_event_tracker->ClosePendingSlice(pending_slice_idx, ts,
- prev_state_string_id);
+ prev_state_string_id);
} else {
// If the pids are not consistent, make a note of this.
context_->storage->IncrementStats(stats::mismatched_sched_switch_tids);
@@ -112,8 +113,8 @@
AddRawSchedSwitchEvent(cpu, ts, prev_utid, prev_pid, prev_comm_id, prev_prio,
prev_state, next_pid, next_comm_id, next_prio);
- auto new_slice_idx = context_->sched_event_tracker
- ->AddStartSlice(cpu, ts, next_utid, next_prio);
+ auto new_slice_idx = context_->sched_event_tracker->AddStartSlice(
+ cpu, ts, next_utid, next_prio);
// Finally, update the info for the next sched switch on this CPU.
pending_sched->pending_slice_storage_idx = new_slice_idx;
@@ -179,7 +180,7 @@
// Do a fresh task name lookup in case it was updated by a task_rename while
// scheduled.
StringId prev_comm_id =
- context_->storage->thread_table().name()[prev_utid].value_or(
+ context_->storage->thread_table()[prev_utid].name().value_or(
kNullStringId);
AddRawSchedSwitchEvent(cpu, ts, prev_utid, prev_pid, prev_comm_id, prev_prio,
diff --git a/src/trace_processor/importers/ftrace/ftrace_sched_event_tracker_unittest.cc b/src/trace_processor/importers/ftrace/ftrace_sched_event_tracker_unittest.cc
index 8becd2e..afb4793 100644
--- a/src/trace_processor/importers/ftrace/ftrace_sched_event_tracker_unittest.cc
+++ b/src/trace_processor/importers/ftrace/ftrace_sched_event_tracker_unittest.cc
@@ -15,14 +15,19 @@
*/
#include "src/trace_processor/importers/ftrace/ftrace_sched_event_tracker.h"
+#include <cstdint>
+#include <memory>
+#include <optional>
#include "perfetto/base/logging.h"
#include "src/trace_processor/importers/common/args_tracker.h"
#include "src/trace_processor/importers/common/cpu_tracker.h"
#include "src/trace_processor/importers/common/event_tracker.h"
+#include "src/trace_processor/importers/common/global_args_tracker.h"
#include "src/trace_processor/importers/common/machine_tracker.h"
#include "src/trace_processor/importers/common/process_tracker.h"
#include "src/trace_processor/importers/common/sched_event_tracker.h"
+#include "src/trace_processor/storage/trace_storage.h"
#include "test/gtest_and_gmock.h"
namespace perfetto {
@@ -36,15 +41,15 @@
class SchedEventTrackerTest : public ::testing::Test {
public:
SchedEventTrackerTest() {
- context.storage.reset(new TraceStorage());
- context.global_args_tracker.reset(
- new GlobalArgsTracker(context.storage.get()));
- context.args_tracker.reset(new ArgsTracker(&context));
- context.event_tracker.reset(new EventTracker(&context));
- context.process_tracker.reset(new ProcessTracker(&context));
- context.machine_tracker.reset(new MachineTracker(&context, 0));
- context.cpu_tracker.reset(new CpuTracker(&context));
- context.sched_event_tracker.reset(new SchedEventTracker(&context));
+ context.storage = std::make_shared<TraceStorage>();
+ context.global_args_tracker =
+ std::make_unique<GlobalArgsTracker>(context.storage.get());
+ context.args_tracker = std::make_unique<ArgsTracker>(&context);
+ context.event_tracker = std::make_unique<EventTracker>(&context);
+ context.process_tracker = std::make_unique<ProcessTracker>(&context);
+ context.machine_tracker = std::make_unique<MachineTracker>(&context, 0);
+ context.cpu_tracker = std::make_unique<CpuTracker>(&context);
+ context.sched_event_tracker = std::make_unique<SchedEventTracker>(&context);
sched_tracker = FtraceSchedEventTracker::GetOrCreate(&context);
}
@@ -72,14 +77,15 @@
ASSERT_EQ(context.storage->sched_slice_table().row_count(), 2ul);
- const auto& timestamps = context.storage->sched_slice_table().ts();
- ASSERT_EQ(timestamps[0], timestamp);
- ASSERT_EQ(context.storage->thread_table().start_ts()[1], std::nullopt);
+ const auto& sched = context.storage->sched_slice_table();
+ ASSERT_EQ(sched[0].ts(), timestamp);
+ ASSERT_EQ(context.storage->thread_table()[1].start_ts(), std::nullopt);
- auto name = context.storage->thread_table().name().GetString(1);
+ auto name =
+ context.storage->GetString(*context.storage->thread_table()[1].name());
ASSERT_STREQ(name.c_str(), kCommProc1);
- ASSERT_EQ(context.storage->sched_slice_table().utid()[0], 1u);
- ASSERT_EQ(context.storage->sched_slice_table().dur()[0], 1);
+ ASSERT_EQ(context.storage->sched_slice_table()[0].utid(), 1u);
+ ASSERT_EQ(context.storage->sched_slice_table()[0].dur(), 1);
}
TEST_F(SchedEventTrackerTest, InsertThirdSched_SameThread) {
@@ -90,30 +96,29 @@
static const char kCommProc2[] = "process2";
int32_t prio = 1024;
- sched_tracker->PushSchedSwitch(cpu, timestamp, /*tid=*/4, kCommProc2, prio,
- prev_state,
+ sched_tracker->PushSchedSwitch(cpu, timestamp, /*prev_pid=*/4, kCommProc2,
+ prio, prev_state,
/*tid=*/2, kCommProc1, prio);
ASSERT_EQ(context.storage->sched_slice_table().row_count(), 1u);
- sched_tracker->PushSchedSwitch(cpu, timestamp + 1, /*tid=*/2, kCommProc1,
+ sched_tracker->PushSchedSwitch(cpu, timestamp + 1, /*prev_pid=*/2, kCommProc1,
prio, prev_state,
/*tid=*/4, kCommProc2, prio);
- sched_tracker->PushSchedSwitch(cpu, timestamp + 11, /*tid=*/4, kCommProc2,
- prio, prev_state,
+ sched_tracker->PushSchedSwitch(cpu, timestamp + 11, /*prev_pid=*/4,
+ kCommProc2, prio, prev_state,
/*tid=*/2, kCommProc1, prio);
sched_tracker->PushSchedSwitch(cpu, timestamp + 31, /*tid=*/2, kCommProc1,
prio, prev_state,
/*tid=*/4, kCommProc2, prio);
ASSERT_EQ(context.storage->sched_slice_table().row_count(), 4ul);
- const auto& timestamps = context.storage->sched_slice_table().ts();
- ASSERT_EQ(timestamps[0], timestamp);
- ASSERT_EQ(context.storage->thread_table().start_ts()[1], std::nullopt);
- ASSERT_EQ(context.storage->sched_slice_table().dur()[0], 1u);
- ASSERT_EQ(context.storage->sched_slice_table().dur()[1], 11u - 1u);
- ASSERT_EQ(context.storage->sched_slice_table().dur()[2], 31u - 11u);
- ASSERT_EQ(context.storage->sched_slice_table().utid()[0],
- context.storage->sched_slice_table().utid()[2]);
+ ASSERT_EQ(context.storage->sched_slice_table()[0].ts(), timestamp);
+ ASSERT_EQ(context.storage->thread_table()[1].start_ts(), std::nullopt);
+ ASSERT_EQ(context.storage->sched_slice_table()[0].dur(), 1u);
+ ASSERT_EQ(context.storage->sched_slice_table()[1].dur(), 11u - 1u);
+ ASSERT_EQ(context.storage->sched_slice_table()[2].dur(), 31u - 11u);
+ ASSERT_EQ(context.storage->sched_slice_table()[0].utid(),
+ context.storage->sched_slice_table()[2].utid());
}
TEST_F(SchedEventTrackerTest, UpdateThreadMatch) {
@@ -135,10 +140,10 @@
base::StringView());
context.process_tracker->UpdateThread(4, 2);
- ASSERT_EQ(context.storage->thread_table().tid()[1], 4u);
- ASSERT_EQ(context.storage->thread_table().upid()[1].value(), 1u);
- ASSERT_EQ(context.storage->process_table().pid()[1], 2u);
- ASSERT_EQ(context.storage->process_table().start_ts()[1], std::nullopt);
+ ASSERT_EQ(context.storage->thread_table()[1].tid(), 4u);
+ ASSERT_EQ(context.storage->thread_table()[1].upid().value(), 1u);
+ ASSERT_EQ(context.storage->process_table()[1].pid(), 2u);
+ ASSERT_EQ(context.storage->process_table()[1].start_ts(), std::nullopt);
}
} // namespace
diff --git a/src/trace_processor/importers/fuchsia/fuchsia_trace_tokenizer.cc b/src/trace_processor/importers/fuchsia/fuchsia_trace_tokenizer.cc
index f01f232..4ffb9a2 100644
--- a/src/trace_processor/importers/fuchsia/fuchsia_trace_tokenizer.cc
+++ b/src/trace_processor/importers/fuchsia/fuchsia_trace_tokenizer.cc
@@ -626,7 +626,8 @@
UniqueTid utid = procs->UpdateThread(static_cast<uint32_t>(obj_id),
static_cast<uint32_t>(pid));
- storage->mutable_thread_table()->mutable_name()->Set(utid, name);
+ auto& tt = *storage->mutable_thread_table();
+ tt[utid].set_name(name);
break;
}
default: {
diff --git a/src/trace_processor/importers/json/json_trace_parser_impl.cc b/src/trace_processor/importers/json/json_trace_parser_impl.cc
index dc7a261..37e56c8 100644
--- a/src/trace_processor/importers/json/json_trace_parser_impl.cc
+++ b/src/trace_processor/importers/json/json_trace_parser_impl.cc
@@ -181,11 +181,9 @@
auto opt_tts = json::CoerceToTs(value["tts"]);
if (opt_slice_id.has_value() && opt_tts) {
auto* slice = storage->mutable_slice_table();
- auto maybe_row = slice->id().IndexOf(*opt_slice_id);
- PERFETTO_DCHECK(maybe_row.has_value());
- auto start_tts = slice->thread_ts()[*maybe_row];
- if (start_tts) {
- slice->mutable_thread_dur()->Set(*maybe_row, *opt_tts - *start_tts);
+ auto rr = *slice->FindById(*opt_slice_id);
+ if (auto start_tts = rr.thread_ts(); start_tts) {
+ rr.set_thread_dur(*opt_tts - *start_tts);
}
}
break;
diff --git a/src/trace_processor/importers/ninja/ninja_log_parser.cc b/src/trace_processor/importers/ninja/ninja_log_parser.cc
index 1fdeee7..ba81882 100644
--- a/src/trace_processor/importers/ninja/ninja_log_parser.cc
+++ b/src/trace_processor/importers/ninja/ninja_log_parser.cc
@@ -16,24 +16,31 @@
#include "src/trace_processor/importers/ninja/ninja_log_parser.h"
+#include <stdio.h>
+#include <algorithm>
+#include <cstdint>
+#include <cstring>
+#include <vector>
+
#include "perfetto/base/status.h"
#include "perfetto/ext/base/string_splitter.h"
#include "perfetto/ext/base/string_utils.h"
+#include "perfetto/ext/base/string_view.h"
+#include "perfetto/trace_processor/trace_blob_view.h"
#include "src/trace_processor/importers/common/process_tracker.h"
#include "src/trace_processor/importers/common/slice_tracker.h"
#include "src/trace_processor/importers/common/track_tracker.h"
-#include "src/trace_processor/sorter/trace_sorter.h"
+#include "src/trace_processor/storage/stats.h"
#include "src/trace_processor/storage/trace_storage.h"
-namespace perfetto {
-namespace trace_processor {
+namespace perfetto::trace_processor {
using base::StringSplitter;
NinjaLogParser::NinjaLogParser(TraceProcessorContext* ctx) : ctx_(ctx) {}
NinjaLogParser::~NinjaLogParser() = default;
-util::Status NinjaLogParser::Parse(TraceBlobView blob) {
+base::Status NinjaLogParser::Parse(TraceBlobView blob) {
// A trace is read in chunks of arbitrary size (for http fetch() pipeliniing),
// not necessarily aligned on a line boundary.
// Here we push everything into a vector and, on each call, consume only
@@ -50,11 +57,11 @@
static const char kHeader[] = "# ninja log v";
if (!header_parsed_) {
if (!base::StartsWith(line.cur_token(), kHeader))
- return util::ErrStatus("Failed to parse ninja log header");
+ return base::ErrStatus("Failed to parse ninja log header");
header_parsed_ = true;
auto version = base::CStringToUInt32(line.cur_token() + strlen(kHeader));
if (!version || *version != 5)
- return util::ErrStatus("Unsupported ninja log version");
+ return base::ErrStatus("Unsupported ninja log version");
continue;
}
@@ -108,7 +115,7 @@
jobs_.emplace_back(*t_start, *t_end, *cmdhash, name);
}
log_.erase(log_.begin(), log_.begin() + static_cast<ssize_t>(valid_size));
- return util::OkStatus();
+ return base::OkStatus();
}
// This is called after the last Parse() call. At this point all |jobs_| have
@@ -169,7 +176,7 @@
worker = &workers.back();
}
- static constexpr int64_t kMsToNs = 1000 * 1000;
+ static constexpr int64_t kMsToNs = 1000ul * 1000;
const int64_t start_ns = job.start_ms * kMsToNs;
const int64_t dur_ns = (job.end_ms - job.start_ms) * kMsToNs;
StringId name_id = ctx_->storage->InternString(base::StringView(job.names));
@@ -179,5 +186,4 @@
return base::OkStatus();
}
-} // namespace trace_processor
-} // namespace perfetto
+} // namespace perfetto::trace_processor
diff --git a/src/trace_processor/importers/proto/BUILD.gn b/src/trace_processor/importers/proto/BUILD.gn
index 467e624..f7ebbe7 100644
--- a/src/trace_processor/importers/proto/BUILD.gn
+++ b/src/trace_processor/importers/proto/BUILD.gn
@@ -301,6 +301,8 @@
"../../../../protos/perfetto/trace/sys_stats:zero",
"../../../../protos/perfetto/trace/track_event:zero",
"../../../protozero",
+ "../../containers",
+ "../../db/column",
"../../sorter",
"../../storage",
"../../tables",
diff --git a/src/trace_processor/importers/proto/gpu_event_parser.cc b/src/trace_processor/importers/proto/gpu_event_parser.cc
index 5664fba..49f7dbd 100644
--- a/src/trace_processor/importers/proto/gpu_event_parser.cc
+++ b/src/trace_processor/importers/proto/gpu_event_parser.cc
@@ -17,33 +17,47 @@
#include "src/trace_processor/importers/proto/gpu_event_parser.h"
#include <cinttypes>
+#include <cstddef>
+#include <cstdint>
+#include <limits>
+#include <optional>
+#include <string>
-#include "perfetto/ext/base/utils.h"
+#include "perfetto/base/logging.h"
+#include "perfetto/ext/base/string_utils.h"
+#include "perfetto/ext/base/string_view.h"
+#include "perfetto/ext/base/string_writer.h"
#include "perfetto/protozero/field.h"
+#include "protos/perfetto/trace/android/gpu_mem_event.pbzero.h"
#include "src/trace_processor/importers/common/args_tracker.h"
#include "src/trace_processor/importers/common/event_tracker.h"
#include "src/trace_processor/importers/common/process_tracker.h"
#include "src/trace_processor/importers/common/slice_tracker.h"
#include "src/trace_processor/importers/common/track_tracker.h"
+#include "src/trace_processor/importers/proto/packet_sequence_state_generation.h"
+#include "src/trace_processor/importers/proto/vulkan_memory_tracker.h"
+#include "src/trace_processor/storage/stats.h"
#include "src/trace_processor/storage/trace_storage.h"
+#include "src/trace_processor/tables/profiler_tables_py.h"
+#include "src/trace_processor/tables/slice_tables_py.h"
+#include "src/trace_processor/tables/track_tables_py.h"
#include "src/trace_processor/types/trace_processor_context.h"
#include "protos/perfetto/common/gpu_counter_descriptor.pbzero.h"
-#include "protos/perfetto/trace/android/graphics_frame_event.pbzero.h"
#include "protos/perfetto/trace/gpu/gpu_counter_event.pbzero.h"
#include "protos/perfetto/trace/gpu/gpu_log.pbzero.h"
#include "protos/perfetto/trace/gpu/gpu_render_stage_event.pbzero.h"
#include "protos/perfetto/trace/gpu/vulkan_api_event.pbzero.h"
#include "protos/perfetto/trace/gpu/vulkan_memory_event.pbzero.h"
#include "protos/perfetto/trace/interned_data/interned_data.pbzero.h"
+#include "src/trace_processor/types/variadic.h"
-namespace perfetto {
-namespace trace_processor {
+namespace perfetto::trace_processor {
namespace {
// https://www.khronos.org/registry/vulkan/specs/1.1-extensions/man/html/VkObjectType.html
-typedef enum VkObjectType {
+enum VkObjectType {
VK_OBJECT_TYPE_UNKNOWN = 0,
VK_OBJECT_TYPE_INSTANCE = 1,
VK_OBJECT_TYPE_PHYSICAL_DEVICE = 2,
@@ -88,7 +102,9 @@
VK_OBJECT_TYPE_SAMPLER_YCBCR_CONVERSION_KHR =
VK_OBJECT_TYPE_SAMPLER_YCBCR_CONVERSION,
VK_OBJECT_TYPE_MAX_ENUM = 0x7FFFFFFF
-} VkObjectType;
+};
+
+using protos::pbzero::VulkanMemoryEvent;
} // anonymous namespace
@@ -209,7 +225,7 @@
}
}
-const StringId GpuEventParser::GetFullStageName(
+StringId GpuEventParser::GetFullStageName(
PacketSequenceStateGeneration* sequence_state,
const protos::pbzero::GpuRenderStageEvent_Decoder& event) const {
StringId stage_name;
@@ -223,8 +239,7 @@
}
stage_name = context_->storage->InternString(decoder->name());
} else {
- uint64_t stage_id = static_cast<uint64_t>(event.stage_id());
-
+ auto stage_id = static_cast<uint64_t>(event.stage_id());
if (stage_id < gpu_render_stage_ids_.size()) {
stage_name = gpu_render_stage_ids_[static_cast<size_t>(stage_id)].first;
} else {
@@ -263,14 +278,11 @@
// description.
auto track_id = gpu_hw_queue_ids_[gpu_hw_queue_counter_];
if (track_id.has_value()) {
- auto row = context_->storage->mutable_gpu_track_table()
- ->id()
- .IndexOf(track_id.value())
- .value();
- context_->storage->mutable_gpu_track_table()->mutable_name()->Set(
- row, track_name);
- context_->storage->mutable_gpu_track_table()->mutable_description()->Set(
- row, context_->storage->InternString(hw_queue.description()));
+ auto rr = *context_->storage->mutable_gpu_track_table()->FindById(
+ track_id.value());
+ rr.set_name(track_name);
+ rr.set_description(
+ context_->storage->InternString(hw_queue.description()));
} else {
tables::GpuTrackTable::Row track(track_name);
track.scope = gpu_render_stage_scope_id_;
@@ -291,12 +303,11 @@
auto name = map->second.find(vk_handle);
if (name == map->second.end()) {
return std::nullopt;
- } else {
- return name->second;
}
+ return name->second;
}
-const StringId GpuEventParser::ParseRenderSubpasses(
+StringId GpuEventParser::ParseRenderSubpasses(
const protos::pbzero::GpuRenderStageEvent_Decoder& event) const {
if (!event.has_render_subpass_index_mask()) {
return kNullStringId;
@@ -345,9 +356,9 @@
protos::pbzero::GpuRenderStageEvent_Specifications_Description::Decoder
stage(*it);
if (stage.has_name()) {
- gpu_render_stage_ids_.emplace_back(std::make_pair(
+ gpu_render_stage_ids_.emplace_back(
context_->storage->InternString(stage.name()),
- context_->storage->InternString(stage.description())));
+ context_->storage->InternString(stage.description()));
}
}
if (spec.has_context_spec()) {
@@ -759,7 +770,7 @@
} else {
// Process emitting the packet can be different from the pid in the event.
UniqueTid utid = context_->process_tracker->UpdateThread(pid, pid);
- UniquePid upid = context_->storage->thread_table().upid()[utid].value_or(0);
+ UniquePid upid = context_->storage->thread_table()[utid].upid().value_or(0);
track = context_->track_tracker->InternProcessCounterTrack(
gpu_mem_total_name_id_, upid, gpu_mem_total_unit_id_,
gpu_mem_total_proc_desc_id_);
@@ -768,5 +779,4 @@
ts, static_cast<double>(gpu_mem_total.size()), track);
}
-} // namespace trace_processor
-} // namespace perfetto
+} // namespace perfetto::trace_processor
diff --git a/src/trace_processor/importers/proto/gpu_event_parser.h b/src/trace_processor/importers/proto/gpu_event_parser.h
index 6ca6527..ccab42a 100644
--- a/src/trace_processor/importers/proto/gpu_event_parser.h
+++ b/src/trace_processor/importers/proto/gpu_event_parser.h
@@ -17,14 +17,18 @@
#ifndef SRC_TRACE_PROCESSOR_IMPORTERS_PROTO_GPU_EVENT_PARSER_H_
#define SRC_TRACE_PROCESSOR_IMPORTERS_PROTO_GPU_EVENT_PARSER_H_
+#include <array>
+#include <cstddef>
+#include <cstdint>
#include <optional>
+#include <string>
+#include <unordered_map>
+#include <utility>
#include <vector>
-#include "perfetto/ext/base/string_writer.h"
#include "perfetto/protozero/field.h"
-#include "protos/perfetto/trace/android/gpu_mem_event.pbzero.h"
#include "protos/perfetto/trace/gpu/gpu_render_stage_event.pbzero.h"
-#include "src/trace_processor/importers/common/args_tracker.h"
+#include "src/trace_processor/importers/proto/packet_sequence_state_generation.h"
#include "src/trace_processor/importers/proto/vulkan_memory_tracker.h"
#include "src/trace_processor/storage/trace_storage.h"
@@ -32,13 +36,9 @@
namespace perfetto {
-namespace protos {
-namespace pbzero {
-
+namespace protos::pbzero {
class GpuRenderStageEvent_Decoder;
-
-} // namespace pbzero
-} // namespace protos
+} // namespace protos::pbzero
namespace trace_processor {
@@ -55,8 +55,9 @@
class GpuEventParser {
public:
using ConstBytes = protozero::ConstBytes;
- using VulkanMemoryEventSource = VulkanMemoryEvent::Source;
- using VulkanMemoryEventOperation = VulkanMemoryEvent::Operation;
+ using VulkanMemoryEventSource = protos::pbzero::VulkanMemoryEvent::Source;
+ using VulkanMemoryEventOperation =
+ protos::pbzero::VulkanMemoryEvent::Operation;
explicit GpuEventParser(TraceProcessorContext*);
void ParseGpuCounterEvent(int64_t ts, ConstBytes);
@@ -67,15 +68,16 @@
void ParseGpuLog(int64_t ts, ConstBytes);
void ParseVulkanMemoryEvent(PacketSequenceStateGeneration*, ConstBytes);
- void UpdateVulkanMemoryAllocationCounters(UniquePid,
- const VulkanMemoryEvent::Decoder&);
+ void UpdateVulkanMemoryAllocationCounters(
+ UniquePid,
+ const protos::pbzero::VulkanMemoryEvent::Decoder&);
void ParseVulkanApiEvent(int64_t, ConstBytes);
void ParseGpuMemTotalEvent(int64_t, ConstBytes);
private:
- const StringId GetFullStageName(
+ StringId GetFullStageName(
PacketSequenceStateGeneration* sequence_state,
const protos::pbzero::GpuRenderStageEvent_Decoder& event) const;
void InsertGpuTrack(
@@ -83,7 +85,7 @@
GpuRenderStageEvent_Specifications_Description_Decoder& hw_queue);
std::optional<std::string> FindDebugName(int32_t vk_object_type,
uint64_t vk_handle) const;
- const StringId ParseRenderSubpasses(
+ StringId ParseRenderSubpasses(
const protos::pbzero::GpuRenderStageEvent_Decoder& event) const;
TraceProcessorContext* const context_;
@@ -98,7 +100,7 @@
// Map of stage ID -> pair(stage name, stage description)
std::vector<std::pair<StringId, StringId>> gpu_render_stage_ids_;
// For VulkanMemoryEvent
- std::unordered_map<VulkanMemoryEvent::AllocationScope,
+ std::unordered_map<protos::pbzero::VulkanMemoryEvent::AllocationScope,
int64_t /*counter_value*/,
ProtoEnumHasher>
vulkan_driver_memory_counters_;
diff --git a/src/trace_processor/importers/proto/graphics_frame_event_parser.cc b/src/trace_processor/importers/proto/graphics_frame_event_parser.cc
index 11808a4..d75c617 100644
--- a/src/trace_processor/importers/proto/graphics_frame_event_parser.cc
+++ b/src/trace_processor/importers/proto/graphics_frame_event_parser.cc
@@ -16,22 +16,26 @@
#include "src/trace_processor/importers/proto/graphics_frame_event_parser.h"
-#include <cinttypes>
+#include <algorithm>
+#include <cstddef>
+#include <cstdint>
+#include <optional>
+#include "perfetto/base/logging.h"
+#include "perfetto/ext/base/string_view.h"
+#include "perfetto/ext/base/string_writer.h"
#include "perfetto/ext/base/utils.h"
-#include "perfetto/protozero/field.h"
-#include "src/trace_processor/importers/common/args_tracker.h"
+#include "protos/perfetto/trace/android/graphics_frame_event.pbzero.h"
#include "src/trace_processor/importers/common/event_tracker.h"
-#include "src/trace_processor/importers/common/process_tracker.h"
#include "src/trace_processor/importers/common/slice_tracker.h"
#include "src/trace_processor/importers/common/track_tracker.h"
+#include "src/trace_processor/storage/stats.h"
#include "src/trace_processor/storage/trace_storage.h"
+#include "src/trace_processor/tables/slice_tables_py.h"
+#include "src/trace_processor/tables/track_tables_py.h"
#include "src/trace_processor/types/trace_processor_context.h"
-#include "protos/perfetto/trace/interned_data/interned_data.pbzero.h"
-
-namespace perfetto {
-namespace trace_processor {
+namespace perfetto::trace_processor {
constexpr char kQueueLostMessage[] =
"Missing queue event. The slice is now a bit extended than it might "
@@ -163,11 +167,8 @@
} else if (event.type() == GraphicsFrameEvent::QUEUE) {
auto it = dequeue_slice_ids_.find(event_key);
if (it != dequeue_slice_ids_.end()) {
- auto dequeue_slice_id = it->second;
- uint32_t row_idx =
- *graphics_frame_slice_table->id().IndexOf(dequeue_slice_id);
- graphics_frame_slice_table->mutable_frame_number()->Set(row_idx,
- frame_number);
+ auto rr = graphics_frame_slice_table->FindById(it->second);
+ rr->set_frame_number(frame_number);
}
}
}
@@ -182,19 +183,19 @@
if (opt_slice_id) {
auto* graphics_frame_slice_table =
context_->storage->mutable_graphics_frame_slice_table();
- uint32_t row_idx = *graphics_frame_slice_table->id().IndexOf(*opt_slice_id);
+ auto rr = *graphics_frame_slice_table->FindById(*opt_slice_id);
if (reset_name) {
// Set the name (frame_number) to be 0 since there is no frame number
// associated, example : dequeue event.
StringId frame_name_id = context_->storage->InternString("0");
- graphics_frame_slice_table->mutable_name()->Set(row_idx, frame_name_id);
- graphics_frame_slice_table->mutable_frame_number()->Set(row_idx, 0);
+ rr.set_name(frame_name_id);
+ rr.set_frame_number(0);
}
// Set the duration to -1 so that this slice will be ignored by the
// UI. Setting any other duration results in wrong data which we want
// to avoid at all costs.
- graphics_frame_slice_table->mutable_dur()->Set(row_idx, -1);
+ rr.set_dur(-1);
}
}
@@ -277,14 +278,10 @@
context_->storage->mutable_graphics_frame_slice_table();
// Set the name of the slice to be the frame number since dequeue did
// not have a frame number at that time.
- uint32_t row_idx =
- *graphics_frame_slice_table->id().IndexOf(*opt_slice_id);
- StringId frame_name_id =
- context_->storage->InternString(slice_name.GetStringView());
- graphics_frame_slice_table->mutable_name()->Set(row_idx,
- frame_name_id);
- graphics_frame_slice_table->mutable_frame_number()->Set(row_idx,
- frame_number);
+ auto rr = *graphics_frame_slice_table->FindById(*opt_slice_id);
+ rr.set_name(
+ context_->storage->InternString(slice_name.GetStringView()));
+ rr.set_frame_number(frame_number);
dequeue_map_.erase(dequeue_time);
}
}
@@ -394,19 +391,17 @@
void GraphicsFrameEventParser::ParseGraphicsFrameEvent(int64_t timestamp,
ConstBytes blob) {
- protos::pbzero::GraphicsFrameEvent_Decoder frame_event(blob.data, blob.size);
+ protos::pbzero::GraphicsFrameEvent::Decoder frame_event(blob);
if (!frame_event.has_buffer_event()) {
return;
}
- ConstBytes bufferBlob = frame_event.buffer_event();
- protos::pbzero::GraphicsFrameEvent_BufferEvent_Decoder event(bufferBlob.data,
- bufferBlob.size);
+ protos::pbzero::GraphicsFrameEvent::BufferEvent::Decoder event(
+ frame_event.buffer_event());
if (CreateBufferEvent(timestamp, event)) {
// Create a phase event only if the buffer event finishes successfully
CreatePhaseEvent(timestamp, event);
}
}
-} // namespace trace_processor
-} // namespace perfetto
+} // namespace perfetto::trace_processor
diff --git a/src/trace_processor/importers/proto/heap_graph_tracker.cc b/src/trace_processor/importers/proto/heap_graph_tracker.cc
index 097f398..89f7977 100644
--- a/src/trace_processor/importers/proto/heap_graph_tracker.cc
+++ b/src/trace_processor/importers/proto/heap_graph_tracker.cc
@@ -586,13 +586,14 @@
}
}
if (!class_package) {
- auto app_id = storage_->process_table()
- .android_appid()[sequence_state.current_upid];
+ auto app_id = storage_->process_table()[sequence_state.current_upid]
+ .android_appid();
if (app_id) {
- auto pkg_row = storage_->package_list_table().uid().IndexOf(*app_id);
- if (pkg_row) {
- class_package =
- storage_->package_list_table().package_name()[*pkg_row];
+ for (auto it = storage_->package_list_table().IterateRows(); it; ++it) {
+ if (it.uid() == *app_id) {
+ class_package = it.package_name();
+ break;
+ }
}
}
}
@@ -736,18 +737,18 @@
auto* classes_tbl = storage_->mutable_heap_graph_class_table();
std::map<ClassDescriptor, ClassTable::Id> class_to_id;
- for (uint32_t idx = 0; idx < classes_tbl->row_count(); ++idx) {
- class_to_id[{classes_tbl->name()[idx], classes_tbl->location()[idx]}] =
- classes_tbl->id()[idx];
+ for (auto it = classes_tbl->IterateRows(); it; ++it) {
+ class_to_id[{it.name(), it.location()}] = it.id();
}
// Iterate through the classes table and annotate with superclasses.
// We iterate all rows on the classes table (even though the superclass
// mapping was generated on the current sequence) - if we cannot identify
// a superclass we will just skip.
- for (uint32_t idx = 0; idx < classes_tbl->row_count(); ++idx) {
- auto name = storage_->GetString(classes_tbl->name()[idx]);
- auto location = classes_tbl->location()[idx];
+ for (uint32_t i = 0; i < classes_tbl->row_count(); ++i) {
+ auto rr = (*classes_tbl)[i];
+ auto name = storage_->GetString(rr.name());
+ auto location = rr.location();
auto normalized = GetNormalizedType(name);
if (normalized.is_static_class || normalized.number_of_arrays > 0)
continue;
@@ -766,9 +767,7 @@
// instances would not appear here).
continue;
}
- auto superclass_id = superclass_it->second;
- // Mutate the superclass column
- classes_tbl->mutable_superclass_id()->Set(idx, superclass_id);
+ rr.set_superclass_id(superclass_it->second);
}
}
diff --git a/src/trace_processor/importers/proto/heap_graph_tracker_unittest.cc b/src/trace_processor/importers/proto/heap_graph_tracker_unittest.cc
index ebc2a5e..70c8af5 100644
--- a/src/trace_processor/importers/proto/heap_graph_tracker_unittest.cc
+++ b/src/trace_processor/importers/proto/heap_graph_tracker_unittest.cc
@@ -16,8 +16,18 @@
#include "src/trace_processor/importers/proto/heap_graph_tracker.h"
-#include "perfetto/base/logging.h"
+#include <cstddef>
+#include <cstdint>
+#include <memory>
+#include <optional>
+#include <utility>
+
+#include "perfetto/ext/base/string_view.h"
+#include "protos/perfetto/trace/profiling/heap_graph.pbzero.h"
+#include "src/trace_processor/containers/string_pool.h"
#include "src/trace_processor/importers/common/process_tracker.h"
+#include "src/trace_processor/storage/trace_storage.h"
+#include "src/trace_processor/tables/profiler_tables_py.h"
#include "src/trace_processor/util/profiler_util.h"
#include "test/gtest_and_gmock.h"
@@ -61,8 +71,8 @@
constexpr int64_t kTimestamp = 1;
TraceProcessorContext context;
- context.storage.reset(new TraceStorage());
- context.process_tracker.reset(new ProcessTracker(&context));
+ context.storage = std::make_shared<TraceStorage>();
+ context.process_tracker = std::make_unique<ProcessTracker>(&context);
context.process_tracker->GetOrCreateProcess(kPid);
HeapGraphTracker tracker(context.storage.get());
@@ -171,19 +181,16 @@
const auto& objs_table = context.storage->heap_graph_object_table();
const auto& class_table = context.storage->heap_graph_class_table();
size_t count_bitmaps = 0;
- for (uint32_t obj_row = 0; obj_row < objs_table.row_count(); ++obj_row) {
- std::optional<uint32_t> class_row =
- class_table.id().IndexOf(objs_table.type_id()[obj_row]);
+ for (auto it = objs_table.IterateRows(); it; ++it) {
+ auto class_row = class_table.FindById(it.type_id());
ASSERT_TRUE(class_row.has_value());
- if (context.storage->string_pool().Get(class_table.name()[*class_row]) ==
+ if (context.storage->string_pool().Get(class_row->name()) ==
"android.graphics.Bitmap") {
- EXPECT_EQ(objs_table.native_size()[obj_row], 24242);
+ EXPECT_EQ(it.native_size(), 24242);
count_bitmaps++;
} else {
- EXPECT_EQ(objs_table.native_size()[obj_row], 0)
- << context.storage->string_pool()
- .Get(class_table.name()[*class_row])
- .c_str()
+ EXPECT_EQ(it.native_size(), 0)
+ << context.storage->string_pool().Get(class_row->name()).c_str()
<< " has non zero native_size";
}
}
@@ -216,7 +223,7 @@
constexpr uint64_t kA = 3;
constexpr uint64_t kB = 4;
- base::StringView field = base::StringView("foo");
+ auto field = base::StringView("foo");
StringPool::Id x = context.storage->InternString("X");
StringPool::Id y = context.storage->InternString("Y");
StringPool::Id a = context.storage->InternString("A");
@@ -424,12 +431,12 @@
EXPECT_THAT(counts, UnorderedElementsAre(1, 1));
}
-static const char kArray[] = "X[]";
-static const char kDoubleArray[] = "X[][]";
-static const char kNoArray[] = "X";
-static const char kLongNoArray[] = "ABCDE";
-static const char kStaticClassNoArray[] = "java.lang.Class<abc>";
-static const char kStaticClassArray[] = "java.lang.Class<abc[]>";
+constexpr char kArray[] = "X[]";
+constexpr char kDoubleArray[] = "X[][]";
+constexpr char kNoArray[] = "X";
+constexpr char kLongNoArray[] = "ABCDE";
+constexpr char kStaticClassNoArray[] = "java.lang.Class<abc>";
+constexpr char kStaticClassArray[] = "java.lang.Class<abc[]>";
TEST(HeapGraphTrackerTest, NormalizeTypeName) {
// sizeof(...) - 1 below to get rid of the null-byte.
diff --git a/src/trace_processor/importers/proto/memory_tracker_snapshot_parser.cc b/src/trace_processor/importers/proto/memory_tracker_snapshot_parser.cc
index c4eeeff..dc96491 100644
--- a/src/trace_processor/importers/proto/memory_tracker_snapshot_parser.cc
+++ b/src/trace_processor/importers/proto/memory_tracker_snapshot_parser.cc
@@ -275,8 +275,7 @@
.id;
auto* node_table = context_->storage->mutable_memory_snapshot_node_table();
- uint32_t node_row_index =
- static_cast<uint32_t>(*node_table->id().IndexOf(node_row_id));
+ auto rr = *node_table->FindById(node_row_id);
ArgsTracker::BoundInserter args =
context_->args_tracker->AddArgsTo(node_row_id);
@@ -286,9 +285,9 @@
int64_t value_int = static_cast<int64_t>(entry.second.value_uint64);
if (entry.first == "size") {
- node_table->mutable_size()->Set(node_row_index, value_int);
+ rr.set_size(value_int);
} else if (entry.first == "effective_size") {
- node_table->mutable_effective_size()->Set(node_row_index, value_int);
+ rr.set_effective_size(value_int);
} else {
args.AddArg(context_->storage->InternString(
base::StringView(entry.first + ".value")),
diff --git a/src/trace_processor/importers/proto/network_trace_module_unittest.cc b/src/trace_processor/importers/proto/network_trace_module_unittest.cc
index 317120e..36ede9a 100644
--- a/src/trace_processor/importers/proto/network_trace_module_unittest.cc
+++ b/src/trace_processor/importers/proto/network_trace_module_unittest.cc
@@ -14,8 +14,21 @@
* limitations under the License.
*/
+#include <cstdint>
+#include <memory>
+#include <vector>
+
#include "src/trace_processor/importers/proto/network_trace_module.h"
+#include "perfetto/base/status.h"
+#include "perfetto/ext/base/string_view.h"
+#include "perfetto/protozero/packed_repeated_fields.h"
+#include "perfetto/protozero/scattered_heap_buffer.h"
+#include "perfetto/trace_processor/trace_blob.h"
+#include "perfetto/trace_processor/trace_blob_view.h"
+#include "protos/perfetto/trace/android/network_trace.pbzero.h"
+#include "protos/perfetto/trace/trace.pbzero.h"
+#include "src/trace_processor/db/column/types.h"
#include "src/trace_processor/importers/common/args_tracker.h"
#include "src/trace_processor/importers/common/args_translation_table.h"
#include "src/trace_processor/importers/common/async_track_set_tracker.h"
@@ -27,35 +40,42 @@
#include "src/trace_processor/importers/proto/proto_trace_parser_impl.h"
#include "src/trace_processor/importers/proto/proto_trace_reader.h"
#include "src/trace_processor/sorter/trace_sorter.h"
+#include "src/trace_processor/storage/trace_storage.h"
#include "src/trace_processor/types/trace_processor_context.h"
+#include "src/trace_processor/types/variadic.h"
#include "test/gtest_and_gmock.h"
-namespace perfetto {
-namespace trace_processor {
+namespace perfetto::trace_processor {
namespace {
+
using ::perfetto::protos::pbzero::TrafficDirection;
class NetworkTraceModuleTest : public testing::Test {
public:
NetworkTraceModuleTest() {
- context_.storage.reset(new TraceStorage());
+ context_.storage = std::make_shared<TraceStorage>();
storage_ = context_.storage.get();
- context_.track_tracker.reset(new TrackTracker(&context_));
- context_.slice_tracker.reset(new SliceTracker(&context_));
- context_.args_tracker.reset(new ArgsTracker(&context_));
- context_.global_args_tracker.reset(new GlobalArgsTracker(storage_));
- context_.slice_translation_table.reset(new SliceTranslationTable(storage_));
- context_.process_track_translation_table.reset(
- new ProcessTrackTranslationTable(storage_));
- context_.args_translation_table.reset(new ArgsTranslationTable(storage_));
- context_.async_track_set_tracker.reset(new AsyncTrackSetTracker(&context_));
- context_.proto_trace_parser.reset(new ProtoTraceParserImpl(&context_));
- context_.sorter.reset(
- new TraceSorter(&context_, TraceSorter::SortingMode::kFullSort));
+ context_.track_tracker = std::make_unique<TrackTracker>(&context_);
+ context_.slice_tracker = std::make_unique<SliceTracker>(&context_);
+ context_.args_tracker = std::make_unique<ArgsTracker>(&context_);
+ context_.global_args_tracker =
+ std::make_unique<GlobalArgsTracker>(storage_);
+ context_.slice_translation_table =
+ std::make_unique<SliceTranslationTable>(storage_);
+ context_.process_track_translation_table =
+ std::make_unique<ProcessTrackTranslationTable>(storage_);
+ context_.args_translation_table =
+ std::make_unique<ArgsTranslationTable>(storage_);
+ context_.async_track_set_tracker =
+ std::make_unique<AsyncTrackSetTracker>(&context_);
+ context_.proto_trace_parser =
+ std::make_unique<ProtoTraceParserImpl>(&context_);
+ context_.sorter = std::make_shared<TraceSorter>(
+ &context_, TraceSorter::SortingMode::kFullSort);
}
- util::Status TokenizeAndParse() {
+ base::Status TokenizeAndParse() {
context_.chunk_readers.push_back(
std::make_unique<ProtoTraceReader>(&context_));
@@ -114,7 +134,7 @@
const auto& slices = storage_->slice_table();
ASSERT_EQ(slices.row_count(), 1u);
- EXPECT_EQ(slices.ts()[0], 123);
+ EXPECT_EQ(slices[0].ts(), 123);
EXPECT_TRUE(HasArg(1u, "packet_length", Variadic::Integer(72)));
EXPECT_TRUE(HasArg(1u, "socket_uid", Variadic::Integer(1010)));
@@ -153,8 +173,8 @@
const auto& slices = storage_->slice_table();
ASSERT_EQ(slices.row_count(), 2u);
- EXPECT_EQ(slices.ts()[0], 123);
- EXPECT_EQ(slices.ts()[1], 133);
+ EXPECT_EQ(slices[0].ts(), 123);
+ EXPECT_EQ(slices[1].ts(), 133);
EXPECT_TRUE(HasArg(1u, "packet_length", Variadic::Integer(72)));
EXPECT_TRUE(HasArg(2u, "packet_length", Variadic::Integer(100)));
@@ -178,13 +198,12 @@
const auto& slices = storage_->slice_table();
ASSERT_EQ(slices.row_count(), 1u);
- EXPECT_EQ(slices.ts()[0], 123);
- EXPECT_EQ(slices.dur()[0], 10);
+ EXPECT_EQ(slices[0].ts(), 123);
+ EXPECT_EQ(slices[0].dur(), 10);
EXPECT_TRUE(HasArg(1u, "packet_length", Variadic::Integer(172)));
EXPECT_TRUE(HasArg(1u, "packet_count", Variadic::Integer(2)));
}
} // namespace
-} // namespace trace_processor
-} // namespace perfetto
+} // namespace perfetto::trace_processor
diff --git a/src/trace_processor/importers/proto/perf_sample_tracker_unittest.cc b/src/trace_processor/importers/proto/perf_sample_tracker_unittest.cc
index df1fba0..86336a7 100644
--- a/src/trace_processor/importers/proto/perf_sample_tracker_unittest.cc
+++ b/src/trace_processor/importers/proto/perf_sample_tracker_unittest.cc
@@ -15,9 +15,12 @@
*/
#include "src/trace_processor/importers/proto/perf_sample_tracker.h"
+#include <cstdint>
+#include <string>
#include "perfetto/base/logging.h"
#include "src/trace_processor/importers/common/track_tracker.h"
+#include "src/trace_processor/storage/trace_storage.h"
#include "test/gtest_and_gmock.h"
#include "protos/perfetto/common/perf_events.gen.h"
@@ -81,17 +84,16 @@
TrackId track_id = stream.timebase_track_id;
const auto& track_table = context.storage->perf_counter_track_table();
- auto row_id = track_table.id().IndexOf(track_id);
+ auto rr = track_table.FindById(track_id);
// track exists and looks sensible
- ASSERT_TRUE(row_id.has_value());
- EXPECT_EQ(track_table.perf_session_id()[*row_id], stream.perf_session_id);
- EXPECT_EQ(track_table.cpu()[*row_id], cpu0);
- EXPECT_TRUE(track_table.is_timebase()[*row_id]);
+ ASSERT_TRUE(rr.has_value());
+ EXPECT_EQ(rr->perf_session_id(), stream.perf_session_id);
+ EXPECT_EQ(rr->cpu(), cpu0);
+ EXPECT_TRUE(rr->is_timebase());
// Name derived from the timebase.
- std::string track_name =
- context.storage->GetString(track_table.name()[*row_id]).ToStdString();
+ std::string track_name = context.storage->GetString(rr->name()).ToStdString();
ASSERT_EQ(track_name, "page-faults");
}
@@ -112,17 +114,16 @@
TrackId track_id = stream.timebase_track_id;
const auto& track_table = context.storage->perf_counter_track_table();
- auto row_id = track_table.id().IndexOf(track_id);
+ auto rr = track_table.FindById(track_id);
// track exists and looks sensible
- ASSERT_TRUE(row_id.has_value());
- EXPECT_EQ(track_table.perf_session_id()[*row_id], stream.perf_session_id);
- EXPECT_EQ(track_table.cpu()[*row_id], cpu0);
- EXPECT_TRUE(track_table.is_timebase()[*row_id]);
+ ASSERT_TRUE(rr.has_value());
+ EXPECT_EQ(rr->perf_session_id(), stream.perf_session_id);
+ EXPECT_EQ(rr->cpu(), cpu0);
+ EXPECT_TRUE(rr->is_timebase());
// Name derived from the timebase.
- std::string track_name =
- context.storage->GetString(track_table.name()[*row_id]).ToStdString();
+ std::string track_name = context.storage->GetString(rr->name()).ToStdString();
ASSERT_EQ(track_name, "sched:sched_switch");
}
@@ -135,18 +136,17 @@
TrackId track_id = stream.timebase_track_id;
const auto& track_table = context.storage->perf_counter_track_table();
- auto row_id = track_table.id().IndexOf(track_id);
+ auto rr = track_table.FindById(track_id);
// track exists and looks sensible
- ASSERT_TRUE(row_id.has_value());
- EXPECT_EQ(track_table.perf_session_id()[*row_id], stream.perf_session_id);
- EXPECT_EQ(track_table.cpu()[*row_id], cpu0);
- EXPECT_TRUE(track_table.is_timebase()[*row_id]);
+ ASSERT_TRUE(rr.has_value());
+ EXPECT_EQ(rr->perf_session_id(), stream.perf_session_id);
+ EXPECT_EQ(rr->cpu(), cpu0);
+ EXPECT_TRUE(rr->is_timebase());
// If the trace doesn't have a PerfSampleDefaults describing the timebase
// counter, we assume cpu-clock.
- std::string track_name =
- context.storage->GetString(track_table.name()[*row_id]).ToStdString();
+ std::string track_name = context.storage->GetString(rr->name()).ToStdString();
ASSERT_EQ(track_name, "cpu-clock");
}
@@ -170,17 +170,16 @@
TrackId track_id = stream.timebase_track_id;
const auto& track_table = context.storage->perf_counter_track_table();
- auto row_id = track_table.id().IndexOf(track_id);
+ auto rr = track_table.FindById(track_id);
// track exists and looks sensible
- ASSERT_TRUE(row_id.has_value());
- EXPECT_EQ(track_table.perf_session_id()[*row_id], stream.perf_session_id);
- EXPECT_EQ(track_table.cpu()[*row_id], cpu0);
- EXPECT_TRUE(track_table.is_timebase()[*row_id]);
+ ASSERT_TRUE(rr.has_value());
+ EXPECT_EQ(rr->perf_session_id(), stream.perf_session_id);
+ EXPECT_EQ(rr->cpu(), cpu0);
+ EXPECT_TRUE(rr->is_timebase());
// Using the config-supplied name for the track.
- std::string track_name =
- context.storage->GetString(track_table.name()[*row_id]).ToStdString();
+ std::string track_name = context.storage->GetString(rr->name()).ToStdString();
ASSERT_EQ(track_name, "test-name");
}
diff --git a/src/trace_processor/importers/proto/profile_module.cc b/src/trace_processor/importers/proto/profile_module.cc
index a5e3672..813fa09 100644
--- a/src/trace_processor/importers/proto/profile_module.cc
+++ b/src/trace_processor/importers/proto/profile_module.cc
@@ -21,6 +21,7 @@
#include "perfetto/base/logging.h"
#include "perfetto/ext/base/flat_hash_map.h"
#include "perfetto/ext/base/string_utils.h"
+#include "perfetto/ext/base/string_view.h"
#include "src/trace_processor/importers/common/args_translation_table.h"
#include "src/trace_processor/importers/common/clock_tracker.h"
#include "src/trace_processor/importers/common/deobfuscation_mapping_table.h"
@@ -480,8 +481,8 @@
for (const FrameId frame_id : frame_ids) {
auto* frames = context_->storage->mutable_stack_profile_frame_table();
- uint32_t frame_row = *frames->id().IndexOf(frame_id);
- frames->mutable_symbol_set_id()->Set(frame_row, symbol_set_id);
+ auto rr = *frames->FindById(frame_id);
+ rr.set_symbol_set_id(symbol_set_id);
frame_found = true;
}
}
@@ -542,10 +543,9 @@
for (tables::StackProfileFrameTable::Id frame_id : frames) {
auto* frames_tbl =
context_->storage->mutable_stack_profile_frame_table();
- frames_tbl->mutable_deobfuscated_name()->Set(
- *frames_tbl->id().IndexOf(frame_id),
- context_->storage->InternString(
- base::StringView(merged_deobfuscated)));
+ auto rr = *frames_tbl->FindById(frame_id);
+ rr.set_deobfuscated_name(context_->storage->InternString(
+ base::StringView(merged_deobfuscated)));
}
obfuscated_to_deobfuscated_members[context_->storage->InternString(
member.obfuscated_name())] =
diff --git a/src/trace_processor/importers/proto/profile_packet_sequence_state_unittest.cc b/src/trace_processor/importers/proto/profile_packet_sequence_state_unittest.cc
index ddaaa85..2022952 100644
--- a/src/trace_processor/importers/proto/profile_packet_sequence_state_unittest.cc
+++ b/src/trace_processor/importers/proto/profile_packet_sequence_state_unittest.cc
@@ -16,11 +16,14 @@
#include "src/trace_processor/importers/proto/profile_packet_sequence_state.h"
+#include <cstdint>
#include <memory>
+#include <optional>
#include "src/trace_processor/importers/common/mapping_tracker.h"
#include "src/trace_processor/importers/common/stack_profile_tracker.h"
#include "src/trace_processor/importers/proto/packet_sequence_state_generation.h"
+#include "src/trace_processor/storage/trace_storage.h"
#include "src/trace_processor/types/trace_processor_context.h"
#include "test/gtest_and_gmock.h"
@@ -127,19 +130,19 @@
InsertMapping(kSecondPacket);
profile_packet_sequence_state().FinalizeProfile();
- EXPECT_THAT(context.storage->stack_profile_mapping_table().build_id()[0],
+ EXPECT_THAT(context.storage->stack_profile_mapping_table()[0].build_id(),
context.storage->InternString({kBuildIDHexName}));
- EXPECT_THAT(context.storage->stack_profile_mapping_table().exact_offset()[0],
+ EXPECT_THAT(context.storage->stack_profile_mapping_table()[0].exact_offset(),
kMappingExactOffset);
- EXPECT_THAT(context.storage->stack_profile_mapping_table().start_offset()[0],
+ EXPECT_THAT(context.storage->stack_profile_mapping_table()[0].start_offset(),
kMappingStartOffset);
- EXPECT_THAT(context.storage->stack_profile_mapping_table().start()[0],
+ EXPECT_THAT(context.storage->stack_profile_mapping_table()[0].start(),
kMappingStart);
- EXPECT_THAT(context.storage->stack_profile_mapping_table().end()[0],
+ EXPECT_THAT(context.storage->stack_profile_mapping_table()[0].end(),
kMappingEnd);
- EXPECT_THAT(context.storage->stack_profile_mapping_table().load_bias()[0],
+ EXPECT_THAT(context.storage->stack_profile_mapping_table()[0].load_bias(),
kMappingLoadBias);
- EXPECT_THAT(context.storage->stack_profile_mapping_table().name()[0],
+ EXPECT_THAT(context.storage->stack_profile_mapping_table()[0].name(),
fully_qualified_mapping_name);
}
@@ -152,9 +155,9 @@
profile_packet_sequence_state().FinalizeProfile();
const auto& frames = context.storage->stack_profile_frame_table();
- EXPECT_THAT(frames.name()[0], frame_name);
- EXPECT_THAT(frames.mapping()[0], MappingId{0});
- EXPECT_THAT(frames.rel_pc()[0], kFrameRelPc);
+ EXPECT_THAT(frames[0].name(), frame_name);
+ EXPECT_THAT(frames[0].mapping(), MappingId{0});
+ EXPECT_THAT(frames[0].rel_pc(), kFrameRelPc);
}
// Insert the same callstack from two different packets, assert it is only
@@ -166,18 +169,15 @@
profile_packet_sequence_state().FinalizeProfile();
const auto& callsite_table = context.storage->stack_profile_callsite_table();
- const auto& depth = callsite_table.depth();
- const auto& parent_id = callsite_table.parent_id();
- const auto& frame_id = callsite_table.frame_id();
- EXPECT_EQ(depth[0], 0u);
- EXPECT_EQ(depth[1], 1u);
+ EXPECT_EQ(callsite_table[0].depth(), 0u);
+ EXPECT_EQ(callsite_table[1].depth(), 1u);
- EXPECT_EQ(parent_id[0], std::nullopt);
- EXPECT_EQ(parent_id[1], CallsiteId{0});
+ EXPECT_EQ(callsite_table[0].parent_id(), std::nullopt);
+ EXPECT_EQ(callsite_table[1].parent_id(), CallsiteId{0});
- EXPECT_EQ(frame_id[0], FrameId{0});
- EXPECT_EQ(frame_id[1], FrameId{0});
+ EXPECT_EQ(callsite_table[0].frame_id(), FrameId{0});
+ EXPECT_EQ(callsite_table[1].frame_id(), FrameId{0});
}
std::optional<CallsiteId> FindCallstack(const TraceStorage& storage,
@@ -185,10 +185,10 @@
std::optional<CallsiteId> parent,
FrameId frame_id) {
const auto& callsites = storage.stack_profile_callsite_table();
- for (uint32_t i = 0; i < callsites.row_count(); ++i) {
- if (callsites.depth()[i] == depth && callsites.parent_id()[i] == parent &&
- callsites.frame_id()[i] == frame_id) {
- return callsites.id()[i];
+ for (auto it = callsites.IterateRows(); it; ++it) {
+ if (it.depth() == depth && it.parent_id() == parent &&
+ it.frame_id() == frame_id) {
+ return it.id();
}
}
return std::nullopt;
@@ -223,7 +223,7 @@
ppss.CommitAllocations();
auto foo_bar_id = context.storage->string_pool().GetId("/foo/bar");
ASSERT_NE(foo_bar_id, std::nullopt);
- EXPECT_THAT(context.storage->stack_profile_mapping_table().name()[0],
+ EXPECT_THAT(context.storage->stack_profile_mapping_table()[0].name(),
*foo_bar_id);
}
diff --git a/src/trace_processor/importers/proto/proto_trace_parser_impl_unittest.cc b/src/trace_processor/importers/proto/proto_trace_parser_impl_unittest.cc
index efa53c9..cbff477 100644
--- a/src/trace_processor/importers/proto/proto_trace_parser_impl_unittest.cc
+++ b/src/trace_processor/importers/proto/proto_trace_parser_impl_unittest.cc
@@ -14,33 +14,51 @@
* limitations under the License.
*/
-#include "src/trace_processor/importers/proto/proto_trace_reader.h"
+#include "src/trace_processor/importers/proto/proto_trace_parser_impl.h"
-#include "perfetto/base/logging.h"
+#include <cmath>
+#include <cstdint>
+#include <cstring>
+#include <functional>
+#include <memory>
+#include <optional>
+#include <string>
+#include <utility>
+#include <vector>
+
+#include "perfetto/base/status.h"
#include "perfetto/ext/base/string_view.h"
#include "perfetto/protozero/scattered_heap_buffer.h"
+#include "perfetto/trace_processor/basic_types.h"
#include "perfetto/trace_processor/trace_blob.h"
+#include "perfetto/trace_processor/trace_blob_view.h"
+#include "src/trace_processor/db/column/types.h"
#include "src/trace_processor/importers/common/args_tracker.h"
#include "src/trace_processor/importers/common/args_translation_table.h"
#include "src/trace_processor/importers/common/clock_tracker.h"
#include "src/trace_processor/importers/common/cpu_tracker.h"
#include "src/trace_processor/importers/common/event_tracker.h"
#include "src/trace_processor/importers/common/flow_tracker.h"
+#include "src/trace_processor/importers/common/global_args_tracker.h"
#include "src/trace_processor/importers/common/machine_tracker.h"
#include "src/trace_processor/importers/common/mapping_tracker.h"
#include "src/trace_processor/importers/common/metadata_tracker.h"
#include "src/trace_processor/importers/common/process_track_translation_table.h"
#include "src/trace_processor/importers/common/process_tracker.h"
#include "src/trace_processor/importers/common/slice_tracker.h"
+#include "src/trace_processor/importers/common/slice_translation_table.h"
#include "src/trace_processor/importers/common/stack_profile_tracker.h"
#include "src/trace_processor/importers/common/track_tracker.h"
#include "src/trace_processor/importers/ftrace/ftrace_sched_event_tracker.h"
#include "src/trace_processor/importers/proto/additional_modules.h"
#include "src/trace_processor/importers/proto/default_modules.h"
-#include "src/trace_processor/importers/proto/proto_trace_parser_impl.h"
+#include "src/trace_processor/importers/proto/proto_trace_reader.h"
#include "src/trace_processor/sorter/trace_sorter.h"
#include "src/trace_processor/storage/metadata.h"
+#include "src/trace_processor/storage/stats.h"
#include "src/trace_processor/storage/trace_storage.h"
+#include "src/trace_processor/tables/metadata_tables_py.h"
+#include "src/trace_processor/types/variadic.h"
#include "src/trace_processor/util/descriptors.h"
#include "test/gtest_and_gmock.h"
@@ -77,10 +95,10 @@
#include "protos/perfetto/trace/track_event/track_descriptor.pbzero.h"
#include "protos/perfetto/trace/track_event/track_event.pbzero.h"
-namespace perfetto {
-namespace trace_processor {
+namespace perfetto::trace_processor {
namespace {
+using ::std::make_pair;
using ::testing::_;
using ::testing::Args;
using ::testing::AtLeast;
@@ -253,12 +271,13 @@
ProtoTraceParserTest() {
storage_ = new TraceStorage();
context_.storage.reset(storage_);
- context_.track_tracker.reset(new TrackTracker(&context_));
- context_.global_args_tracker.reset(
- new GlobalArgsTracker(context_.storage.get()));
+ context_.track_tracker = std::make_unique<TrackTracker>(&context_);
+ context_.global_args_tracker =
+ std::make_unique<GlobalArgsTracker>(context_.storage.get());
context_.mapping_tracker.reset(new MappingTracker(&context_));
- context_.stack_profile_tracker.reset(new StackProfileTracker(&context_));
- context_.args_tracker.reset(new ArgsTracker(&context_));
+ context_.stack_profile_tracker =
+ std::make_unique<StackProfileTracker>(&context_);
+ context_.args_tracker = std::make_unique<ArgsTracker>(&context_);
context_.args_translation_table.reset(new ArgsTranslationTable(storage_));
context_.metadata_tracker.reset(
new MetadataTracker(context_.storage.get()));
@@ -274,14 +293,16 @@
new ProcessTrackTranslationTable(storage_));
slice_ = new NiceMock<MockSliceTracker>(&context_);
context_.slice_tracker.reset(slice_);
- context_.slice_translation_table.reset(new SliceTranslationTable(storage_));
+ context_.slice_translation_table =
+ std::make_unique<SliceTranslationTable>(storage_);
clock_ = new ClockTracker(&context_);
context_.clock_tracker.reset(clock_);
- context_.flow_tracker.reset(new FlowTracker(&context_));
- context_.proto_trace_parser.reset(new ProtoTraceParserImpl(&context_));
- context_.sorter.reset(
- new TraceSorter(&context_, TraceSorter::SortingMode::kFullSort));
- context_.descriptor_pool_.reset(new DescriptorPool());
+ context_.flow_tracker = std::make_unique<FlowTracker>(&context_);
+ context_.proto_trace_parser =
+ std::make_unique<ProtoTraceParserImpl>(&context_);
+ context_.sorter = std::make_shared<TraceSorter>(
+ &context_, TraceSorter::SortingMode::kFullSort);
+ context_.descriptor_pool_ = std::make_unique<DescriptorPool>();
RegisterDefaultModules(&context_);
RegisterAdditionalModules(&context_);
@@ -291,7 +312,7 @@
void SetUp() override { ResetTraceBuffers(); }
- util::Status Tokenize() {
+ base::Status Tokenize() {
trace_->Finalize();
std::vector<uint8_t> trace_bytes = trace_.SerializeAsArray();
std::unique_ptr<uint8_t[]> raw_trace(new uint8_t[trace_bytes.size()]);
@@ -309,12 +330,12 @@
const auto& args = storage_->arg_table();
Query q;
q.constraints = {args.arg_set_id().eq(set_id)};
- RowMap rm = args.QueryToRowMap(q);
+
bool found = false;
- for (auto it = rm.IterateRows(); it; it.Next()) {
- if (args.key()[it.index()] == key_id) {
- EXPECT_EQ(args.flat_key()[it.index()], key_id);
- if (storage_->GetArgValue(it.index()) == value) {
+ for (auto it = args.FilterToIterator(q); it; ++it) {
+ if (it.key() == key_id) {
+ EXPECT_EQ(it.flat_key(), key_id);
+ if (storage_->GetArgValue(it.row_number().row_number()) == value) {
found = true;
break;
}
@@ -401,17 +422,17 @@
std::vector<std::string> expected_keys;
for (uint32_t i = 0; i < args.row_count(); i++) {
expected_keys.push_back(
- context_.storage->GetString(args.key()[i]).ToStdString());
+ context_.storage->GetString(args[i].key()).ToStdString());
}
ASSERT_THAT(expected_keys,
testing::ElementsAre("pid", "comm", "clone_flags",
"oom_score_adj", "ip", "buf"));
- ASSERT_EQ(args.int_value()[0], 123);
- ASSERT_STREQ(args.string_value().GetString(1).c_str(), task_newtask);
- ASSERT_EQ(args.int_value()[2], 12);
- ASSERT_EQ(args.int_value()[3], 15);
- ASSERT_EQ(args.int_value()[4], 20);
- ASSERT_STREQ(args.string_value().GetString(5).c_str(), buf_value);
+ ASSERT_EQ(args[0].int_value(), 123);
+ ASSERT_EQ(context_.storage->GetString(*args[1].string_value()), task_newtask);
+ ASSERT_EQ(args[2].int_value(), 12);
+ ASSERT_EQ(args[3].int_value(), 15);
+ ASSERT_EQ(args[4].int_value(), 20);
+ ASSERT_EQ(context_.storage->GetString(*args[5].string_value()), buf_value);
// TODO(hjd): Add test ftrace event with all field types
// and test here.
@@ -449,28 +470,31 @@
const auto& raw = storage_->raw_table();
ASSERT_EQ(raw.row_count(), 1u);
- ASSERT_EQ(raw.ts()[raw.row_count() - 1], 100);
- ASSERT_EQ(storage_->thread_table().tid()[raw.utid()[raw.row_count() - 1]],
+ ASSERT_EQ(raw[raw.row_count() - 1].ts(), 100);
+ ASSERT_EQ(storage_->thread_table()[raw[raw.row_count() - 1].utid()].tid(),
10u);
- ASSERT_EQ(raw.name().GetString(raw.row_count() - 1), "Test");
+ ASSERT_EQ(storage_->GetString(raw[raw.row_count() - 1].name()), "Test");
- auto set_id = raw.arg_set_id()[raw.row_count() - 1];
+ auto set_id = raw[raw.row_count() - 1].arg_set_id();
const auto& args = storage_->arg_table();
Query q;
q.constraints = {args.arg_set_id().eq(set_id)};
- RowMap rm = args.QueryToRowMap(q);
- auto row = rm.Get(0);
+ auto it = args.FilterToIterator(q);
+ ASSERT_TRUE(it);
- ASSERT_EQ(args.key().GetString(row), "meta1");
- ASSERT_EQ(args.string_value().GetString(row++), "value1");
+ ASSERT_EQ(storage_->GetString(it.key()), "meta1");
+ ASSERT_EQ(storage_->GetString(*it.string_value()), "value1");
+ ASSERT_TRUE(++it);
- ASSERT_EQ(args.key().GetString(row), "meta2");
- ASSERT_EQ(args.int_value()[row++], -2);
+ ASSERT_EQ(storage_->GetString(it.key()), "meta2");
+ ASSERT_EQ(it.int_value(), -2);
+ ASSERT_TRUE(++it);
- ASSERT_EQ(args.key().GetString(row), "meta3");
- ASSERT_EQ(args.int_value()[row++], 3);
+ ASSERT_EQ(storage_->GetString(it.key()), "meta3");
+ ASSERT_EQ(it.int_value(), 3);
+ ASSERT_FALSE(++it);
}
TEST_F(ProtoTraceParserTest, LoadMultipleEvents) {
@@ -620,7 +644,7 @@
Tokenize();
context_.sorter->ExtractEventsForced();
- EXPECT_EQ(context_.storage->cpu_counter_track_table().ucpu()[0].value, 10u);
+ EXPECT_EQ(context_.storage->cpu_counter_track_table()[0].ucpu().value, 10u);
}
TEST_F(ProtoTraceParserTest, LoadCpuFreqKHz) {
@@ -947,14 +971,14 @@
context_.sorter->ExtractEventsForced();
EXPECT_EQ(storage_->slice_table().row_count(), 2u);
- auto id_0 = storage_->slice_table().id().IndexOf(SliceId(0u));
- EXPECT_TRUE(id_0);
- EXPECT_EQ(storage_->slice_table().thread_ts()[*id_0], 2003000);
- EXPECT_EQ(storage_->slice_table().thread_dur()[*id_0], 12000);
- auto id_1 = storage_->slice_table().id().IndexOf(SliceId(1u));
- EXPECT_TRUE(id_1);
- EXPECT_EQ(storage_->slice_table().thread_ts()[*id_1], 2005000);
- EXPECT_EQ(storage_->slice_table().thread_dur()[*id_1], 5000);
+ auto rr_0 = storage_->slice_table().FindById(SliceId(0u));
+ EXPECT_TRUE(rr_0);
+ EXPECT_EQ(rr_0->thread_ts(), 2003000);
+ EXPECT_EQ(rr_0->thread_dur(), 12000);
+ auto rr_1 = storage_->slice_table().FindById(SliceId(1u));
+ EXPECT_TRUE(rr_1);
+ EXPECT_EQ(rr_1->thread_ts(), 2005000);
+ EXPECT_EQ(rr_1->thread_dur(), 5000);
}
TEST_F(ProtoTraceParserTest, TrackEventWithoutInternedDataWithTypes) {
@@ -1036,14 +1060,14 @@
context_.sorter->ExtractEventsForced();
EXPECT_EQ(storage_->slice_table().row_count(), 2u);
- auto id_0 = storage_->slice_table().id().IndexOf(SliceId(0u));
- EXPECT_TRUE(id_0);
- EXPECT_EQ(storage_->slice_table().thread_ts()[*id_0], 2005000);
- EXPECT_EQ(storage_->slice_table().thread_dur()[*id_0], 5000);
- auto id_1 = storage_->slice_table().id().IndexOf(SliceId(1u));
- EXPECT_TRUE(id_1);
- EXPECT_EQ(storage_->slice_table().thread_ts()[*id_1], 2007000);
- EXPECT_EQ(storage_->slice_table().thread_dur()[*id_1], 0);
+ auto rr_0 = storage_->slice_table().FindById(SliceId(0u));
+ EXPECT_TRUE(rr_0);
+ EXPECT_EQ(rr_0->thread_ts(), 2005000);
+ EXPECT_EQ(rr_0->thread_dur(), 5000);
+ auto rr_1 = storage_->slice_table().FindById(SliceId(1u));
+ EXPECT_TRUE(rr_1);
+ EXPECT_EQ(rr_1->thread_ts(), 2007000);
+ EXPECT_EQ(rr_1->thread_dur(), 0);
}
TEST_F(ProtoTraceParserTest, TrackEventWithInternedData) {
@@ -1071,10 +1095,10 @@
legacy_event->set_phase('B');
auto* interned_data = packet->set_interned_data();
- auto cat1 = interned_data->add_event_categories();
+ auto* cat1 = interned_data->add_event_categories();
cat1->set_iid(1);
cat1->set_name("cat1");
- auto ev1 = interned_data->add_event_names();
+ auto* ev1 = interned_data->add_event_names();
ev1->set_iid(1);
ev1->set_name("ev1");
}
@@ -1134,13 +1158,13 @@
protos::pbzero::TrackEvent::LegacyEvent::FLOW_OUT);
auto* interned_data = packet->set_interned_data();
- auto cat2 = interned_data->add_event_categories();
+ auto* cat2 = interned_data->add_event_categories();
cat2->set_iid(2);
cat2->set_name("cat2");
- auto cat3 = interned_data->add_event_categories();
+ auto* cat3 = interned_data->add_event_categories();
cat3->set_iid(3);
cat3->set_name("cat3");
- auto ev2 = interned_data->add_event_names();
+ auto* ev2 = interned_data->add_event_names();
ev2->set_iid(4);
ev2->set_name("ev2");
}
@@ -1235,24 +1259,24 @@
context_.sorter->ExtractEventsForced();
EXPECT_EQ(storage_->slice_table().row_count(), 3u);
- auto id_0 = storage_->slice_table().id().IndexOf(SliceId(0u));
- EXPECT_TRUE(id_0);
- EXPECT_EQ(storage_->slice_table().thread_ts()[*id_0], 2003000);
- EXPECT_EQ(storage_->slice_table().thread_dur()[*id_0], 12000);
- EXPECT_EQ(storage_->slice_table().thread_instruction_count()[*id_0], 3010);
- EXPECT_EQ(storage_->slice_table().thread_instruction_delta()[*id_0], 50);
- auto id_1 = storage_->slice_table().id().IndexOf(SliceId(1u));
- EXPECT_TRUE(id_1);
- EXPECT_EQ(storage_->slice_table().thread_ts()[*id_1], 2005000);
- EXPECT_EQ(storage_->slice_table().thread_dur()[*id_1], 5000);
- EXPECT_EQ(storage_->slice_table().thread_instruction_count()[*id_1], 3020);
- EXPECT_EQ(storage_->slice_table().thread_instruction_delta()[*id_1], 20);
- auto id_2 = storage_->slice_table().id().IndexOf(SliceId(2u));
- EXPECT_TRUE(id_2);
- EXPECT_EQ(storage_->slice_table().thread_ts()[*id_2], 2030000);
- EXPECT_EQ(storage_->slice_table().thread_dur()[*id_2], 0);
- EXPECT_EQ(storage_->slice_table().thread_instruction_count()[*id_2], 3100);
- EXPECT_EQ(storage_->slice_table().thread_instruction_delta()[*id_2], 0);
+ auto rr_0 = storage_->slice_table().FindById(SliceId(0u));
+ EXPECT_TRUE(rr_0);
+ EXPECT_EQ(rr_0->thread_ts(), 2003000);
+ EXPECT_EQ(rr_0->thread_dur(), 12000);
+ EXPECT_EQ(rr_0->thread_instruction_count(), 3010);
+ EXPECT_EQ(rr_0->thread_instruction_delta(), 50);
+ auto rr_1 = storage_->slice_table().FindById(SliceId(1u));
+ EXPECT_TRUE(rr_1);
+ EXPECT_EQ(rr_1->thread_ts(), 2005000);
+ EXPECT_EQ(rr_1->thread_dur(), 5000);
+ EXPECT_EQ(rr_1->thread_instruction_count(), 3020);
+ EXPECT_EQ(rr_1->thread_instruction_delta(), 20);
+ auto rr_2 = storage_->slice_table().FindById(SliceId(2u));
+ EXPECT_TRUE(rr_2);
+ EXPECT_EQ(rr_2->thread_ts(), 2030000);
+ EXPECT_EQ(rr_2->thread_dur(), 0);
+ EXPECT_EQ(rr_2->thread_instruction_count(), 3100);
+ EXPECT_EQ(rr_2->thread_instruction_delta(), 0);
}
TEST_F(ProtoTraceParserTest, TrackEventAsyncEvents) {
@@ -1282,10 +1306,10 @@
legacy_event->set_use_async_tts(true);
auto* interned_data = packet->set_interned_data();
- auto cat1 = interned_data->add_event_categories();
+ auto* cat1 = interned_data->add_event_categories();
cat1->set_iid(1);
cat1->set_name("cat1");
- auto ev1 = interned_data->add_event_names();
+ auto* ev1 = interned_data->add_event_names();
ev1->set_iid(1);
ev1->set_name("ev1");
}
@@ -1315,7 +1339,7 @@
legacy_event->set_global_id(10);
auto* interned_data = packet->set_interned_data();
- auto ev2 = interned_data->add_event_names();
+ auto* ev2 = interned_data->add_event_names();
ev2->set_iid(2);
ev2->set_name("ev2");
}
@@ -1332,7 +1356,7 @@
legacy_event->set_global_id(15);
auto* interned_data = packet->set_interned_data();
- auto cat2 = interned_data->add_event_categories();
+ auto* cat2 = interned_data->add_event_categories();
cat2->set_iid(2);
cat2->set_name("cat2");
}
@@ -1388,14 +1412,14 @@
// First track is for the thread; second first async, third and fourth for
// thread time and instruction count, others are the async event tracks.
EXPECT_EQ(storage_->track_table().row_count(), 6u);
- EXPECT_EQ(storage_->track_table().name()[1], ev_1);
- EXPECT_EQ(storage_->track_table().name()[4], ev_2);
- EXPECT_EQ(storage_->track_table().name()[5], ev_2);
+ EXPECT_EQ(storage_->track_table()[1].name(), ev_1);
+ EXPECT_EQ(storage_->track_table()[4].name(), ev_2);
+ EXPECT_EQ(storage_->track_table()[5].name(), ev_2);
EXPECT_EQ(storage_->process_track_table().row_count(), 3u);
- EXPECT_EQ(storage_->process_track_table().upid()[0], 1u);
- EXPECT_EQ(storage_->process_track_table().upid()[1], 1u);
- EXPECT_EQ(storage_->process_track_table().upid()[2], 1u);
+ EXPECT_EQ(storage_->process_track_table()[0].upid(), 1u);
+ EXPECT_EQ(storage_->process_track_table()[1].upid(), 1u);
+ EXPECT_EQ(storage_->process_track_table()[2].upid(), 1u);
EXPECT_EQ(storage_->virtual_track_slices().slice_count(), 1u);
EXPECT_EQ(storage_->virtual_track_slices().slice_ids()[0], SliceId(0u));
@@ -1449,10 +1473,10 @@
legacy_event->set_use_async_tts(true);
auto* interned_data = packet->set_interned_data();
- auto cat1 = interned_data->add_event_categories();
+ auto* cat1 = interned_data->add_event_categories();
cat1->set_iid(1);
cat1->set_name("cat1");
- auto ev1 = interned_data->add_event_names();
+ auto* ev1 = interned_data->add_event_names();
ev1->set_iid(1);
ev1->set_name("ev1");
}
@@ -1469,10 +1493,10 @@
event->set_type(protos::pbzero::TrackEvent::TYPE_INSTANT);
auto* interned_data = packet->set_interned_data();
- auto cat1 = interned_data->add_event_categories();
+ auto* cat1 = interned_data->add_event_categories();
cat1->set_iid(2);
cat1->set_name("cat2");
- auto ev1 = interned_data->add_event_names();
+ auto* ev1 = interned_data->add_event_names();
ev1->set_iid(2);
ev1->set_name("ev2");
}
@@ -1516,10 +1540,10 @@
event->set_type(protos::pbzero::TrackEvent::TYPE_INSTANT);
auto* interned_data = packet->set_interned_data();
- auto cat1 = interned_data->add_event_categories();
+ auto* cat1 = interned_data->add_event_categories();
cat1->set_iid(1);
cat1->set_name("cat3");
- auto ev1 = interned_data->add_event_names();
+ auto* ev1 = interned_data->add_event_names();
ev1->set_iid(1);
ev1->set_name("ev3");
}
@@ -1575,12 +1599,15 @@
// default track (parent of async track), fourth is "Thread track 2", fifth &
// sixth are thread time tracks for thread 1 and 2.
EXPECT_EQ(storage_->track_table().row_count(), 5u);
- EXPECT_EQ(storage_->track_table().name().GetString(0), "Thread track 1");
- EXPECT_EQ(storage_->track_table().name().GetString(1), "Async track 1");
- EXPECT_EQ(storage_->track_table().name().GetString(2), "Thread track 2");
+ EXPECT_EQ(storage_->GetString((storage_->track_table()[0].name())),
+ "Thread track 1");
+ EXPECT_EQ(storage_->GetString((storage_->track_table()[1].name())),
+ "Async track 1");
+ EXPECT_EQ(storage_->GetString((storage_->track_table()[2].name())),
+ "Thread track 2");
EXPECT_EQ(storage_->thread_track_table().row_count(), 2u);
- EXPECT_EQ(storage_->thread_track_table().utid()[0], 1u);
- EXPECT_EQ(storage_->thread_track_table().utid()[1], 2u);
+ EXPECT_EQ(storage_->thread_track_table()[0].utid(), 1u);
+ EXPECT_EQ(storage_->thread_track_table()[1].utid(), 2u);
EXPECT_EQ(storage_->virtual_track_slices().slice_count(), 1u);
EXPECT_EQ(storage_->virtual_track_slices().slice_ids()[0], SliceId(2u));
@@ -1592,19 +1619,19 @@
20);
EXPECT_EQ(storage_->slice_table().row_count(), 2u);
- auto id_0 = storage_->slice_table().id().IndexOf(SliceId(0u));
- EXPECT_TRUE(id_0);
- EXPECT_EQ(storage_->slice_table().thread_ts()[*id_0], 2007000);
- EXPECT_EQ(storage_->slice_table().thread_dur()[*id_0], 0);
+ auto rr_0 = storage_->slice_table().FindById(SliceId(0u));
+ EXPECT_TRUE(rr_0);
+ EXPECT_EQ(rr_0->thread_ts(), 2007000);
+ EXPECT_EQ(rr_0->thread_dur(), 0);
// There was no thread instructions in the packets above.
- EXPECT_FALSE(storage_->slice_table().thread_instruction_count()[*id_0]);
- EXPECT_FALSE(storage_->slice_table().thread_instruction_delta()[*id_0]);
- auto id_1 = storage_->slice_table().id().IndexOf(SliceId(1u));
- EXPECT_TRUE(id_1);
- EXPECT_EQ(storage_->slice_table().thread_ts()[*id_1], 2008000);
- EXPECT_EQ(storage_->slice_table().thread_dur()[*id_1], 0);
- EXPECT_FALSE(storage_->slice_table().thread_instruction_count()[*id_1]);
- EXPECT_FALSE(storage_->slice_table().thread_instruction_delta()[*id_1]);
+ EXPECT_FALSE(rr_0->thread_instruction_count());
+ EXPECT_FALSE(rr_0->thread_instruction_delta());
+ auto rr_1 = storage_->slice_table().FindById(SliceId(1u));
+ EXPECT_TRUE(rr_1);
+ EXPECT_EQ(rr_1->thread_ts(), 2008000);
+ EXPECT_EQ(rr_1->thread_dur(), 0);
+ EXPECT_FALSE(rr_1->thread_instruction_count());
+ EXPECT_FALSE(rr_1->thread_instruction_delta());
}
TEST_F(ProtoTraceParserTest, TrackEventWithResortedCounterDescriptor) {
@@ -1697,14 +1724,14 @@
// First track is thread time track, second is "t1".
EXPECT_EQ(storage_->track_table().row_count(), 2u);
EXPECT_EQ(storage_->thread_track_table().row_count(), 1u);
- EXPECT_EQ(storage_->thread_track_table().utid()[0], 1u);
+ EXPECT_EQ(storage_->thread_track_table()[0].utid(), 1u);
// Counter values should also be imported into thread slices.
EXPECT_EQ(storage_->slice_table().row_count(), 1u);
- auto id_0 = storage_->slice_table().id().IndexOf(SliceId(0u));
- EXPECT_TRUE(id_0);
- EXPECT_EQ(storage_->slice_table().thread_ts()[*id_0], 1000000);
- EXPECT_EQ(storage_->slice_table().thread_dur()[*id_0], 10000);
+ auto rr_0 = storage_->slice_table().FindById(SliceId(0u));
+ EXPECT_TRUE(rr_0);
+ EXPECT_EQ(rr_0->thread_ts(), 1000000);
+ EXPECT_EQ(rr_0->thread_dur(), 10000);
}
TEST_F(ProtoTraceParserTest, TrackEventWithoutIncrementalStateReset) {
@@ -1916,10 +1943,10 @@
legacy_event->set_phase('B');
auto* interned_data = packet->set_interned_data();
- auto cat1 = interned_data->add_event_categories();
+ auto* cat1 = interned_data->add_event_categories();
cat1->set_iid(1);
cat1->set_name("cat1");
- auto ev1 = interned_data->add_event_names();
+ auto* ev1 = interned_data->add_event_names();
ev1->set_iid(1);
ev1->set_name("ev1");
}
@@ -1943,10 +1970,10 @@
legacy_event->set_phase('B');
auto* interned_data = packet->set_interned_data();
- auto cat1 = interned_data->add_event_categories();
+ auto* cat1 = interned_data->add_event_categories();
cat1->set_iid(1);
cat1->set_name("cat1");
- auto ev2 = interned_data->add_event_names();
+ auto* ev2 = interned_data->add_event_names();
ev2->set_iid(1);
ev2->set_name("ev2");
}
@@ -2051,16 +2078,16 @@
legacy_event->set_phase('B');
auto* interned_data = packet->set_interned_data();
- auto cat1 = interned_data->add_event_categories();
+ auto* cat1 = interned_data->add_event_categories();
cat1->set_iid(1);
cat1->set_name("cat1");
- auto ev1 = interned_data->add_event_names();
+ auto* ev1 = interned_data->add_event_names();
ev1->set_iid(1);
ev1->set_name("ev1");
- auto an1 = interned_data->add_debug_annotation_names();
+ auto* an1 = interned_data->add_debug_annotation_names();
an1->set_iid(1);
an1->set_name("an1");
- auto an2 = interned_data->add_debug_annotation_names();
+ auto* an2 = interned_data->add_debug_annotation_names();
an2->set_iid(2);
an2->set_name("an2");
}
@@ -2097,25 +2124,25 @@
legacy_event->set_phase('E');
auto* interned_data = packet->set_interned_data();
- auto an3 = interned_data->add_debug_annotation_names();
+ auto* an3 = interned_data->add_debug_annotation_names();
an3->set_iid(3);
an3->set_name("an3");
- auto an4 = interned_data->add_debug_annotation_names();
+ auto* an4 = interned_data->add_debug_annotation_names();
an4->set_iid(4);
an4->set_name("an4");
- auto an5 = interned_data->add_debug_annotation_names();
+ auto* an5 = interned_data->add_debug_annotation_names();
an5->set_iid(5);
an5->set_name("an5");
- auto an6 = interned_data->add_debug_annotation_names();
+ auto* an6 = interned_data->add_debug_annotation_names();
an6->set_iid(6);
an6->set_name("an6");
- auto an7 = interned_data->add_debug_annotation_names();
+ auto* an7 = interned_data->add_debug_annotation_names();
an7->set_iid(7);
an7->set_name("an7");
- auto an8 = interned_data->add_debug_annotation_names();
+ auto* an8 = interned_data->add_debug_annotation_names();
an8->set_iid(8);
an8->set_name("an8");
- auto an9 = interned_data->add_debug_annotation_names();
+ auto* an9 = interned_data->add_debug_annotation_names();
an9->set_iid(9);
an9->set_name("an8.foo");
}
@@ -2224,13 +2251,13 @@
legacy_event->set_phase('B');
auto* interned_data = packet->set_interned_data();
- auto cat1 = interned_data->add_event_categories();
+ auto* cat1 = interned_data->add_event_categories();
cat1->set_iid(1);
cat1->set_name("cat1");
- auto ev1 = interned_data->add_event_names();
+ auto* ev1 = interned_data->add_event_names();
ev1->set_iid(1);
ev1->set_name("ev1");
- auto loc1 = interned_data->add_source_locations();
+ auto* loc1 = interned_data->add_source_locations();
loc1->set_iid(1);
loc1->set_file_name("file1");
loc1->set_function_name("func1");
@@ -2289,19 +2316,19 @@
legacy_event->set_phase('I');
auto* interned_data = packet->set_interned_data();
- auto cat1 = interned_data->add_event_categories();
+ auto* cat1 = interned_data->add_event_categories();
cat1->set_iid(1);
cat1->set_name("cat1");
- auto ev1 = interned_data->add_event_names();
+ auto* ev1 = interned_data->add_event_names();
ev1->set_iid(1);
ev1->set_name("ev1");
- auto body = interned_data->add_log_message_body();
+ auto* body = interned_data->add_log_message_body();
body->set_iid(1);
body->set_body("body1");
- auto loc1 = interned_data->add_source_locations();
+ auto* loc1 = interned_data->add_source_locations();
loc1->set_iid(1);
loc1->set_file_name("file1");
loc1->set_function_name("func1");
@@ -2338,9 +2365,9 @@
context_.sorter->ExtractEventsForced();
EXPECT_GT(context_.storage->android_log_table().row_count(), 0u);
- EXPECT_EQ(context_.storage->android_log_table().ts()[0], 1010000);
- EXPECT_EQ(context_.storage->android_log_table().msg()[0], body_1);
- EXPECT_EQ(context_.storage->android_log_table().tag()[0], source_location_id);
+ EXPECT_EQ(context_.storage->android_log_table()[0].ts(), 1010000);
+ EXPECT_EQ(context_.storage->android_log_table()[0].msg(), body_1);
+ EXPECT_EQ(context_.storage->android_log_table()[0].tag(), source_location_id);
}
TEST_F(ProtoTraceParserTest, TrackEventParseLegacyEventIntoRawTable) {
@@ -2377,13 +2404,13 @@
annotation1->set_uint_value(10u);
auto* interned_data = packet->set_interned_data();
- auto cat1 = interned_data->add_event_categories();
+ auto* cat1 = interned_data->add_event_categories();
cat1->set_iid(1);
cat1->set_name("cat1");
- auto ev1 = interned_data->add_event_names();
+ auto* ev1 = interned_data->add_event_names();
ev1->set_iid(1);
ev1->set_name("ev1");
- auto an1 = interned_data->add_debug_annotation_names();
+ auto* an1 = interned_data->add_debug_annotation_names();
an1->set_iid(1);
an1->set_name("an1");
}
@@ -2412,14 +2439,14 @@
// Verify raw_table and args contents.
const auto& raw_table = storage_->raw_table();
EXPECT_EQ(raw_table.row_count(), 1u);
- EXPECT_EQ(raw_table.ts()[0], 1010000);
- EXPECT_EQ(raw_table.name()[0],
+ EXPECT_EQ(raw_table[0].ts(), 1010000);
+ EXPECT_EQ(raw_table[0].name(),
storage_->InternString("track_event.legacy_event"));
- auto ucpu = raw_table.ucpu()[0];
+ auto ucpu = raw_table[0].ucpu();
const auto& cpu_table = storage_->cpu_table();
- EXPECT_EQ(cpu_table.cpu()[ucpu.value], 0u);
- EXPECT_EQ(raw_table.utid()[0], 1u);
- EXPECT_EQ(raw_table.arg_set_id()[0], 1u);
+ EXPECT_EQ(cpu_table[ucpu.value].cpu(), 0u);
+ EXPECT_EQ(raw_table[0].utid(), 1u);
+ EXPECT_EQ(raw_table[0].arg_set_id(), 1u);
EXPECT_GE(storage_->arg_table().row_count(), 10u);
@@ -2499,7 +2526,7 @@
metadata->set_int_value(23);
}
- util::Status status = Tokenize();
+ base::Status status = Tokenize();
EXPECT_TRUE(status.ok());
context_.sorter->ExtractEventsForced();
@@ -2534,9 +2561,9 @@
// Verify raw_table and args contents.
const auto& raw_table = storage_->raw_table();
EXPECT_EQ(raw_table.row_count(), 1u);
- EXPECT_EQ(raw_table.name()[0],
+ EXPECT_EQ(raw_table[0].name(),
storage_->InternString("chrome_event.metadata"));
- EXPECT_EQ(raw_table.arg_set_id()[0], 1u);
+ EXPECT_EQ(raw_table[0].arg_set_id(), 1u);
EXPECT_EQ(storage_->arg_table().row_count(), 2u);
EXPECT_TRUE(HasArg(1u, storage_->InternString(kStringName),
@@ -2565,9 +2592,9 @@
// Verify raw_table and args contents.
const auto& raw_table = storage_->raw_table();
EXPECT_EQ(raw_table.row_count(), 1u);
- EXPECT_EQ(raw_table.name()[0],
+ EXPECT_EQ(raw_table[0].name(),
storage_->InternString("chrome_event.legacy_system_trace"));
- EXPECT_EQ(raw_table.arg_set_id()[0], 1u);
+ EXPECT_EQ(raw_table[0].arg_set_id(), 1u);
EXPECT_EQ(storage_->arg_table().row_count(), 1u);
EXPECT_TRUE(HasArg(1u, storage_->InternString("data"),
@@ -2593,9 +2620,9 @@
// Verify raw_table and args contents.
const auto& raw_table = storage_->raw_table();
EXPECT_EQ(raw_table.row_count(), 1u);
- EXPECT_EQ(raw_table.name()[0],
+ EXPECT_EQ(raw_table[0].name(),
storage_->InternString("chrome_event.legacy_user_trace"));
- EXPECT_EQ(raw_table.arg_set_id()[0], 1u);
+ EXPECT_EQ(raw_table[0].arg_set_id(), 1u);
EXPECT_EQ(storage_->arg_table().row_count(), 1u);
EXPECT_TRUE(
@@ -2619,18 +2646,15 @@
base::StringView tags = metadata::kNames[metadata::benchmark_story_tags];
context_.sorter->ExtractEventsForced();
-
- const auto& meta_keys = storage_->metadata_table().name();
- const auto& meta_values = storage_->metadata_table().str_value();
EXPECT_EQ(storage_->metadata_table().row_count(), 3u);
std::vector<std::pair<base::StringView, base::StringView>> meta_entries;
- for (uint32_t i = 0; i < storage_->metadata_table().row_count(); i++) {
- meta_entries.emplace_back(
- std::make_pair(meta_keys.GetString(i), meta_values.GetString(i)));
+ for (auto it = storage_->metadata_table().IterateRows(); it; ++it) {
+ meta_entries.emplace_back(storage_->GetString(it.name()),
+ storage_->GetString(*it.str_value()));
}
EXPECT_THAT(meta_entries,
- UnorderedElementsAreArray({std::make_pair(benchmark, kName),
+ UnorderedElementsAreArray({make_pair(benchmark, kName),
std::make_pair(tags, kTag1),
std::make_pair(tags, kTag2)}));
}
@@ -2666,17 +2690,18 @@
const auto& metadata = storage_->metadata_table();
- EXPECT_STREQ(metadata.name().GetString(0).c_str(), "cr-str_name");
- EXPECT_STREQ(metadata.str_value().GetString(0).c_str(), "foostr");
+ EXPECT_STREQ(storage_->GetString(metadata[0].name()).c_str(), "cr-str_name");
+ EXPECT_STREQ(storage_->GetString(*metadata[0].str_value()).c_str(), "foostr");
- EXPECT_STREQ(metadata.name().GetString(1).c_str(), "cr-int_name");
- EXPECT_EQ(metadata.int_value()[1], 42);
+ EXPECT_STREQ(storage_->GetString(metadata[1].name()).c_str(), "cr-int_name");
+ EXPECT_EQ(metadata[1].int_value(), 42);
- EXPECT_STREQ(metadata.name().GetString(2).c_str(), "cr-bool_name");
- EXPECT_EQ(metadata.int_value()[2], 1);
+ EXPECT_STREQ(storage_->GetString(metadata[2].name()).c_str(), "cr-bool_name");
+ EXPECT_EQ(metadata[2].int_value(), 1);
- EXPECT_STREQ(metadata.name().GetString(3).c_str(), "cr-json_name");
- EXPECT_STREQ(metadata.str_value().GetString(3).c_str(), "{key: value}");
+ EXPECT_STREQ(storage_->GetString(metadata[3].name()).c_str(), "cr-json_name");
+ EXPECT_STREQ(storage_->GetString(*metadata[3].str_value()).c_str(),
+ "{key: value}");
}
TEST_F(ProtoTraceParserTest, AndroidPackagesList) {
@@ -2717,19 +2742,19 @@
const auto& package_list = context_.storage->package_list_table();
ASSERT_EQ(package_list.row_count(), 2u);
- EXPECT_STREQ(storage_->GetString(package_list.package_name()[0]).c_str(),
+ EXPECT_STREQ(storage_->GetString(package_list[0].package_name()).c_str(),
"com.test.app");
- EXPECT_EQ(package_list.uid()[0], 1000u);
- EXPECT_EQ(package_list.debuggable()[0], false);
- EXPECT_EQ(package_list.profileable_from_shell()[0], true);
- EXPECT_EQ(package_list.version_code()[0], 42);
+ EXPECT_EQ(package_list[0].uid(), 1000u);
+ EXPECT_EQ(package_list[0].debuggable(), false);
+ EXPECT_EQ(package_list[0].profileable_from_shell(), true);
+ EXPECT_EQ(package_list[0].version_code(), 42);
- EXPECT_STREQ(storage_->GetString(package_list.package_name()[1]).c_str(),
+ EXPECT_STREQ(storage_->GetString(package_list[1].package_name()).c_str(),
"com.test.app2");
- EXPECT_EQ(package_list.uid()[1], 1001u);
- EXPECT_EQ(package_list.debuggable()[1], false);
- EXPECT_EQ(package_list.profileable_from_shell()[1], false);
- EXPECT_EQ(package_list.version_code()[1], 43);
+ EXPECT_EQ(package_list[1].uid(), 1001u);
+ EXPECT_EQ(package_list[1].debuggable(), false);
+ EXPECT_EQ(package_list[1].profileable_from_shell(), false);
+ EXPECT_EQ(package_list[1].version_code(), 43);
}
TEST_F(ProtoTraceParserTest, AndroidPackagesListDuplicate) {
@@ -2770,12 +2795,12 @@
const auto& package_list = context_.storage->package_list_table();
ASSERT_EQ(package_list.row_count(), 1u);
- EXPECT_STREQ(storage_->GetString(package_list.package_name()[0]).c_str(),
+ EXPECT_STREQ(storage_->GetString(package_list[0].package_name()).c_str(),
"com.test.app");
- EXPECT_EQ(package_list.uid()[0], 1000u);
- EXPECT_EQ(package_list.debuggable()[0], false);
- EXPECT_EQ(package_list.profileable_from_shell()[0], true);
- EXPECT_EQ(package_list.version_code()[0], 42);
+ EXPECT_EQ(package_list[0].uid(), 1000u);
+ EXPECT_EQ(package_list[0].debuggable(), false);
+ EXPECT_EQ(package_list[0].profileable_from_shell(), true);
+ EXPECT_EQ(package_list[0].version_code(), 42);
}
TEST_F(ProtoTraceParserTest, ParseCPUProfileSamplesIntoTable) {
@@ -2792,29 +2817,29 @@
auto* interned_data = packet->set_interned_data();
- auto mapping = interned_data->add_mappings();
+ auto* mapping = interned_data->add_mappings();
mapping->set_iid(1);
mapping->set_build_id(1);
- auto build_id = interned_data->add_build_ids();
+ auto* build_id = interned_data->add_build_ids();
build_id->set_iid(1);
build_id->set_str("3BBCFBD372448A727265C3E7C4D954F91");
- auto frame = interned_data->add_frames();
+ auto* frame = interned_data->add_frames();
frame->set_iid(1);
frame->set_rel_pc(0x42);
frame->set_mapping_id(1);
- auto frame2 = interned_data->add_frames();
+ auto* frame2 = interned_data->add_frames();
frame2->set_iid(2);
frame2->set_rel_pc(0x4242);
frame2->set_mapping_id(1);
- auto callstack = interned_data->add_callstacks();
+ auto* callstack = interned_data->add_callstacks();
callstack->set_iid(1);
callstack->add_frame_ids(1);
- auto callstack2 = interned_data->add_callstacks();
+ auto* callstack2 = interned_data->add_callstacks();
callstack2->set_iid(42);
callstack2->add_frame_ids(2);
}
@@ -2851,25 +2876,25 @@
const auto& samples = storage_->cpu_profile_stack_sample_table();
EXPECT_EQ(samples.row_count(), 3u);
- EXPECT_EQ(samples.ts()[0], 11000);
- EXPECT_EQ(samples.callsite_id()[0], CallsiteId{0});
- EXPECT_EQ(samples.utid()[0], 1u);
- EXPECT_EQ(samples.process_priority()[0], 20);
+ EXPECT_EQ(samples[0].ts(), 11000);
+ EXPECT_EQ(samples[0].callsite_id(), CallsiteId{0});
+ EXPECT_EQ(samples[0].utid(), 1u);
+ EXPECT_EQ(samples[0].process_priority(), 20);
- EXPECT_EQ(samples.ts()[1], 26000);
- EXPECT_EQ(samples.callsite_id()[1], CallsiteId{1});
- EXPECT_EQ(samples.utid()[1], 1u);
- EXPECT_EQ(samples.process_priority()[1], 20);
+ EXPECT_EQ(samples[1].ts(), 26000);
+ EXPECT_EQ(samples[1].callsite_id(), CallsiteId{1});
+ EXPECT_EQ(samples[1].utid(), 1u);
+ EXPECT_EQ(samples[1].process_priority(), 20);
- EXPECT_EQ(samples.ts()[2], 68000);
- EXPECT_EQ(samples.callsite_id()[2], CallsiteId{0});
- EXPECT_EQ(samples.utid()[2], 1u);
- EXPECT_EQ(samples.process_priority()[2], 30);
+ EXPECT_EQ(samples[2].ts(), 68000);
+ EXPECT_EQ(samples[2].callsite_id(), CallsiteId{0});
+ EXPECT_EQ(samples[2].utid(), 1u);
+ EXPECT_EQ(samples[2].process_priority(), 30);
// Breakpad build_ids should not be modified/mangled.
ASSERT_STREQ(
context_.storage
- ->GetString(storage_->stack_profile_mapping_table().build_id()[0])
+ ->GetString(storage_->stack_profile_mapping_table()[0].build_id())
.c_str(),
"3BBCFBD372448A727265C3E7C4D954F91");
}
@@ -2902,20 +2927,20 @@
auto* interned_data = packet->set_interned_data();
- auto mapping = interned_data->add_mappings();
+ auto* mapping = interned_data->add_mappings();
mapping->set_iid(1);
mapping->set_build_id(1);
- auto build_id = interned_data->add_build_ids();
+ auto* build_id = interned_data->add_build_ids();
build_id->set_iid(1);
build_id->set_str("3BBCFBD372448A727265C3E7C4D954F91");
- auto frame = interned_data->add_frames();
+ auto* frame = interned_data->add_frames();
frame->set_iid(1);
frame->set_rel_pc(0x42);
frame->set_mapping_id(1);
- auto callstack = interned_data->add_callstacks();
+ auto* callstack = interned_data->add_callstacks();
callstack->set_iid(1);
callstack->add_frame_ids(1);
}
@@ -2938,9 +2963,9 @@
EXPECT_EQ(samples.row_count(), 1u);
// Should have been translated to boottime, i.e. 10015 us absolute.
- EXPECT_EQ(samples.ts()[0], 10015000);
- EXPECT_EQ(samples.callsite_id()[0], CallsiteId{0});
- EXPECT_EQ(samples.utid()[0], 1u);
+ EXPECT_EQ(samples[0].ts(), 10015000);
+ EXPECT_EQ(samples[0].callsite_id(), CallsiteId{0});
+ EXPECT_EQ(samples[0].utid(), 1u);
}
TEST_F(ProtoTraceParserTest, ConfigUuid) {
@@ -3005,5 +3030,4 @@
}
} // namespace
-} // namespace trace_processor
-} // namespace perfetto
+} // namespace perfetto::trace_processor
diff --git a/src/trace_processor/importers/proto/track_event_parser.cc b/src/trace_processor/importers/proto/track_event_parser.cc
index b9509a0..01b5313 100644
--- a/src/trace_processor/importers/proto/track_event_parser.cc
+++ b/src/trace_processor/importers/proto/track_event_parser.cc
@@ -16,41 +16,51 @@
#include "src/trace_processor/importers/proto/track_event_parser.h"
-#include <iostream>
+#include <cstddef>
+#include <cstdint>
#include <optional>
#include <string>
+#include <utility>
+#include <vector>
#include "perfetto/base/logging.h"
#include "perfetto/base/status.h"
-#include "perfetto/ext/base/base64.h"
+#include "perfetto/ext/base/string_view.h"
#include "perfetto/ext/base/string_writer.h"
+#include "perfetto/protozero/field.h"
+#include "perfetto/protozero/proto_decoder.h"
+#include "perfetto/public/compiler.h"
+#include "perfetto/trace_processor/basic_types.h"
#include "perfetto/trace_processor/status.h"
+#include "src/trace_processor/containers/null_term_string_view.h"
+#include "src/trace_processor/containers/string_pool.h"
#include "src/trace_processor/importers/common/args_tracker.h"
#include "src/trace_processor/importers/common/args_translation_table.h"
#include "src/trace_processor/importers/common/cpu_tracker.h"
#include "src/trace_processor/importers/common/event_tracker.h"
#include "src/trace_processor/importers/common/flow_tracker.h"
+#include "src/trace_processor/importers/common/parser_types.h"
#include "src/trace_processor/importers/common/process_track_translation_table.h"
#include "src/trace_processor/importers/common/process_tracker.h"
#include "src/trace_processor/importers/common/track_tracker.h"
#include "src/trace_processor/importers/common/virtual_memory_mapping.h"
-#include "src/trace_processor/importers/json/json_utils.h"
#include "src/trace_processor/importers/proto/args_parser.h"
#include "src/trace_processor/importers/proto/packet_analyzer.h"
-#include "src/trace_processor/importers/proto/profile_packet_utils.h"
#include "src/trace_processor/importers/proto/stack_profile_sequence_state.h"
#include "src/trace_processor/importers/proto/track_event_tracker.h"
+#include "src/trace_processor/storage/stats.h"
+#include "src/trace_processor/storage/trace_storage.h"
+#include "src/trace_processor/tables/slice_tables_py.h"
+#include "src/trace_processor/types/variadic.h"
#include "src/trace_processor/util/debug_annotation_parser.h"
#include "src/trace_processor/util/proto_to_args_parser.h"
#include "src/trace_processor/util/status_macros.h"
#include "protos/perfetto/common/android_log_constants.pbzero.h"
-#include "protos/perfetto/trace/extension_descriptor.pbzero.h"
#include "protos/perfetto/trace/interned_data/interned_data.pbzero.h"
#include "protos/perfetto/trace/track_event/chrome_active_processes.pbzero.h"
#include "protos/perfetto/trace/track_event/chrome_compositor_scheduler_state.pbzero.h"
#include "protos/perfetto/trace/track_event/chrome_histogram_sample.pbzero.h"
-#include "protos/perfetto/trace/track_event/chrome_legacy_ipc.pbzero.h"
#include "protos/perfetto/trace/track_event/chrome_process_descriptor.pbzero.h"
#include "protos/perfetto/trace/track_event/chrome_thread_descriptor.pbzero.h"
#include "protos/perfetto/trace/track_event/counter_descriptor.pbzero.h"
@@ -63,8 +73,7 @@
#include "protos/perfetto/trace/track_event/track_descriptor.pbzero.h"
#include "protos/perfetto/trace/track_event/track_event.pbzero.h"
-namespace perfetto {
-namespace trace_processor {
+namespace perfetto::trace_processor {
namespace {
using BoundInserter = ArgsTracker::BoundInserter;
@@ -90,7 +99,7 @@
}
std::optional<base::Status> MaybeParseUnsymbolizedSourceLocation(
- std::string prefix,
+ const std::string& prefix,
const protozero::Field& field,
util::ProtoToArgsParser::Delegate& delegate) {
auto* decoder = delegate.GetInternedMessage(
@@ -103,9 +112,9 @@
}
// Interned mapping_id loses it's meaning when the sequence ends. So we need
// to get an id from stack_profile_mapping table.
- auto mapping = delegate.seq_state()
- ->GetCustomState<StackProfileSequenceState>()
- ->FindOrInsertMapping(decoder->mapping_id());
+ auto* mapping = delegate.seq_state()
+ ->GetCustomState<StackProfileSequenceState>()
+ ->FindOrInsertMapping(decoder->mapping_id());
if (!mapping) {
return std::nullopt;
}
@@ -118,7 +127,7 @@
}
std::optional<base::Status> MaybeParseSourceLocation(
- std::string prefix,
+ const std::string& prefix,
const protozero::Field& field,
util::ProtoToArgsParser::Delegate& delegate) {
auto* decoder = delegate.GetInternedMessage(
@@ -137,7 +146,6 @@
delegate.AddInteger(util::ProtoToArgsParser::Key(prefix + ".line_number"),
decoder->line_number());
}
-
return base::OkStatus();
}
@@ -181,7 +189,7 @@
ts_(ts),
event_data_(event_data),
sequence_state_(event_data->trace_packet_data.sequence_state.get()),
- blob_(std::move(blob)),
+ blob_(blob),
event_(blob_),
legacy_event_(event_.legacy_event()),
defaults_(event_data->trace_packet_data.sequence_state
@@ -190,11 +198,11 @@
thread_instruction_count_(event_data->thread_instruction_count),
packet_sequence_id_(packet_sequence_id) {}
- util::Status Import() {
+ base::Status Import() {
// TODO(eseckler): This legacy event field will eventually be replaced by
// fields in TrackEvent itself.
if (PERFETTO_UNLIKELY(!event_.type() && !legacy_event_.has_phase()))
- return util::ErrStatus("TrackEvent without type or phase");
+ return base::ErrStatus("TrackEvent without type or phase");
category_id_ = ParseTrackEventCategory();
name_id_ = ParseTrackEventName();
@@ -213,7 +221,7 @@
// CounterDescriptor instead). All they have is a |{double_,}counter_value|.
if (event_.type() == TrackEvent::TYPE_COUNTER) {
ParseCounterEvent();
- return util::OkStatus();
+ return base::OkStatus();
}
// If we have legacy thread time / instruction count fields, also parse them
@@ -341,7 +349,7 @@
return kNullStringId;
}
- util::Status ParseTrackAssociation() {
+ base::Status ParseTrackAssociation() {
TrackTracker* track_tracker = context_->track_tracker.get();
ProcessTracker* procs = context_->process_tracker.get();
@@ -373,35 +381,34 @@
}
track_id_ = *opt_track_id;
- auto thread_track_row =
- storage_->thread_track_table().id().IndexOf(track_id_);
- if (thread_track_row) {
- utid_ = storage_->thread_track_table().utid()[*thread_track_row];
- upid_ = storage_->thread_table().upid()[*utid_];
+ auto tt_rr = storage_->thread_track_table().FindById(track_id_);
+ if (tt_rr) {
+ utid_ = tt_rr->utid();
+ upid_ = storage_->thread_table()[*utid_].upid();
} else {
- auto process_track_row =
- storage_->process_track_table().id().IndexOf(track_id_);
- if (process_track_row) {
- upid_ = storage_->process_track_table().upid()[*process_track_row];
+ auto pt_rr = storage_->process_track_table().FindById(track_id_);
+ if (pt_rr) {
+ upid_ = pt_rr->upid();
if (sequence_state_->pid_and_tid_valid()) {
- uint32_t pid = static_cast<uint32_t>(sequence_state_->pid());
- uint32_t tid = static_cast<uint32_t>(sequence_state_->tid());
+ auto pid = static_cast<uint32_t>(sequence_state_->pid());
+ auto tid = static_cast<uint32_t>(sequence_state_->tid());
UniqueTid utid_candidate = procs->UpdateThread(tid, pid);
- if (storage_->thread_table().upid()[utid_candidate] == upid_)
+ if (storage_->thread_table()[utid_candidate].upid() == upid_) {
legacy_passthrough_utid_ = utid_candidate;
+ }
}
} else {
auto* tracks = context_->storage->mutable_track_table();
- auto track_index = tracks->id().IndexOf(track_id_);
- if (track_index) {
- const StringPool::Id& id = tracks->name()[*track_index];
- if (id.is_null())
- tracks->mutable_name()->Set(*track_index, name_id_);
+ auto t_rr = tracks->FindById(track_id_);
+ if (t_rr) {
+ StringPool::Id id = t_rr->name();
+ if (id.is_null()) {
+ t_rr->set_name(name_id_);
+ }
}
-
if (sequence_state_->pid_and_tid_valid()) {
- uint32_t pid = static_cast<uint32_t>(sequence_state_->pid());
- uint32_t tid = static_cast<uint32_t>(sequence_state_->tid());
+ auto pid = static_cast<uint32_t>(sequence_state_->pid());
+ auto tid = static_cast<uint32_t>(sequence_state_->tid());
legacy_passthrough_utid_ = procs->UpdateThread(tid, pid);
}
}
@@ -426,8 +433,8 @@
legacy_event_.has_tid_override() && pid_tid_state_valid;
if (fallback_to_legacy_pid_tid_tracks) {
- uint32_t pid = static_cast<uint32_t>(sequence_state_->pid());
- uint32_t tid = static_cast<uint32_t>(sequence_state_->tid());
+ auto pid = static_cast<uint32_t>(sequence_state_->pid());
+ auto tid = static_cast<uint32_t>(sequence_state_->tid());
if (legacy_event_.has_pid_override()) {
pid = static_cast<uint32_t>(legacy_event_.pid_override());
tid = static_cast<uint32_t>(-1);
@@ -436,7 +443,7 @@
tid = static_cast<uint32_t>(legacy_event_.tid_override());
utid_ = procs->UpdateThread(tid, pid);
- upid_ = storage_->thread_table().upid()[*utid_];
+ upid_ = storage_->thread_table()[*utid_].upid();
track_id_ = track_tracker->InternThreadTrack(*utid_);
} else {
track_id_ = track_event_tracker_->GetOrCreateDefaultDescriptorTrack();
@@ -444,7 +451,7 @@
}
if (!legacy_event_.has_phase())
- return util::OkStatus();
+ return base::OkStatus();
// Legacy phases may imply a different track than the one specified by
// the fallback (or default track uuid) above.
@@ -465,14 +472,14 @@
source_id = static_cast<int64_t>(legacy_event_.global_id());
} else if (legacy_event_.has_local_id()) {
if (!upid_) {
- return util::ErrStatus(
+ return base::ErrStatus(
"TrackEvent with local_id without process association");
}
source_id = static_cast<int64_t>(legacy_event_.local_id());
source_id_is_process_scoped = true;
} else {
- return util::ErrStatus("Async LegacyEvent without ID");
+ return base::ErrStatus("Async LegacyEvent without ID");
}
// Catapult treats nestable async events of different categories with
@@ -504,7 +511,7 @@
// Thread-scoped legacy instant events already have the right
// track based on the tid/pid of the sequence.
if (!utid_) {
- return util::ErrStatus(
+ return base::ErrStatus(
"Thread-scoped instant event without thread association");
}
break;
@@ -516,7 +523,7 @@
break;
case LegacyEvent::SCOPE_PROCESS:
if (!upid_) {
- return util::ErrStatus(
+ return base::ErrStatus(
"Process-scoped instant event without process association");
}
@@ -533,7 +540,7 @@
break;
}
- return util::OkStatus();
+ return base::OkStatus();
}
int32_t ParsePhaseOrType() {
@@ -556,7 +563,7 @@
void ParseCounterEvent() {
// Tokenizer ensures that TYPE_COUNTER events are associated with counter
// tracks and have values.
- PERFETTO_DCHECK(storage_->counter_track_table().id().IndexOf(track_id_));
+ PERFETTO_DCHECK(storage_->counter_track_table().FindById(track_id_));
PERFETTO_DCHECK(event_.has_counter_value() ||
event_.has_double_counter_value());
@@ -630,16 +637,14 @@
std::optional<TrackId> track_id = track_event_tracker_->GetDescriptorTrack(
*track_uuid_it, kNullStringId, packet_sequence_id_);
- std::optional<uint32_t> counter_row =
- storage_->counter_track_table().id().IndexOf(*track_id);
+ auto counter_row = storage_->counter_track_table().FindById(*track_id);
double value = event_data_->extra_counter_values[index];
context_->event_tracker->PushCounter(ts_, value, *track_id);
// Also import thread_time and thread_instruction_count counters into
// slice columns to simplify JSON export.
- StringId counter_name =
- storage_->counter_track_table().name()[*counter_row];
+ StringId counter_name = counter_row->name();
if (counter_name == parser_->counter_name_thread_time_id_) {
thread_timestamp_ = static_cast<int64_t>(value);
} else if (counter_name ==
@@ -648,9 +653,9 @@
}
}
- util::Status ParseThreadBeginEvent() {
+ base::Status ParseThreadBeginEvent() {
if (!utid_) {
- return util::ErrStatus(
+ return base::ErrStatus(
"TrackEvent with phase B without thread association");
}
@@ -662,12 +667,12 @@
if (opt_slice_id.has_value()) {
MaybeParseFlowEvents(opt_slice_id.value());
}
- return util::OkStatus();
+ return base::OkStatus();
}
- util::Status ParseThreadEndEvent() {
+ base::Status ParseThreadEndEvent() {
if (!utid_) {
- return util::ErrStatus(
+ return base::ErrStatus(
"TrackEvent with phase E without thread association");
}
auto opt_slice_id = context_->slice_tracker->End(
@@ -699,18 +704,18 @@
slice_ref.set_thread_instruction_delta(
*event_data_->thread_instruction_count - *tic);
}
- return util::OkStatus();
+ return base::OkStatus();
}
- util::Status ParseThreadCompleteEvent() {
+ base::Status ParseThreadCompleteEvent() {
if (!utid_) {
- return util::ErrStatus(
+ return base::ErrStatus(
"TrackEvent with phase X without thread association");
}
auto duration_ns = legacy_event_.duration_us() * 1000;
if (duration_ns < 0)
- return util::ErrStatus("TrackEvent with phase X with negative duration");
+ return base::ErrStatus("TrackEvent with phase X with negative duration");
auto* thread_slices = storage_->mutable_slice_table();
tables::SliceTable::Row row = MakeThreadSliceRow();
@@ -722,13 +727,13 @@
row.thread_instruction_delta = legacy_event_.thread_instruction_delta();
}
auto opt_slice_id = context_->slice_tracker->ScopedTyped(
- thread_slices, std::move(row),
+ thread_slices, row,
[this](BoundInserter* inserter) { ParseTrackEventArgs(inserter); });
if (opt_slice_id.has_value()) {
MaybeParseFlowEvents(opt_slice_id.value());
}
- return util::OkStatus();
+ return base::OkStatus();
}
std::optional<uint64_t> GetLegacyEventId() {
@@ -742,11 +747,11 @@
return std::nullopt;
}
- util::Status ParseFlowEventV1(char phase) {
+ base::Status ParseFlowEventV1(char phase) {
auto opt_source_id = GetLegacyEventId();
if (!opt_source_id) {
storage_->IncrementStats(stats::flow_invalid_id);
- return util::ErrStatus("Invalid id for flow event v1");
+ return base::ErrStatus("Invalid id for flow event v1");
}
FlowId flow_id = context_->flow_tracker->GetFlowIdForV1Event(
opt_source_id.value(), category_id_, name_id_);
@@ -763,7 +768,7 @@
/* close_flow = */ false);
break;
}
- return util::OkStatus();
+ return base::OkStatus();
}
void MaybeParseTrackEventFlows(SliceId slice_id) {
@@ -828,7 +833,7 @@
MaybeParseTrackEventFlows(slice_id);
}
- util::Status ParseThreadInstantEvent(char phase) {
+ base::Status ParseThreadInstantEvent(char phase) {
// Handle instant events as slices with zero duration, so that they end
// up nested underneath their parent slices.
int64_t duration_ns = 0;
@@ -862,13 +867,13 @@
std::move(args_inserter));
}
if (!opt_slice_id.has_value()) {
- return util::OkStatus();
+ return base::OkStatus();
}
MaybeParseFlowEvents(opt_slice_id.value());
- return util::OkStatus();
+ return base::OkStatus();
}
- util::Status ParseAsyncBeginEvent(char phase) {
+ base::Status ParseAsyncBeginEvent(char phase) {
auto args_inserter = [this, phase](BoundInserter* inserter) {
ParseTrackEventArgs(inserter);
@@ -884,7 +889,7 @@
auto opt_slice_id = context_->slice_tracker->Begin(
ts_, track_id_, category_id_, name_id_, args_inserter);
if (!opt_slice_id.has_value()) {
- return util::OkStatus();
+ return base::OkStatus();
}
MaybeParseFlowEvents(opt_slice_id.value());
// For the time being, we only create vtrack slice rows if we need to
@@ -899,10 +904,10 @@
kPendingThreadDuration, tic,
kPendingThreadInstructionDelta);
}
- return util::OkStatus();
+ return base::OkStatus();
}
- util::Status ParseAsyncEndEvent() {
+ base::Status ParseAsyncEndEvent() {
auto opt_slice_id = context_->slice_tracker->End(
ts_, track_id_, category_id_, name_id_,
[this](BoundInserter* inserter) { ParseTrackEventArgs(inserter); });
@@ -916,10 +921,10 @@
int64_t tic = event_data_->thread_instruction_count.value_or(0);
vtrack_slices->UpdateThreadDeltasForSliceId(*opt_slice_id, tts, tic);
}
- return util::OkStatus();
+ return base::OkStatus();
}
- util::Status ParseAsyncStepEvent(char phase) {
+ base::Status ParseAsyncStepEvent(char phase) {
// Parse step events as instant events. Reconstructing the begin/end times
// of the child slice would be too complicated, see b/178540838. For JSON
// export, we still record the original step's phase in an arg.
@@ -937,10 +942,10 @@
});
// Step events don't support thread timestamps, so no need to add a row to
// virtual_track_slices.
- return util::OkStatus();
+ return base::OkStatus();
}
- util::Status ParseAsyncInstantEvent() {
+ base::Status ParseAsyncInstantEvent() {
// Handle instant events as slices with zero duration, so that they end
// up nested underneath their parent slices.
int64_t duration_ns = 0;
@@ -949,7 +954,7 @@
ts_, track_id_, category_id_, name_id_, duration_ns,
[this](BoundInserter* inserter) { ParseTrackEventArgs(inserter); });
if (!opt_slice_id.has_value()) {
- return util::OkStatus();
+ return base::OkStatus();
}
MaybeParseFlowEvents(opt_slice_id.value());
if (legacy_event_.use_async_tts()) {
@@ -961,68 +966,68 @@
vtrack_slices->AddVirtualTrackSlice(opt_slice_id.value(), tts,
duration_ns, tic, tidelta);
}
- return util::OkStatus();
+ return base::OkStatus();
}
- util::Status ParseMetadataEvent() {
+ base::Status ParseMetadataEvent() {
ProcessTracker* procs = context_->process_tracker.get();
if (name_id_ == kNullStringId)
- return util::ErrStatus("Metadata event without name");
+ return base::ErrStatus("Metadata event without name");
// Parse process and thread names from correspondingly named events.
NullTermStringView event_name = storage_->GetString(name_id_);
PERFETTO_DCHECK(event_name.data());
- if (strcmp(event_name.c_str(), "thread_name") == 0) {
+ if (event_name == "thread_name") {
if (!utid_) {
- return util::ErrStatus(
+ return base::ErrStatus(
"thread_name metadata event without thread association");
}
auto it = event_.debug_annotations();
if (!it) {
- return util::ErrStatus(
+ return base::ErrStatus(
"thread_name metadata event without debug annotations");
}
protos::pbzero::DebugAnnotation::Decoder annotation(*it);
auto thread_name = annotation.string_value();
if (!thread_name.size)
- return util::OkStatus();
+ return base::OkStatus();
auto thread_name_id = storage_->InternString(thread_name);
procs->UpdateThreadNameByUtid(
*utid_, thread_name_id,
ThreadNamePriority::kTrackDescriptorThreadType);
- return util::OkStatus();
+ return base::OkStatus();
}
- if (strcmp(event_name.c_str(), "process_name") == 0) {
+ if (event_name == "process_name") {
if (!upid_) {
- return util::ErrStatus(
+ return base::ErrStatus(
"process_name metadata event without process association");
}
auto it = event_.debug_annotations();
if (!it) {
- return util::ErrStatus(
+ return base::ErrStatus(
"process_name metadata event without debug annotations");
}
protos::pbzero::DebugAnnotation::Decoder annotation(*it);
auto process_name = annotation.string_value();
if (!process_name.size)
- return util::OkStatus();
+ return base::OkStatus();
auto process_name_id =
storage_->InternString(base::StringView(process_name));
// Don't override system-provided names.
procs->SetProcessNameIfUnset(*upid_, process_name_id);
- return util::OkStatus();
+ return base::OkStatus();
}
// Other metadata events are proxied via the raw table for JSON export.
ParseLegacyEventAsRawEvent();
- return util::OkStatus();
+ return base::OkStatus();
}
- util::Status ParseLegacyEventAsRawEvent() {
+ base::Status ParseLegacyEventAsRawEvent() {
if (!utid_)
- return util::ErrStatus("raw legacy event without thread association");
+ return base::ErrStatus("raw legacy event without thread association");
auto ucpu = context_->cpu_tracker->GetOrCreateCpu(0);
RawId id =
@@ -1099,11 +1104,11 @@
// instant events into the slice table.
ParseTrackEventArgs(&inserter);
- return util::OkStatus();
+ return base::OkStatus();
}
void ParseTrackEventArgs(BoundInserter* inserter) {
- auto log_errors = [this](util::Status status) {
+ auto log_errors = [this](const base::Status& status) {
if (status.ok())
return;
// Log error but continue parsing the other args.
@@ -1159,18 +1164,18 @@
}
}
- util::Status ParseTaskExecutionArgs(ConstBytes task_execution,
+ base::Status ParseTaskExecutionArgs(ConstBytes task_execution,
BoundInserter* inserter) {
protos::pbzero::TaskExecution::Decoder task(task_execution);
uint64_t iid = task.posted_from_iid();
if (!iid)
- return util::ErrStatus("TaskExecution with invalid posted_from_iid");
+ return base::ErrStatus("TaskExecution with invalid posted_from_iid");
auto* decoder = sequence_state_->LookupInternedMessage<
protos::pbzero::InternedData::kSourceLocationsFieldNumber,
protos::pbzero::SourceLocation>(iid);
if (!decoder)
- return util::ErrStatus("TaskExecution with invalid posted_from_iid");
+ return base::ErrStatus("TaskExecution with invalid posted_from_iid");
StringId file_name_id = kNullStringId;
StringId function_name_id = kNullStringId;
@@ -1187,18 +1192,18 @@
Variadic::String(function_name_id));
inserter->AddArg(parser_->task_line_number_args_key_id_,
Variadic::UnsignedInteger(line_number));
- return util::OkStatus();
+ return base::OkStatus();
}
- util::Status AddSourceLocationArgs(uint64_t iid, BoundInserter* inserter) {
+ base::Status AddSourceLocationArgs(uint64_t iid, BoundInserter* inserter) {
if (!iid)
- return util::ErrStatus("SourceLocation with invalid iid");
+ return base::ErrStatus("SourceLocation with invalid iid");
auto* decoder = sequence_state_->LookupInternedMessage<
protos::pbzero::InternedData::kSourceLocationsFieldNumber,
protos::pbzero::SourceLocation>(iid);
if (!decoder)
- return util::ErrStatus("SourceLocation with invalid iid");
+ return base::ErrStatus("SourceLocation with invalid iid");
StringId file_name_id = kNullStringId;
StringId function_name_id = kNullStringId;
@@ -1215,12 +1220,12 @@
Variadic::String(function_name_id));
inserter->AddArg(parser_->source_location_line_number_key_id_,
Variadic::UnsignedInteger(line_number));
- return util::OkStatus();
+ return base::OkStatus();
}
- util::Status ParseLogMessage(ConstBytes blob, BoundInserter* inserter) {
+ base::Status ParseLogMessage(ConstBytes blob, BoundInserter* inserter) {
if (!utid_)
- return util::ErrStatus("LogMessage without thread association");
+ return base::ErrStatus("LogMessage without thread association");
protos::pbzero::LogMessage::Decoder message(blob);
@@ -1228,7 +1233,7 @@
protos::pbzero::InternedData::kLogMessageBodyFieldNumber,
protos::pbzero::LogMessageBody>(message.body_iid());
if (!body_decoder)
- return util::ErrStatus("LogMessage with invalid body_iid");
+ return base::ErrStatus("LogMessage with invalid body_iid");
const StringId log_message_id =
storage_->InternString(body_decoder->body());
@@ -1241,7 +1246,7 @@
protos::pbzero::InternedData::kSourceLocationsFieldNumber,
protos::pbzero::SourceLocation>(message.source_location_iid());
if (!source_location_decoder)
- return util::ErrStatus("LogMessage with invalid source_location_iid");
+ return base::ErrStatus("LogMessage with invalid source_location_iid");
const std::string source_location =
source_location_decoder->file_name().ToStdString() + ":" +
std::to_string(source_location_decoder->line_number());
@@ -1276,16 +1281,16 @@
/*priority*/ static_cast<uint32_t>(priority),
/*tag_id*/ source_location_id, log_message_id});
- return util::OkStatus();
+ return base::OkStatus();
}
- util::Status ParseHistogramName(ConstBytes blob, BoundInserter* inserter) {
+ base::Status ParseHistogramName(ConstBytes blob, BoundInserter* inserter) {
protos::pbzero::ChromeHistogramSample::Decoder sample(blob);
if (!sample.has_name_iid())
- return util::OkStatus();
+ return base::OkStatus();
if (sample.has_name()) {
- return util::ErrStatus(
+ return base::ErrStatus(
"name is already set for ChromeHistogramSample: only one of name and "
"name_iid can be set.");
}
@@ -1294,11 +1299,11 @@
protos::pbzero::InternedData::kHistogramNamesFieldNumber,
protos::pbzero::HistogramName>(sample.name_iid());
if (!decoder)
- return util::ErrStatus("HistogramName with invalid name_iid");
+ return base::ErrStatus("HistogramName with invalid name_iid");
inserter->AddArg(parser_->histogram_name_key_id_,
Variadic::String(storage_->InternString(decoder->name())));
- return util::OkStatus();
+ return base::OkStatus();
}
tables::SliceTable::Row MakeThreadSliceRow() {
@@ -1347,7 +1352,7 @@
TrackEventParser::TrackEventParser(TraceProcessorContext* context,
TrackEventTracker* track_event_tracker)
- : args_parser_(*context->descriptor_pool_.get()),
+ : args_parser_(*context->descriptor_pool_),
context_(context),
track_event_tracker_(track_event_tracker),
counter_name_thread_time_id_(
@@ -1535,7 +1540,7 @@
decoder.has_name() ? decoder.name() : decoder.static_name());
const StringId name_id =
context_->process_track_translation_table->TranslateName(raw_name_id);
- tracks->mutable_name()->Set(*tracks->id().IndexOf(track_id), name_id);
+ tracks->FindById(track_id)->set_name(name_id);
}
}
@@ -1645,30 +1650,26 @@
if (unit_index >= counter_unit_ids_.size())
unit_index = CounterDescriptor::UNIT_UNSPECIFIED;
- auto opt_track_idx = counter_tracks->id().IndexOf(track_id);
- if (!opt_track_idx) {
+ auto opt_rr = counter_tracks->FindById(track_id);
+ if (!opt_rr) {
context_->storage->IncrementStats(stats::track_event_parser_errors);
return;
}
- auto track_idx = *opt_track_idx;
-
+ auto& rr = *opt_rr;
switch (decoder.type()) {
case CounterDescriptor::COUNTER_UNSPECIFIED:
break;
case CounterDescriptor::COUNTER_THREAD_TIME_NS:
unit_index = CounterDescriptor::UNIT_TIME_NS;
- counter_tracks->mutable_name()->Set(track_idx,
- counter_name_thread_time_id_);
+ rr.set_name(counter_name_thread_time_id_);
break;
case CounterDescriptor::COUNTER_THREAD_INSTRUCTION_COUNT:
unit_index = CounterDescriptor::UNIT_COUNT;
- counter_tracks->mutable_name()->Set(
- track_idx, counter_name_thread_instruction_count_id_);
+ rr.set_name(counter_name_thread_instruction_count_id_);
break;
}
-
- counter_tracks->mutable_unit()->Set(track_idx, counter_unit_ids_[unit_index]);
+ rr.set_unit(counter_unit_ids_[unit_index]);
}
void TrackEventParser::ParseTrackEvent(int64_t ts,
@@ -1686,9 +1687,8 @@
stats::track_event_dropped_packets_outside_of_range_of_interest);
return;
}
- util::Status status =
- EventImporter(this, ts, event_data, std::move(blob), packet_sequence_id)
- .Import();
+ base::Status status =
+ EventImporter(this, ts, event_data, blob, packet_sequence_id).Import();
if (!status.ok()) {
context_->storage->IncrementStats(stats::track_event_parser_errors);
PERFETTO_DLOG("ParseTrackEvent error: %s", status.c_message());
@@ -1706,5 +1706,4 @@
active_chrome_processes_tracker_.NotifyEndOfFile();
}
-} // namespace trace_processor
-} // namespace perfetto
+} // namespace perfetto::trace_processor
diff --git a/src/trace_processor/importers/proto/track_event_tracker.cc b/src/trace_processor/importers/proto/track_event_tracker.cc
index e758b9d..a336b60 100644
--- a/src/trace_processor/importers/proto/track_event_tracker.cc
+++ b/src/trace_processor/importers/proto/track_event_tracker.cc
@@ -16,15 +16,29 @@
#include "src/trace_processor/importers/proto/track_event_tracker.h"
+#include <algorithm>
+#include <cinttypes>
+#include <cstddef>
+#include <cstdint>
+#include <map>
+#include <memory>
+#include <optional>
+#include <tuple>
+#include <utility>
+#include <vector>
+
+#include "perfetto/base/logging.h"
#include "src/trace_processor/importers/common/args_tracker.h"
-#include "src/trace_processor/importers/common/args_translation_table.h"
#include "src/trace_processor/importers/common/process_track_translation_table.h"
#include "src/trace_processor/importers/common/process_tracker.h"
#include "src/trace_processor/importers/common/track_tracker.h"
+#include "src/trace_processor/storage/stats.h"
+#include "src/trace_processor/storage/trace_storage.h"
#include "src/trace_processor/tables/track_tables_py.h"
+#include "src/trace_processor/types/trace_processor_context.h"
+#include "src/trace_processor/types/variadic.h"
-namespace perfetto {
-namespace trace_processor {
+namespace perfetto::trace_processor {
TrackEventTracker::TrackEventTracker(TraceProcessorContext* context)
: source_key_(context->storage->InternString("source")),
@@ -64,7 +78,6 @@
context_->storage->IncrementStats(stats::track_event_tokenizer_errors);
return;
}
-
it->second.min_timestamp = std::min(it->second.min_timestamp, timestamp);
}
@@ -190,9 +203,10 @@
// Update the name of the track if unset and the track is not the primary
// track of a process/thread or a counter track.
auto* tracks = context_->storage->mutable_track_table();
- uint32_t row = *tracks->id().IndexOf(*track_id);
- if (!tracks->name()[row].is_null())
+ auto rr = *tracks->FindById(*track_id);
+ if (!rr.name().is_null()) {
return track_id;
+ }
// Check reservation for track type.
auto reservation_it = reserved_descriptor_tracks_.find(uuid);
@@ -202,9 +216,8 @@
reservation_it->second.is_counter) {
return track_id;
}
- const StringId track_name =
- context_->process_track_translation_table->TranslateName(event_name);
- tracks->mutable_name()->Set(row, track_name);
+ rr.set_name(
+ context_->process_track_translation_table->TranslateName(event_name));
return track_id;
}
@@ -385,7 +398,7 @@
// seen in the recursion.
std::unique_ptr<std::vector<uint64_t>> owned_descendent_uuids;
if (!descendent_uuids) {
- owned_descendent_uuids.reset(new std::vector<uint64_t>());
+ owned_descendent_uuids = std::make_unique<std::vector<uint64_t>>();
descendent_uuids = owned_descendent_uuids.get();
}
descendent_uuids->push_back(uuid);
@@ -633,5 +646,4 @@
return track;
}
-} // namespace trace_processor
-} // namespace perfetto
+} // namespace perfetto::trace_processor
diff --git a/src/trace_processor/importers/proto/vulkan_memory_tracker.h b/src/trace_processor/importers/proto/vulkan_memory_tracker.h
index dd44a89..cb770cc 100644
--- a/src/trace_processor/importers/proto/vulkan_memory_tracker.h
+++ b/src/trace_processor/importers/proto/vulkan_memory_tracker.h
@@ -17,6 +17,11 @@
#ifndef SRC_TRACE_PROCESSOR_IMPORTERS_PROTO_VULKAN_MEMORY_TRACKER_H_
#define SRC_TRACE_PROCESSOR_IMPORTERS_PROTO_VULKAN_MEMORY_TRACKER_H_
+#include <cstdint>
+#include <string>
+#include <unordered_map>
+#include <vector>
+
#include "src/trace_processor/importers/proto/packet_sequence_state_generation.h"
#include "src/trace_processor/storage/trace_storage.h"
#include "src/trace_processor/types/trace_processor_context.h"
@@ -24,13 +29,12 @@
#include "protos/perfetto/trace/gpu/vulkan_memory_event.pbzero.h"
#include "protos/perfetto/trace/profiling/profile_common.pbzero.h"
-namespace perfetto {
-namespace trace_processor {
-
-using protos::pbzero::VulkanMemoryEvent;
+namespace perfetto::trace_processor {
class VulkanMemoryTracker {
public:
+ using VulkanMemoryEvent = protos::pbzero::VulkanMemoryEvent;
+
enum class DeviceCounterType {
kAllocationCounter = 0,
kBindCounter = 1,
@@ -76,7 +80,6 @@
void SetupSourceAndTypeInternedStrings();
};
-} // namespace trace_processor
-} // namespace perfetto
+} // namespace perfetto::trace_processor
#endif // SRC_TRACE_PROCESSOR_IMPORTERS_PROTO_VULKAN_MEMORY_TRACKER_H_
diff --git a/src/trace_processor/metrics/sql/android/BUILD.gn b/src/trace_processor/metrics/sql/android/BUILD.gn
index ea029b0..ba8666e 100644
--- a/src/trace_processor/metrics/sql/android/BUILD.gn
+++ b/src/trace_processor/metrics/sql/android/BUILD.gn
@@ -145,6 +145,6 @@
"unsymbolized_frames.sql",
"wattson_app_startup.sql",
"wattson_rail_relations.sql",
- "wattson_trace_estimate.sql",
+ "wattson_trace_rails.sql",
]
}
diff --git a/src/trace_processor/metrics/sql/android/wattson_trace_estimate.sql b/src/trace_processor/metrics/sql/android/wattson_trace_rails.sql
similarity index 92%
rename from src/trace_processor/metrics/sql/android/wattson_trace_estimate.sql
rename to src/trace_processor/metrics/sql/android/wattson_trace_rails.sql
index 865ad3d..ab035c0 100644
--- a/src/trace_processor/metrics/sql/android/wattson_trace_estimate.sql
+++ b/src/trace_processor/metrics/sql/android/wattson_trace_rails.sql
@@ -30,8 +30,8 @@
'window_table', '_wattson_period_windows'
);
-DROP VIEW IF EXISTS wattson_trace_estimate_output;
-CREATE PERFETTO VIEW wattson_trace_estimate_output AS
+DROP VIEW IF EXISTS wattson_trace_rails_output;
+CREATE PERFETTO VIEW wattson_trace_rails_output AS
SELECT AndroidWattsonTimePeriodMetric(
'metric_version', 2,
'period_info', (
diff --git a/src/trace_processor/minimal_shell.cc b/src/trace_processor/minimal_shell.cc
new file mode 100644
index 0000000..0bbf6f7
--- /dev/null
+++ b/src/trace_processor/minimal_shell.cc
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2024 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 <cinttypes>
+#include <cstdint>
+#include <cstdio>
+#include <memory>
+
+#include "perfetto/base/status.h"
+#include "perfetto/trace_processor/basic_types.h"
+#include "perfetto/trace_processor/read_trace.h"
+#include "perfetto/trace_processor/trace_processor.h"
+#include "src/trace_processor/util/status_macros.h"
+
+namespace perfetto::trace_processor {
+namespace {
+
+// This binary exists just for the purpose of debugging the binary size of
+// trace processor. To that end, we just run some basic trace processor
+// functions to ensure that the linker does not strip the TP symbols.
+base::Status MinimalMain(int, char**) {
+ std::unique_ptr<TraceProcessor> tp = TraceProcessor::CreateInstance({});
+ RETURN_IF_ERROR(tp->Parse(std::unique_ptr<uint8_t[]>(new uint8_t[0]), 0));
+ RETURN_IF_ERROR(tp->NotifyEndOfFile());
+
+ auto it = tp->ExecuteQuery("SELECT id FROM slice");
+ while (it.Next()) {
+ SqlValue value = it.Get(0);
+ fprintf(stderr, "%" PRId64, value.AsLong());
+ }
+ return it.Status();
+}
+
+} // namespace
+} // namespace perfetto::trace_processor
+
+int main(int argc, char** argv) {
+ auto status = perfetto::trace_processor::MinimalMain(argc, argv);
+ if (!status.ok()) {
+ fprintf(stderr, "%s\n", status.c_message());
+ return 1;
+ }
+ return 0;
+}
diff --git a/src/trace_processor/perfetto_sql/engine/BUILD.gn b/src/trace_processor/perfetto_sql/engine/BUILD.gn
index e297c2b..a721a51 100644
--- a/src/trace_processor/perfetto_sql/engine/BUILD.gn
+++ b/src/trace_processor/perfetto_sql/engine/BUILD.gn
@@ -42,6 +42,7 @@
"../../../base",
"../../containers",
"../../db",
+ "../../db/column",
"../../perfetto_sql/intrinsics/functions:interface",
"../../perfetto_sql/intrinsics/table_functions:interface",
"../../sqlite",
diff --git a/src/trace_processor/perfetto_sql/engine/perfetto_sql_engine.cc b/src/trace_processor/perfetto_sql/engine/perfetto_sql_engine.cc
index 4302847..86bf583 100644
--- a/src/trace_processor/perfetto_sql/engine/perfetto_sql_engine.cc
+++ b/src/trace_processor/perfetto_sql/engine/perfetto_sql_engine.cc
@@ -37,7 +37,10 @@
#include "perfetto/ext/base/status_or.h"
#include "perfetto/ext/base/string_utils.h"
#include "perfetto/ext/base/string_view.h"
+#include "perfetto/trace_processor/basic_types.h"
+#include "src/trace_processor/containers/row_map.h"
#include "src/trace_processor/containers/string_pool.h"
+#include "src/trace_processor/db/column/types.h"
#include "src/trace_processor/db/runtime_table.h"
#include "src/trace_processor/db/table.h"
#include "src/trace_processor/perfetto_sql/engine/created_function.h"
@@ -709,8 +712,6 @@
return base::ErrStatus("CREATE PERFETTO INDEX: Table '%s' not found",
index.table_name.c_str());
}
-
- std::vector<Order> obs;
std::vector<uint32_t> col_idxs;
for (const std::string& col_name : index.col_names) {
const std::optional<uint32_t> opt_col = t->ColumnIdxFromName(col_name);
@@ -719,19 +720,10 @@
"CREATE PERFETTO INDEX: Column '%s' not found in table '%s'",
index.col_names.front().c_str(), index.table_name.c_str());
}
- Order o;
- o.col_idx = *opt_col;
- obs.push_back(o);
col_idxs.push_back(*opt_col);
}
-
- Query q;
- q.orders = obs;
- RowMap sorted_rm = t->QueryToRowMap(q);
-
- RETURN_IF_ERROR(t->SetIndex(index.name, std::move(col_idxs),
- std::move(sorted_rm).TakeAsIndexVector(),
- index.replace));
+ RETURN_IF_ERROR(
+ t->CreateIndex(index.name, std::move(col_idxs), index.replace));
return base::OkStatus();
}
@@ -742,7 +734,6 @@
return base::ErrStatus("DROP PERFETTO INDEX: Table '%s' not found",
index.table_name.c_str());
}
-
RETURN_IF_ERROR(t->DropIndex(index.name));
return base::OkStatus();
}
diff --git a/src/trace_processor/perfetto_sql/engine/table_pointer_module.cc b/src/trace_processor/perfetto_sql/engine/table_pointer_module.cc
index f8ee59f..1127fd1 100644
--- a/src/trace_processor/perfetto_sql/engine/table_pointer_module.cc
+++ b/src/trace_processor/perfetto_sql/engine/table_pointer_module.cc
@@ -172,18 +172,15 @@
return sqlite::utils::SetError(c->pVtab, "Column name is not text");
}
- std::string_view tok(
- reinterpret_cast<const char*>(sqlite3_value_text(argv[i])));
- auto it = std::find_if(
- c->table->columns().begin(), c->table->columns().end(),
- [&tok](const ColumnLegacy& col) { return col.name() == tok; });
- if (it == c->table->columns().end()) {
+ const char* tok =
+ reinterpret_cast<const char*>(sqlite3_value_text(argv[i]));
+ auto idx = c->table->ColumnIdxFromName(tok);
+ if (!idx) {
base::StackString<128> err("column '%s' does not exist in table",
sqlite3_value_text(argv[i]));
return sqlite::utils::SetError(c->pVtab, err.c_str());
}
- c->bound_col_to_table_index[c->col_count++] =
- static_cast<uint32_t>(std::distance(c->table->columns().begin(), it));
+ c->bound_col_to_table_index[c->col_count++] = *idx;
}
c->iterator = c->table->IterateRows();
return SQLITE_OK;
diff --git a/src/trace_processor/perfetto_sql/intrinsics/functions/BUILD.gn b/src/trace_processor/perfetto_sql/intrinsics/functions/BUILD.gn
index 53df4f7..863c2e6 100644
--- a/src/trace_processor/perfetto_sql/intrinsics/functions/BUILD.gn
+++ b/src/trace_processor/perfetto_sql/intrinsics/functions/BUILD.gn
@@ -76,6 +76,7 @@
"../../../perfetto_sql/intrinsics/table_functions",
"../../../sqlite",
"../../../storage",
+ "../../../tables",
"../../../types",
"../../../util",
"../../../util:profile_builder",
diff --git a/src/trace_processor/perfetto_sql/intrinsics/functions/to_ftrace.cc b/src/trace_processor/perfetto_sql/intrinsics/functions/to_ftrace.cc
index efa7659..7898fb9 100644
--- a/src/trace_processor/perfetto_sql/intrinsics/functions/to_ftrace.cc
+++ b/src/trace_processor/perfetto_sql/intrinsics/functions/to_ftrace.cc
@@ -16,16 +16,31 @@
#include "src/trace_processor/perfetto_sql/intrinsics/functions/to_ftrace.h"
-#include "perfetto/base/compiler.h"
+#include <cstddef>
+#include <cstdint>
+#include <cstdlib>
+#include <functional>
+#include <optional>
+#include <vector>
+
+#include "perfetto/base/logging.h"
#include "perfetto/base/status.h"
-#include "perfetto/ext/base/string_utils.h"
+#include "perfetto/ext/base/string_view.h"
+#include "perfetto/ext/base/string_writer.h"
+#include "perfetto/public/compiler.h"
#include "perfetto/trace_processor/basic_types.h"
+#include "src/trace_processor/containers/null_term_string_view.h"
+#include "src/trace_processor/db/column/types.h"
#include "src/trace_processor/importers/common/system_info_tracker.h"
#include "src/trace_processor/importers/ftrace/ftrace_descriptors.h"
-#include "src/trace_processor/sqlite/sqlite_utils.h"
+#include "src/trace_processor/sqlite/bindings/sqlite_type.h"
+#include "src/trace_processor/sqlite/bindings/sqlite_value.h"
+#include "src/trace_processor/storage/trace_storage.h"
+#include "src/trace_processor/tables/metadata_tables_py.h"
#include "src/trace_processor/types/gfp_flags.h"
#include "src/trace_processor/types/softirq_action.h"
#include "src/trace_processor/types/task_state.h"
+#include "src/trace_processor/types/trace_processor_context.h"
#include "src/trace_processor/types/variadic.h"
#include "protos/perfetto/trace/ftrace/binder.pbzero.h"
@@ -43,9 +58,9 @@
#include "protos/perfetto/trace/ftrace/samsung.pbzero.h"
#include "protos/perfetto/trace/ftrace/sched.pbzero.h"
#include "protos/perfetto/trace/ftrace/workqueue.pbzero.h"
+#include "src/trace_processor/types/version_number.h"
-namespace perfetto {
-namespace trace_processor {
+namespace perfetto::trace_processor {
namespace {
@@ -57,6 +72,12 @@
const int64_t micros;
};
+Query GetArgQuery(const tables::ArgTable& table, uint32_t arg_set_id) {
+ Query q;
+ q.constraints = {table.arg_set_id().eq(arg_set_id)};
+ return q;
+}
+
class ArgsSerializer {
public:
ArgsSerializer(TraceProcessorContext*,
@@ -72,7 +93,7 @@
using SerializerValueWriter = void (ArgsSerializer::*)(const Variadic&);
// Arg writing functions.
- void WriteArgForField(uint32_t field_id, ValueWriter writer) {
+ void WriteArgForField(uint32_t field_id, const ValueWriter& writer) {
std::optional<uint32_t> row = FieldIdToRow(field_id);
if (!row)
return;
@@ -80,21 +101,23 @@
}
void WriteArgForField(uint32_t field_id,
base::StringView key,
- ValueWriter writer) {
+ const ValueWriter& writer) {
std::optional<uint32_t> row = FieldIdToRow(field_id);
if (!row)
return;
WriteArg(key, storage_->GetArgValue(*row), writer);
}
- void WriteArgAtRow(uint32_t arg_row, ValueWriter writer) {
+ void WriteArgAtRow(uint32_t arg_row, const ValueWriter& writer) {
const auto& args = storage_->arg_table();
const auto& key = storage_->GetString(args.key()[arg_row]);
WriteArg(key, storage_->GetArgValue(arg_row), writer);
}
- void WriteArg(base::StringView key, Variadic value, ValueWriter writer);
+ void WriteArg(base::StringView key,
+ Variadic value,
+ const ValueWriter& writer);
// Value writing functions.
- void WriteValueForField(uint32_t field_id, ValueWriter writer) {
+ void WriteValueForField(uint32_t field_id, const ValueWriter& writer) {
std::optional<uint32_t> row = FieldIdToRow(field_id);
if (!row)
return;
@@ -109,7 +132,7 @@
PERFETTO_DFATAL("Invalid field type %d", static_cast<int>(value.type));
}
}
- void WriteValue(const Variadic& variadic);
+ void WriteValue(const Variadic&);
// The default value writer which uses the |WriteValue| function.
ValueWriter DVW() { return Wrap(&ArgsSerializer::WriteValue); }
@@ -130,11 +153,10 @@
const TraceStorage* storage_ = nullptr;
TraceProcessorContext* context_ = nullptr;
- ArgSetId arg_set_id_ = kInvalidArgSetId;
NullTermStringView event_name_;
std::vector<std::optional<uint32_t>>* field_id_to_arg_index_;
- RowMap row_map_;
+ tables::ArgTable::ConstIterator it_;
uint32_t start_row_ = 0;
base::StringWriter* writer_ = nullptr;
@@ -146,21 +168,16 @@
NullTermStringView event_name,
std::vector<std::optional<uint32_t>>* field_id_to_arg_index,
base::StringWriter* writer)
- : context_(context),
- arg_set_id_(arg_set_id),
+ : storage_(context->storage.get()),
+ context_(context),
event_name_(event_name),
field_id_to_arg_index_(field_id_to_arg_index),
+ it_(context->storage->arg_table().FilterToIterator(
+ GetArgQuery(context->storage->arg_table(), arg_set_id))),
writer_(writer) {
- storage_ = context_->storage.get();
- const auto& args = storage_->arg_table();
- const auto& set_ids = args.arg_set_id();
-
// We assume that the row map is a contiguous range (which is always the case
// because arg_set_ids are contiguous by definition).
- Query q;
- q.constraints = {set_ids.eq(arg_set_id_)};
- row_map_ = args.QueryToRowMap(q);
- start_row_ = row_map_.empty() ? 0 : row_map_.Get(0);
+ start_row_ = it_ ? it_.row_number().row_number() : 0;
// If the vector already has entries, we've previously cached the mapping
// from field id to arg index.
@@ -185,11 +202,13 @@
field_id_to_arg_index_->resize(max + 1);
// Go through each field id and find the entry in the args table for that
- for (uint32_t i = 1; i <= max; ++i) {
- for (auto it = row_map_.IterateRows(); it; it.Next()) {
- base::StringView key = args.key().GetString(it.index());
+ auto it = storage_->arg_table().FilterToIterator(
+ GetArgQuery(context->storage->arg_table(), arg_set_id));
+ for (uint32_t r = 0; it; ++it, ++r) {
+ for (uint32_t i = 1; i <= max; ++i) {
+ base::StringView key = context->storage->GetString(it.key());
if (key == descriptor->fields[i].name) {
- (*field_id_to_arg_index)[i] = it.row();
+ (*field_id_to_arg_index)[i] = r;
break;
}
}
@@ -197,7 +216,7 @@
}
void ArgsSerializer::SerializeArgs() {
- if (row_map_.empty())
+ if (!it_)
return;
if (event_name_ == "sched_switch") {
@@ -513,14 +532,14 @@
WriteArgForField(CAT::kCommFieldNumber, DVW());
return;
}
- for (auto it = row_map_.IterateRows(); it; it.Next()) {
- WriteArgAtRow(it.index(), DVW());
+ for (; it_; ++it_) {
+ WriteArgAtRow(it_.row_number().row_number(), DVW());
}
}
void ArgsSerializer::WriteArg(base::StringView key,
Variadic value,
- ValueWriter writer) {
+ const ValueWriter& writer) {
writer_->AppendChar(' ');
writer_->AppendString(key.data(), key.size());
writer_->AppendChar('=');
@@ -574,7 +593,7 @@
sqlite3_value** argv,
SqlValue& out,
Destructors& destructors) {
- if (argc != 1 || sqlite3_value_type(argv[0]) != SQLITE_INTEGER) {
+ if (argc != 1 || sqlite::value::Type(argv[0]) != sqlite::Type::kInteger) {
return base::ErrStatus("Usage: to_ftrace(id)");
}
uint32_t row = static_cast<uint32_t>(sqlite3_value_int64(argv[0]));
@@ -624,7 +643,7 @@
&writer);
serializer.SerializeArgs();
- return ScopedCString(writer.CreateStringCopy(), free);
+ return {writer.CreateStringCopy(), free};
}
void SystraceSerializer::SerializePrefix(uint32_t raw_row,
@@ -686,5 +705,4 @@
writer->AppendChar(':');
}
-} // namespace trace_processor
-} // namespace perfetto
+} // namespace perfetto::trace_processor
diff --git a/src/trace_processor/perfetto_sql/intrinsics/table_functions/ancestor.cc b/src/trace_processor/perfetto_sql/intrinsics/table_functions/ancestor.cc
index ab9ea14..093afae 100644
--- a/src/trace_processor/perfetto_sql/intrinsics/table_functions/ancestor.cc
+++ b/src/trace_processor/perfetto_sql/intrinsics/table_functions/ancestor.cc
@@ -112,14 +112,17 @@
// Nothing matches a null id so return an empty table.
switch (type_) {
case Type::kSlice:
- return tables::AncestorSliceTable::SelectAndExtendParent(
- storage_->slice_table(), {}, {});
+ return std::unique_ptr<Table>(
+ tables::AncestorSliceTable::SelectAndExtendParent(
+ storage_->slice_table(), {}, {}));
case Type::kStackProfileCallsite:
- return tables::AncestorStackProfileCallsiteTable::SelectAndExtendParent(
- storage_->stack_profile_callsite_table(), {}, {});
+ return std::unique_ptr<Table>(
+ tables::AncestorStackProfileCallsiteTable::SelectAndExtendParent(
+ storage_->stack_profile_callsite_table(), {}, {}));
case Type::kSliceByStack:
- return tables::AncestorSliceByStackTable::SelectAndExtendParent(
- storage_->slice_table(), {}, {});
+ return std::unique_ptr<Table>(
+ tables::AncestorSliceByStackTable::SelectAndExtendParent(
+ storage_->slice_table(), {}, {}));
}
return base::OkStatus();
}
diff --git a/src/trace_processor/perfetto_sql/intrinsics/table_functions/connected_flow.cc b/src/trace_processor/perfetto_sql/intrinsics/table_functions/connected_flow.cc
index 4089036..12d0455 100644
--- a/src/trace_processor/perfetto_sql/intrinsics/table_functions/connected_flow.cc
+++ b/src/trace_processor/perfetto_sql/intrinsics/table_functions/connected_flow.cc
@@ -30,6 +30,7 @@
#include "perfetto/base/status.h"
#include "perfetto/ext/base/status_or.h"
#include "perfetto/trace_processor/basic_types.h"
+#include "src/trace_processor/db/column/types.h"
#include "src/trace_processor/db/column_storage.h"
#include "src/trace_processor/db/table.h"
#include "src/trace_processor/db/typed_column.h"
@@ -209,14 +210,15 @@
if (arguments[0].type == SqlValue::Type::kNull) {
// Nothing matches a null id so return an empty table.
- return tables::ConnectedFlowTable::SelectAndExtendParent(flow, {}, {});
+ return std::unique_ptr<Table>(
+ tables::ConnectedFlowTable::SelectAndExtendParent(flow, {}, {}));
}
if (arguments[0].type != SqlValue::Type::kLong) {
return base::ErrStatus("start id should be an integer.");
}
SliceId start_id{static_cast<uint32_t>(arguments[0].AsLong())};
- if (!slice.id().IndexOf(start_id)) {
+ if (!slice.FindById(start_id)) {
return base::ErrStatus("invalid slice id %" PRIu32 "",
static_cast<uint32_t>(start_id.value));
}
@@ -243,8 +245,9 @@
for (size_t i = 0; i < result_rows.size(); i++) {
start_ids.Append(start_id.value);
}
- return tables::ConnectedFlowTable::SelectAndExtendParent(
- flow, result_rows, std::move(start_ids));
+ return std::unique_ptr<Table>(
+ tables::ConnectedFlowTable::SelectAndExtendParent(flow, result_rows,
+ std::move(start_ids)));
}
Table::Schema ConnectedFlow::CreateSchema() {
diff --git a/src/trace_processor/perfetto_sql/intrinsics/table_functions/descendant.cc b/src/trace_processor/perfetto_sql/intrinsics/table_functions/descendant.cc
index 4d3ab12..62a5b94 100644
--- a/src/trace_processor/perfetto_sql/intrinsics/table_functions/descendant.cc
+++ b/src/trace_processor/perfetto_sql/intrinsics/table_functions/descendant.cc
@@ -113,11 +113,13 @@
// Nothing matches a null id so return an empty table.
switch (type_) {
case Type::kSlice:
- return tables::DescendantSliceTable::SelectAndExtendParent(
- storage_->slice_table(), {}, {});
+ return std::unique_ptr<Table>(
+ tables::DescendantSliceTable::SelectAndExtendParent(
+ storage_->slice_table(), {}, {}));
case Type::kSliceByStack:
- return tables::DescendantSliceByStackTable::SelectAndExtendParent(
- storage_->slice_table(), {}, {});
+ return std::unique_ptr<Table>(
+ tables::DescendantSliceByStackTable::SelectAndExtendParent(
+ storage_->slice_table(), {}, {}));
}
PERFETTO_FATAL("For GCC");
}
diff --git a/src/trace_processor/perfetto_sql/intrinsics/table_functions/experimental_annotated_stack.cc b/src/trace_processor/perfetto_sql/intrinsics/table_functions/experimental_annotated_stack.cc
index 98b1ab2..d2b7fa2 100644
--- a/src/trace_processor/perfetto_sql/intrinsics/table_functions/experimental_annotated_stack.cc
+++ b/src/trace_processor/perfetto_sql/intrinsics/table_functions/experimental_annotated_stack.cc
@@ -296,9 +296,10 @@
for (uint32_t i = 0; i < cs_rows.size(); i++)
start_id_vals.Append(start_id.value);
- return tables::ExperimentalAnnotatedCallstackTable::SelectAndExtendParent(
- cs_table, std::move(cs_rows), std::move(annotation_vals),
- std::move(start_id_vals));
+ return std::unique_ptr<Table>(
+ tables::ExperimentalAnnotatedCallstackTable::SelectAndExtendParent(
+ cs_table, std::move(cs_rows), std::move(annotation_vals),
+ std::move(start_id_vals)));
}
uint32_t ExperimentalAnnotatedStack::EstimateRowCount() {
diff --git a/src/trace_processor/perfetto_sql/intrinsics/table_functions/experimental_flamegraph.cc b/src/trace_processor/perfetto_sql/intrinsics/table_functions/experimental_flamegraph.cc
index b4d76cf..3f58dfd 100644
--- a/src/trace_processor/perfetto_sql/intrinsics/table_functions/experimental_flamegraph.cc
+++ b/src/trace_processor/perfetto_sql/intrinsics/table_functions/experimental_flamegraph.cc
@@ -28,6 +28,7 @@
#include "perfetto/ext/base/status_or.h"
#include "perfetto/ext/base/string_utils.h"
#include "perfetto/trace_processor/basic_types.h"
+#include "src/trace_processor/containers/string_pool.h"
#include "src/trace_processor/db/column/types.h"
#include "src/trace_processor/db/table.h"
#include "src/trace_processor/importers/proto/heap_graph_tracker.h"
@@ -194,34 +195,38 @@
using tables::ExperimentalFlamegraphTable;
std::vector<FocusedState> ComputeFocusedState(
+ const StringPool& pool,
const ExperimentalFlamegraphTable& table,
const Matcher& focus_matcher) {
// Each row corresponds to a node in the flame chart tree with its parent
// ptr. Root trees (no parents) will have a null parent ptr.
std::vector<FocusedState> focused(table.row_count());
- for (uint32_t i = 0; i < table.row_count(); ++i) {
- auto parent_id = table.parent_id()[i];
+ for (auto it = table.IterateRows(); it; ++it) {
+ auto parent_id = it.parent_id();
// Constraint: all descendants MUST come after their parents.
- PERFETTO_DCHECK(!parent_id.has_value() || *parent_id < table.id()[i]);
+ PERFETTO_DCHECK(!parent_id.has_value() || *parent_id < it.id());
- if (focus_matcher.matches(table.name().GetString(i).ToStdString())) {
+ auto i = it.row_number().row_number();
+ if (focus_matcher.matches(pool.Get(it.name()).ToStdString())) {
// Mark as focused
focused[i] = FocusedState::kFocusedPropagating;
auto current = parent_id;
// Mark all parent nodes as focused
while (current.has_value()) {
- auto current_idx = *table.id().IndexOf(*current);
+ auto c = *table.FindById(*current);
+ uint32_t current_idx = c.ToRowNumber().row_number();
if (focused[current_idx] != FocusedState::kNotFocused) {
// We have already visited these nodes, skip
break;
}
focused[current_idx] = FocusedState::kFocusedNotPropagating;
- current = table.parent_id()[current_idx];
+ current = c.parent_id();
}
- } else if (parent_id.has_value() &&
- focused[*table.id().IndexOf(*parent_id)] ==
- FocusedState::kFocusedPropagating) {
+ } else if (parent_id.has_value() && focused[table.FindById(*parent_id)
+ ->ToRowNumber()
+ .row_number()] ==
+ FocusedState::kFocusedPropagating) {
// Focus cascades downwards.
focused[i] = FocusedState::kFocusedPropagating;
} else {
@@ -245,7 +250,7 @@
return in;
}
std::vector<FocusedState> focused_state =
- ComputeFocusedState(*in, Matcher(focus_str));
+ ComputeFocusedState(storage->string_pool(), *in, Matcher(focus_str));
std::unique_ptr<ExperimentalFlamegraphTable> tbl(
new tables::ExperimentalFlamegraphTable(storage->mutable_string_pool()));
@@ -253,19 +258,21 @@
std::vector<CumulativeCounts> node_to_cumulatives(in->row_count());
for (int64_t idx = in->row_count() - 1; idx >= 0; --idx) {
auto i = static_cast<uint32_t>(idx);
+ auto rr = (*in)[i];
if (focused_state[i] == FocusedState::kNotFocused) {
continue;
}
auto& cumulatives = node_to_cumulatives[i];
- cumulatives.size += in->size()[i];
- cumulatives.count += in->count()[i];
- cumulatives.alloc_size += in->alloc_size()[i];
- cumulatives.alloc_count += in->alloc_count()[i];
+ cumulatives.size += rr.size();
+ cumulatives.count += rr.count();
+ cumulatives.alloc_size += rr.alloc_size();
+ cumulatives.alloc_count += rr.alloc_count();
- auto parent_id = in->parent_id()[i];
+ auto parent_id = rr.parent_id();
if (parent_id.has_value()) {
- auto& parent_cumulatives =
- node_to_cumulatives[*in->id().IndexOf(*parent_id)];
+ uint32_t parent_row =
+ in->FindById(*parent_id)->ToRowNumber().row_number();
+ auto& parent_cumulatives = node_to_cumulatives[parent_row];
parent_cumulatives.size += cumulatives.size;
parent_cumulatives.count += cumulatives.count;
parent_cumulatives.alloc_size += cumulatives.alloc_size;
@@ -275,7 +282,8 @@
// Mapping between the old rows ('node') to the new identifiers.
std::vector<ExperimentalFlamegraphTable::Id> node_to_id(in->row_count());
- for (uint32_t i = 0; i < in->row_count(); ++i) {
+ for (auto it = in->IterateRows(); it; ++it) {
+ uint32_t i = it.row_number().row_number();
if (focused_state[i] == FocusedState::kNotFocused) {
continue;
}
@@ -283,22 +291,23 @@
tables::ExperimentalFlamegraphTable::Row alloc_row{};
// We must reparent the rows as every insertion will get its own
// identifier.
- auto original_parent_id = in->parent_id()[i];
+ auto original_parent_id = it.parent_id();
if (original_parent_id.has_value()) {
- auto original_idx = *in->id().IndexOf(*original_parent_id);
+ auto original_idx =
+ in->FindById(*original_parent_id)->ToRowNumber().row_number();
alloc_row.parent_id = node_to_id[original_idx];
}
- alloc_row.ts = in->ts()[i];
- alloc_row.upid = in->upid()[i];
- alloc_row.profile_type = in->profile_type()[i];
- alloc_row.depth = in->depth()[i];
- alloc_row.name = in->name()[i];
- alloc_row.map_name = in->map_name()[i];
- alloc_row.count = in->count()[i];
- alloc_row.size = in->size()[i];
- alloc_row.alloc_count = in->alloc_count()[i];
- alloc_row.alloc_size = in->alloc_size()[i];
+ alloc_row.ts = it.ts();
+ alloc_row.upid = it.upid();
+ alloc_row.profile_type = it.profile_type();
+ alloc_row.depth = it.depth();
+ alloc_row.name = it.name();
+ alloc_row.map_name = it.map_name();
+ alloc_row.count = it.count();
+ alloc_row.size = it.size();
+ alloc_row.alloc_count = it.alloc_count();
+ alloc_row.alloc_size = it.alloc_size();
const auto& cumulative = node_to_cumulatives[i];
alloc_row.cumulative_count = cumulative.count;
diff --git a/src/trace_processor/perfetto_sql/intrinsics/table_functions/experimental_flat_slice.cc b/src/trace_processor/perfetto_sql/intrinsics/table_functions/experimental_flat_slice.cc
index 8e384e6..6d4ff85 100644
--- a/src/trace_processor/perfetto_sql/intrinsics/table_functions/experimental_flat_slice.cc
+++ b/src/trace_processor/perfetto_sql/intrinsics/table_functions/experimental_flat_slice.cc
@@ -36,8 +36,7 @@
#include "src/trace_processor/tables/track_tables_py.h"
#include "src/trace_processor/types/trace_processor_context.h"
-namespace perfetto {
-namespace trace_processor {
+namespace perfetto::trace_processor {
ExperimentalFlatSlice::ExperimentalFlatSlice(TraceProcessorContext* context)
: context_(context) {}
@@ -67,14 +66,15 @@
auto insert_slice = [&](uint32_t i, int64_t ts,
tables::TrackTable::Id track_id) {
+ auto rr = slice[i];
tables::ExperimentalFlatSliceTable::Row row;
row.ts = ts;
row.dur = -1;
row.track_id = track_id;
- row.category = slice.category()[i];
- row.name = slice.name()[i];
- row.arg_set_id = slice.arg_set_id()[i];
- row.source_id = slice.id()[i];
+ row.category = rr.category();
+ row.name = rr.name();
+ row.arg_set_id = rr.arg_set_id();
+ row.source_id = rr.id();
row.start_bound = start_bound;
row.end_bound = end_bound;
return out->Insert(row).row;
@@ -94,9 +94,9 @@
};
auto terminate_slice = [&](uint32_t out_row, int64_t end_ts) {
- PERFETTO_DCHECK(out->dur()[out_row] == -1);
- int64_t out_ts = out->ts()[out_row];
- out->mutable_dur()->Set(out_row, end_ts - out_ts);
+ auto rr = (*out)[out_row];
+ PERFETTO_DCHECK(rr.dur() == -1);
+ rr.set_dur(end_ts - rr.ts());
};
struct ActiveSlice {
@@ -113,8 +113,9 @@
std::unordered_map<TrackId, Track> tracks;
auto maybe_terminate_active_slice = [&](const Track& t, int64_t fin_ts) {
- int64_t ts = slice.ts()[t.active.source_row.value()];
- int64_t dur = slice.dur()[t.active.source_row.value()];
+ auto rr = slice[t.active.source_row.value()];
+ int64_t ts = rr.ts();
+ int64_t dur = rr.dur();
if (dur == -1 || ts + dur > fin_ts)
return false;
@@ -146,8 +147,9 @@
uint32_t source_row = t.parents[static_cast<size_t>(i)];
t.parents.pop_back();
- int64_t active_ts = out->ts()[t.active.out_row];
- int64_t active_dur = out->dur()[t.active.out_row];
+ auto rr = (*out)[t.active.out_row];
+ int64_t active_ts = rr.ts();
+ int64_t active_dur = rr.dur();
PERFETTO_DCHECK(active_dur != -1);
t.active.source_row = source_row;
@@ -165,8 +167,9 @@
// should have caught it; all code only adds slices from source.
PERFETTO_DCHECK(!t.active.is_sentinel());
- int64_t ts = out->ts()[t.active.out_row];
- int64_t dur = out->dur()[t.active.out_row];
+ auto rr = (*out)[t.active.out_row];
+ int64_t ts = rr.ts();
+ int64_t dur = rr.dur();
// If the active slice is unfinshed, we return that for the caller to
// terminate.
@@ -178,11 +181,11 @@
t.active.out_row = insert_sentinel(ts + dur, track_id);
};
- for (uint32_t i = 0; i < slice.row_count(); ++i) {
+ for (auto it = slice.IterateRows(); it; ++it) {
// TODO(lalitm): this can be optimized using a O(logn) lower bound/filter.
// Not adding for now as a premature optimization but may be needed down the
// line.
- int64_t ts = slice.ts()[i];
+ int64_t ts = it.ts();
if (ts < start_bound)
continue;
@@ -190,15 +193,15 @@
break;
// Ignore instants as they don't factor into flat slice at all.
- if (slice.dur()[i] == 0)
+ if (it.dur() == 0)
continue;
- TrackId track_id = slice.track_id()[i];
+ TrackId track_id = it.track_id();
Track& track = tracks[track_id];
// Initalize the track (if needed) by adding a sentinel slice starting at
// start_bound.
- bool is_root = slice.depth()[i] == 0;
+ bool is_root = it.depth() == 0;
if (!track.initialized) {
// If we are unintialized and our start box picks up slices mid way
// through startup, wait until we reach a root slice.
@@ -221,10 +224,11 @@
// The depth of our slice should also match the depth of the parent stack
// (after adding the previous slice).
- PERFETTO_DCHECK(track.parents.size() == slice.depth()[i]);
+ PERFETTO_DCHECK(track.parents.size() == it.depth());
- track.active.source_row = i;
- track.active.out_row = insert_slice(i, ts, track_id);
+ track.active.source_row = it.row_number().row_number();
+ track.active.out_row =
+ insert_slice(it.row_number().row_number(), ts, track_id);
}
for (const auto& track : tracks) {
@@ -254,5 +258,4 @@
return context_->storage->slice_table().row_count();
}
-} // namespace trace_processor
-} // namespace perfetto
+} // namespace perfetto::trace_processor
diff --git a/src/trace_processor/perfetto_sql/intrinsics/table_functions/experimental_flat_slice_unittest.cc b/src/trace_processor/perfetto_sql/intrinsics/table_functions/experimental_flat_slice_unittest.cc
index 3a107d2..e3a6450 100644
--- a/src/trace_processor/perfetto_sql/intrinsics/table_functions/experimental_flat_slice_unittest.cc
+++ b/src/trace_processor/perfetto_sql/intrinsics/table_functions/experimental_flat_slice_unittest.cc
@@ -57,20 +57,20 @@
class TableAsserter {
public:
- explicit TableAsserter(Table::Iterator it) : iterator_(std::move(it)) {}
+ explicit TableAsserter(tables::ExperimentalFlatSliceTable::Iterator it)
+ : iterator_(std::move(it)) {}
void NextSlice(int64_t ts, int64_t dur) {
- using CI = tables::ExperimentalFlatSliceTable::ColumnIndex;
ASSERT_TRUE(HasMoreSlices());
- ASSERT_EQ(iterator_.Get(CI::ts).AsLong(), ts);
- ASSERT_EQ(iterator_.Get(CI::dur).AsLong(), dur);
+ ASSERT_EQ(iterator_.ts(), ts);
+ ASSERT_EQ(iterator_.dur(), dur);
++iterator_;
}
bool HasMoreSlices() { return bool(iterator_); }
private:
- Table::Iterator iterator_;
+ tables::ExperimentalFlatSliceTable::Iterator iterator_;
};
TEST(ExperimentalFlatSlice, Smoke) {
@@ -102,7 +102,7 @@
auto out = ExperimentalFlatSlice::ComputeFlatSliceTable(table, &pool, 0, 400);
Query q;
q.orders = {out->track_id().ascending(), out->ts().ascending()};
- auto it = out->ApplyAndIterateRows(out->QueryToRowMap(q));
+ auto it = out->FilterToIterator(q);
TableAsserter asserter(std::move(it));
@@ -186,7 +186,7 @@
ExperimentalFlatSlice::ComputeFlatSliceTable(table, &pool, start, end);
Query q;
q.orders = {out->track_id().ascending(), out->ts().ascending()};
- auto it = out->ApplyAndIterateRows(out->QueryToRowMap(q));
+ auto it = out->FilterToIterator(q);
TableAsserter asserter(std::move(it));
diff --git a/src/trace_processor/perfetto_sql/intrinsics/table_functions/experimental_slice_layout_unittest.cc b/src/trace_processor/perfetto_sql/intrinsics/table_functions/experimental_slice_layout_unittest.cc
index 5df44c3..5735a1d 100644
--- a/src/trace_processor/perfetto_sql/intrinsics/table_functions/experimental_slice_layout_unittest.cc
+++ b/src/trace_processor/perfetto_sql/intrinsics/table_functions/experimental_slice_layout_unittest.cc
@@ -42,9 +42,9 @@
using CI = tables::ExperimentalSliceLayoutTable::ColumnIndex;
std::vector<std::string> lines;
for (auto it = table.IterateRows(); it; ++it) {
- int64_t layout_depth = it.Get(CI::layout_depth).long_value;
- int64_t ts = it.Get(CI::ts).long_value;
- int64_t dur = it.Get(CI::dur).long_value;
+ int64_t layout_depth = it.Get(CI::layout_depth).AsLong();
+ int64_t ts = it.Get(CI::ts).AsLong();
+ int64_t dur = it.Get(CI::dur).AsLong();
const char* filter_track_ids = it.Get(CI::filter_track_ids).AsString();
if (std::string("") == filter_track_ids) {
continue;
diff --git a/src/trace_processor/perfetto_sql/intrinsics/table_functions/flamegraph_construction_algorithms.cc b/src/trace_processor/perfetto_sql/intrinsics/table_functions/flamegraph_construction_algorithms.cc
index d47f834..9dd5564 100644
--- a/src/trace_processor/perfetto_sql/intrinsics/table_functions/flamegraph_construction_algorithms.cc
+++ b/src/trace_processor/perfetto_sql/intrinsics/table_functions/flamegraph_construction_algorithms.cc
@@ -283,15 +283,21 @@
static std::unique_ptr<tables::ExperimentalFlamegraphTable>
BuildFlamegraphTableCallstackSizeAndCount(
+ const tables::PerfSampleTable& table,
std::unique_ptr<tables::ExperimentalFlamegraphTable> tbl,
const std::vector<uint32_t>& callsite_to_merged_callsite,
- Table::Iterator it) {
- for (; it; ++it) {
- int64_t callsite_id =
- it.Get(tables::PerfSampleTable::ColumnIndex::callsite_id).long_value;
- int64_t ts = it.Get(tables::PerfSampleTable::ColumnIndex::ts).long_value;
- uint32_t merged_idx =
- callsite_to_merged_callsite[static_cast<uint32_t>(callsite_id)];
+ std::vector<Constraint> constraints,
+ const std::unordered_set<uint32_t>& utids) {
+ Query q;
+ q.constraints = std::move(constraints);
+ for (auto it = table.FilterToIterator(q); it; ++it) {
+ if (utids.find(it.utid()) == utids.end()) {
+ continue;
+ }
+
+ uint32_t callsite_id = it.callsite_id().value_or(CallsiteId(0u)).value;
+ int64_t ts = it.ts();
+ uint32_t merged_idx = callsite_to_merged_callsite[callsite_id];
tbl->mutable_size()->Set(merged_idx, tbl->size()[merged_idx] + 1);
tbl->mutable_count()->Set(merged_idx, tbl->count()[merged_idx] + 1);
tbl->mutable_ts()->Set(merged_idx, ts);
@@ -392,21 +398,6 @@
cs.emplace_back(Constraint{tables::PerfSampleTable::ColumnIndex::ts, tc.op,
SqlValue::Long(tc.value)});
}
- std::vector<uint32_t> cs_rows;
- {
- Query q;
- q.constraints = cs;
- auto it = storage->perf_sample_table().FilterToIterator(q);
- for (; it; ++it) {
- if (utids.find(it.utid()) != utids.end()) {
- cs_rows.push_back(it.row_number().row_number());
- }
- }
- }
- if (cs_rows.empty()) {
- return std::make_unique<tables::ExperimentalFlamegraphTable>(
- storage->mutable_string_pool());
- }
// The logic underneath is selecting a default timestamp to be used by all
// frames which do not have a timestamp. The timestamp is taken from the
@@ -415,7 +406,7 @@
// the table ExperimentalFlamegraphTable in this class.
int64_t default_timestamp = 0;
if (!time_constraints.empty()) {
- auto& tc = time_constraints[0];
+ const auto& tc = time_constraints[0];
if (tc.op == FilterOp::kGt) {
default_timestamp = tc.value + 1;
} else if (tc.op == FilterOp::kLt) {
@@ -431,10 +422,8 @@
default_timestamp,
storage->InternString("perf"));
return BuildFlamegraphTableCallstackSizeAndCount(
- std::move(table_and_callsites.tbl),
- table_and_callsites.callsite_to_merged_callsite,
- storage->perf_sample_table().ApplyAndIterateRows(
- RowMap(std::move(cs_rows))));
+ storage->perf_sample_table(), std::move(table_and_callsites.tbl),
+ table_and_callsites.callsite_to_merged_callsite, std::move(cs), utids);
}
} // namespace perfetto::trace_processor
diff --git a/src/trace_processor/perfetto_sql/stdlib/intervals/intersect.sql b/src/trace_processor/perfetto_sql/stdlib/intervals/intersect.sql
index 2ed2851..08d9808 100644
--- a/src/trace_processor/perfetto_sql/stdlib/intervals/intersect.sql
+++ b/src/trace_processor/perfetto_sql/stdlib/intervals/intersect.sql
@@ -16,7 +16,7 @@
INCLUDE PERFETTO MODULE metasql.table_list;
CREATE PERFETTO MACRO _ii_df_agg(x Expr, y Expr)
-RETURNS Expr AS __intrinsic_stringify!($x), $y;
+RETURNS Expr AS __intrinsic_stringify!($x), input.$y;
CREATE PERFETTO MACRO _ii_df_bind(x Expr, y Expr)
RETURNS Expr AS __intrinsic_table_ptr_bind($x, __intrinsic_stringify!($y));
@@ -33,22 +33,18 @@
)
RETURNS TableOrSubquery AS
(
- WITH sorted_tab AS (
- SELECT * FROM $tab ORDER BY ts
- )
- SELECT
- __intrinsic_interval_tree_intervals_agg(
- id,
- ts,
- dur
- __intrinsic_prefixed_token_zip_join!(
- $agg_columns,
- $agg_columns,
- _ii_df_agg,
- __intrinsic_token_comma!()
- )
+ SELECT __intrinsic_interval_tree_intervals_agg(
+ input.id,
+ input.ts,
+ input.dur
+ __intrinsic_prefixed_token_zip_join!(
+ $agg_columns,
+ $agg_columns,
+ _ii_df_agg,
+ __intrinsic_token_comma!()
)
- FROM sorted_tab
+ )
+ FROM (SELECT * FROM $tab ORDER BY ts) input
);
CREATE PERFETTO MACRO _interval_intersect(
@@ -95,11 +91,11 @@
-- Partition columns. Prefixed to handle case of no partitions.
__intrinsic_prefixed_token_zip_join!(
- (c7, c8, c9, c10),
- $agg_columns,
- _ii_df_bind,
- AND
- )
+ (c7, c8, c9, c10),
+ $agg_columns,
+ _ii_df_bind,
+ AND
+ )
);
CREATE PERFETTO MACRO _interval_intersect_single(
diff --git a/src/trace_processor/sqlite/db_sqlite_table.cc b/src/trace_processor/sqlite/db_sqlite_table.cc
index d1485bb..c119d99 100644
--- a/src/trace_processor/sqlite/db_sqlite_table.cc
+++ b/src/trace_processor/sqlite/db_sqlite_table.cc
@@ -822,6 +822,7 @@
SqlValue value = c->mode == Cursor::Mode::kSingleRow
? source_table->columns()[idx].Get(*c->single_row)
: c->iterator->Get(idx);
+
// We can say kSqliteStatic for strings because all strings are expected
// to come from the string pool. Thus they will be valid for the lifetime
// of trace processor. Similarily, for bytes, we can also use
diff --git a/src/trace_processor/sqlite/db_sqlite_table.h b/src/trace_processor/sqlite/db_sqlite_table.h
index 4085e7c..e438386 100644
--- a/src/trace_processor/sqlite/db_sqlite_table.h
+++ b/src/trace_processor/sqlite/db_sqlite_table.h
@@ -109,6 +109,7 @@
Mode mode = Mode::kSingleRow;
int last_idx_num = -1;
+
Query query;
std::vector<SqlValue> table_function_arguments;
diff --git a/src/trace_processor/storage/BUILD.gn b/src/trace_processor/storage/BUILD.gn
index 844d228..060e821 100644
--- a/src/trace_processor/storage/BUILD.gn
+++ b/src/trace_processor/storage/BUILD.gn
@@ -26,6 +26,8 @@
"../../../include/perfetto/ext/base",
"../../../include/perfetto/trace_processor",
"../containers",
+ "../db:minimal",
+ "../db/column",
"../tables",
"../types",
]
diff --git a/src/trace_processor/storage/trace_storage.cc b/src/trace_processor/storage/trace_storage.cc
index ba53e3e..7f0c973 100644
--- a/src/trace_processor/storage/trace_storage.cc
+++ b/src/trace_processor/storage/trace_storage.cc
@@ -16,39 +16,21 @@
#include "src/trace_processor/storage/trace_storage.h"
-#include <string.h>
-#include <algorithm>
-#include <limits>
+#include <cstdint>
+#include <cstring>
+#include <string>
+#include <vector>
+#include "perfetto/base/logging.h"
#include "perfetto/ext/base/no_destructor.h"
+#include "perfetto/trace_processor/basic_types.h"
+#include "src/trace_processor/containers/null_term_string_view.h"
+#include "src/trace_processor/types/variadic.h"
-namespace perfetto {
-namespace trace_processor {
+namespace perfetto::trace_processor {
namespace {
-void DbTableMaybeUpdateMinMax(const TypedColumn<int64_t>& ts_col,
- int64_t* min_value,
- int64_t* max_value,
- const TypedColumn<int64_t>* dur_col = nullptr) {
- if (ts_col.overlay().empty())
- return;
-
- int64_t col_min = ts_col.Min()->AsLong();
- int64_t col_max = ts_col.Max()->AsLong();
-
- if (dur_col) {
- PERFETTO_CHECK(ts_col.IsSorted());
- PERFETTO_CHECK(dur_col->overlay().size() == ts_col.overlay().size());
- for (uint32_t i = 0; i < dur_col->overlay().size(); i++) {
- col_max = std::max(ts_col[i] + (*dur_col)[i], col_max);
- }
- }
-
- *min_value = std::min(*min_value, col_min);
- *max_value = std::max(*max_value, col_max);
-}
-
std::vector<NullTermStringView> CreateRefTypeStringMap() {
std::vector<NullTermStringView> map(static_cast<size_t>(RefType::kRefMax));
map[static_cast<size_t>(RefType::kRefNoRef)] = NullTermStringView();
@@ -115,34 +97,4 @@
times_ended_[queue_row] = time_ended;
}
-std::pair<int64_t, int64_t> TraceStorage::GetTraceTimestampBoundsNs() const {
- int64_t start_ns = std::numeric_limits<int64_t>::max();
- int64_t end_ns = std::numeric_limits<int64_t>::min();
-
- DbTableMaybeUpdateMinMax(raw_table_.ts(), &start_ns, &end_ns);
- DbTableMaybeUpdateMinMax(sched_slice_table_.ts(), &start_ns, &end_ns,
- &sched_slice_table_.dur());
- DbTableMaybeUpdateMinMax(counter_table_.ts(), &start_ns, &end_ns);
- DbTableMaybeUpdateMinMax(slice_table_.ts(), &start_ns, &end_ns,
- &slice_table_.dur());
- DbTableMaybeUpdateMinMax(heap_profile_allocation_table_.ts(), &start_ns,
- &end_ns);
- DbTableMaybeUpdateMinMax(thread_state_table_.ts(), &start_ns, &end_ns);
- DbTableMaybeUpdateMinMax(android_log_table_.ts(), &start_ns, &end_ns);
- DbTableMaybeUpdateMinMax(heap_graph_object_table_.graph_sample_ts(),
- &start_ns, &end_ns);
- DbTableMaybeUpdateMinMax(perf_sample_table_.ts(), &start_ns, &end_ns);
- DbTableMaybeUpdateMinMax(cpu_profile_stack_sample_table_.ts(), &start_ns,
- &end_ns);
-
- if (start_ns == std::numeric_limits<int64_t>::max()) {
- return std::make_pair(0, 0);
- }
- if (start_ns == end_ns) {
- end_ns += 1;
- }
- return std::make_pair(start_ns, end_ns);
-}
-
-} // namespace trace_processor
-} // namespace perfetto
+} // namespace perfetto::trace_processor
diff --git a/src/trace_processor/storage/trace_storage.h b/src/trace_processor/storage/trace_storage.h
index 74862f1..649c28d 100644
--- a/src/trace_processor/storage/trace_storage.h
+++ b/src/trace_processor/storage/trace_storage.h
@@ -32,13 +32,15 @@
#include <vector>
#include "perfetto/base/logging.h"
+#include "perfetto/base/status.h"
#include "perfetto/base/time.h"
#include "perfetto/ext/base/string_view.h"
#include "perfetto/trace_processor/basic_types.h"
#include "perfetto/trace_processor/status.h"
#include "src/trace_processor/containers/null_term_string_view.h"
-#include "src/trace_processor/containers/row_map.h"
#include "src/trace_processor/containers/string_pool.h"
+#include "src/trace_processor/db/column/types.h"
+#include "src/trace_processor/db/typed_column_internal.h"
#include "src/trace_processor/storage/stats.h"
#include "src/trace_processor/tables/android_tables_py.h"
#include "src/trace_processor/tables/counter_tables_py.h"
@@ -959,60 +961,57 @@
// Number of interned strings in the pool. Includes the empty string w/ ID=0.
size_t string_count() const { return string_pool_.size(); }
- // Start / end ts (in nanoseconds) across the parsed trace events.
- // Returns (0, 0) if the trace is empty.
- std::pair<int64_t, int64_t> GetTraceTimestampBoundsNs() const;
-
- util::Status ExtractArg(uint32_t arg_set_id,
+ base::Status ExtractArg(uint32_t arg_set_id,
const char* key,
std::optional<Variadic>* result) const {
const auto& args = arg_table();
Query q;
q.constraints = {args.arg_set_id().eq(arg_set_id), args.key().eq(key)};
- RowMap filtered = args.QueryToRowMap(q);
- if (filtered.empty()) {
+ auto it = args.FilterToIterator(q);
+ if (!it) {
*result = std::nullopt;
- return util::OkStatus();
+ return base::OkStatus();
}
- if (filtered.size() > 1) {
- return util::ErrStatus(
+ *result = GetArgValue(it.row_number().row_number());
+ if (++it) {
+ return base::ErrStatus(
"EXTRACT_ARG: received multiple args matching arg set id and key");
}
- uint32_t idx = filtered.Get(0);
- *result = GetArgValue(idx);
- return util::OkStatus();
+ return base::OkStatus();
}
Variadic GetArgValue(uint32_t row) const {
+ auto rr = arg_table_[row];
+
Variadic v;
- v.type = *GetVariadicTypeForId(arg_table_.value_type()[row]);
+ v.type = *GetVariadicTypeForId(rr.value_type());
// Force initialization of union to stop GCC complaining.
v.int_value = 0;
switch (v.type) {
case Variadic::Type::kBool:
- v.bool_value = static_cast<bool>(*arg_table_.int_value()[row]);
+ v.bool_value = static_cast<bool>(*rr.int_value());
break;
case Variadic::Type::kInt:
- v.int_value = *arg_table_.int_value()[row];
+ v.int_value = *rr.int_value();
break;
case Variadic::Type::kUint:
- v.uint_value = static_cast<uint64_t>(*arg_table_.int_value()[row]);
+ v.uint_value = static_cast<uint64_t>(*rr.int_value());
break;
case Variadic::Type::kString: {
- auto opt_value = arg_table_.string_value()[row];
+ auto opt_value = rr.string_value();
v.string_value = opt_value ? *opt_value : kNullStringId;
break;
}
case Variadic::Type::kPointer:
- v.pointer_value = static_cast<uint64_t>(*arg_table_.int_value()[row]);
+ v.pointer_value = static_cast<uint64_t>(*rr.int_value());
break;
case Variadic::Type::kReal:
- v.real_value = *arg_table_.real_value()[row];
+ v.real_value = *rr.real_value();
break;
case Variadic::Type::kJson: {
- auto opt_value = arg_table_.string_value()[row];
+ auto opt_value = rr.string_value();
v.json_value = opt_value ? *opt_value : kNullStringId;
break;
}
@@ -1144,8 +1143,8 @@
tables::AndroidKeyEventsTable android_key_events_table_{&string_pool_};
tables::AndroidMotionEventsTable android_motion_events_table_{&string_pool_};
- tables::AndroidInputEventDispatchTable
- android_input_event_dispatch_table_{&string_pool_};
+ tables::AndroidInputEventDispatchTable android_input_event_dispatch_table_{
+ &string_pool_};
tables::StackProfileMappingTable stack_profile_mapping_table_{&string_pool_};
tables::StackProfileFrameTable stack_profile_frame_table_{&string_pool_};
diff --git a/src/trace_processor/tables/BUILD.gn b/src/trace_processor/tables/BUILD.gn
index 7cf8bb0..72796e5 100644
--- a/src/trace_processor/tables/BUILD.gn
+++ b/src/trace_processor/tables/BUILD.gn
@@ -36,6 +36,7 @@
source_set("tables") {
sources = [
+ "macros_internal.cc",
"macros_internal.h",
"table_destructors.cc",
]
@@ -64,6 +65,7 @@
"../../../gn:gtest_and_gmock",
"../containers",
"../db",
+ "../db/column",
]
}
diff --git a/src/trace_processor/tables/macros_internal.cc b/src/trace_processor/tables/macros_internal.cc
new file mode 100644
index 0000000..c2ce1bf
--- /dev/null
+++ b/src/trace_processor/tables/macros_internal.cc
@@ -0,0 +1,137 @@
+/*
+ * Copyright (C) 2024 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/tables/macros_internal.h"
+
+#include <cstdint>
+#include <initializer_list>
+#include <type_traits>
+#include <utility>
+#include <vector>
+
+#include "perfetto/base/logging.h"
+#include "perfetto/public/compiler.h"
+#include "perfetto/trace_processor/ref_counted.h"
+#include "src/trace_processor/containers/bit_vector.h"
+#include "src/trace_processor/containers/row_map.h"
+#include "src/trace_processor/containers/string_pool.h"
+#include "src/trace_processor/db/column.h"
+#include "src/trace_processor/db/column/overlay_layer.h"
+#include "src/trace_processor/db/column/selector_overlay.h"
+#include "src/trace_processor/db/column/storage_layer.h"
+#include "src/trace_processor/db/column_storage_overlay.h"
+
+namespace perfetto::trace_processor::macros_internal {
+
+PERFETTO_NO_INLINE MacroTable::MacroTable(StringPool* pool,
+ std::vector<ColumnLegacy> columns,
+ const MacroTable* parent)
+ : Table(pool, 0u, std::move(columns), EmptyOverlaysFromParent(parent)),
+ allow_inserts_(true),
+ parent_(parent) {}
+
+PERFETTO_NO_INLINE MacroTable::MacroTable(StringPool* pool,
+ std::vector<ColumnLegacy> columns,
+ const MacroTable& parent,
+ const RowMap& parent_overlay)
+ : Table(pool,
+ parent_overlay.size(),
+ std::move(columns),
+ SelectedOverlaysFromParent(parent, parent_overlay)),
+ allow_inserts_(false),
+ parent_(&parent) {}
+
+PERFETTO_NO_INLINE void MacroTable::UpdateOverlaysAfterParentInsert() {
+ CopyLastInsertFrom(parent_->overlays());
+}
+
+PERFETTO_NO_INLINE void MacroTable::UpdateSelfOverlayAfterInsert() {
+ IncrementRowCountAndAddToLastOverlay();
+}
+
+PERFETTO_NO_INLINE std::vector<ColumnLegacy>
+MacroTable::CopyColumnsFromParentOrAddRootColumns(MacroTable* self,
+ const MacroTable* parent) {
+ std::vector<ColumnLegacy> columns;
+ if (parent) {
+ for (const ColumnLegacy& col : parent->columns()) {
+ columns.emplace_back(col, col.index_in_table(), col.overlay_index());
+ }
+ } else {
+ columns.emplace_back(ColumnLegacy::IdColumn(0, 0));
+ columns.emplace_back("type", &self->type_, ColumnLegacy::kNonNull, 1, 0);
+ }
+ return columns;
+}
+
+PERFETTO_NO_INLINE void MacroTable::OnConstructionCompletedRegularConstructor(
+ std::initializer_list<RefPtr<column::StorageLayer>> storage_layers,
+ std::initializer_list<RefPtr<column::OverlayLayer>> null_layers) {
+ std::vector<RefPtr<column::OverlayLayer>> overlay_layers(
+ OverlayCount(parent_) + 1);
+ for (uint32_t i = 0; i < overlay_layers.size() - 1; ++i) {
+ PERFETTO_CHECK(overlays()[i].row_map().IsBitVector());
+ overlay_layers[i].reset(
+ new column::SelectorOverlay(overlays()[i].row_map().GetIfBitVector()));
+ }
+ Table::OnConstructionCompleted(storage_layers, null_layers,
+ std::move(overlay_layers));
+}
+
+PERFETTO_NO_INLINE std::vector<ColumnStorageOverlay>
+MacroTable::EmptyOverlaysFromParent(const MacroTable* parent) {
+ std::vector<ColumnStorageOverlay> overlays(parent ? parent->overlays().size()
+ : 0);
+ for (auto& overlay : overlays) {
+ overlay = ColumnStorageOverlay(BitVector());
+ }
+ overlays.emplace_back();
+ return overlays;
+}
+
+PERFETTO_NO_INLINE std::vector<ColumnStorageOverlay>
+MacroTable::SelectedOverlaysFromParent(
+ const macros_internal::MacroTable& parent,
+ const RowMap& rm) {
+ std::vector<ColumnStorageOverlay> overlays;
+ for (const auto& overlay : parent.overlays()) {
+ overlays.emplace_back(overlay.SelectRows(rm));
+ PERFETTO_DCHECK(overlays.back().size() == rm.size());
+ }
+ overlays.emplace_back(rm.size());
+ return overlays;
+}
+
+BaseConstIterator::BaseConstIterator(const MacroTable* table,
+ Table::Iterator iterator)
+ : iterator_(std::move(iterator)), table_(table) {
+ static_assert(std::is_base_of<Table, MacroTable>::value,
+ "Template param should be a subclass of Table.");
+}
+
+BaseConstIterator::operator bool() const {
+ return bool(iterator_);
+}
+
+BaseConstIterator& BaseConstIterator::operator++() {
+ ++iterator_;
+ return *this;
+}
+
+BaseRowReference::BaseRowReference(const MacroTable* table, uint32_t row_number)
+ : table_(table), row_number_(row_number) {}
+
+} // namespace perfetto::trace_processor::macros_internal
diff --git a/src/trace_processor/tables/macros_internal.h b/src/trace_processor/tables/macros_internal.h
index 5f69c6c..994322d 100644
--- a/src/trace_processor/tables/macros_internal.h
+++ b/src/trace_processor/tables/macros_internal.h
@@ -24,16 +24,13 @@
#include <utility>
#include <vector>
-#include "perfetto/base/compiler.h"
#include "perfetto/base/logging.h"
+#include "perfetto/public/compiler.h"
#include "perfetto/trace_processor/ref_counted.h"
-#include "src/trace_processor/containers/bit_vector.h"
#include "src/trace_processor/containers/row_map.h"
#include "src/trace_processor/containers/string_pool.h"
#include "src/trace_processor/db/column.h"
-#include "src/trace_processor/db/column/data_layer.h"
#include "src/trace_processor/db/column/overlay_layer.h"
-#include "src/trace_processor/db/column/selector_overlay.h"
#include "src/trace_processor/db/column/storage_layer.h"
#include "src/trace_processor/db/column_storage.h"
#include "src/trace_processor/db/column_storage_overlay.h"
@@ -88,61 +85,27 @@
// Constructors for tables created by the regular constructor.
PERFETTO_NO_INLINE explicit MacroTable(StringPool* pool,
std::vector<ColumnLegacy> columns,
- const MacroTable* parent)
- : Table(pool, 0u, std::move(columns), EmptyOverlaysFromParent(parent)),
- allow_inserts_(true),
- parent_(parent) {}
+ const MacroTable* parent);
// Constructor for tables created by SelectAndExtendParent.
MacroTable(StringPool* pool,
std::vector<ColumnLegacy> columns,
const MacroTable& parent,
- const RowMap& parent_overlay)
- : Table(pool,
- parent_overlay.size(),
- std::move(columns),
- SelectedOverlaysFromParent(parent, parent_overlay)),
- allow_inserts_(false),
- parent_(&parent) {}
+ const RowMap& parent_overlay);
~MacroTable() override;
- PERFETTO_NO_INLINE void UpdateOverlaysAfterParentInsert() {
- CopyLastInsertFrom(parent_->overlays());
- }
+ PERFETTO_NO_INLINE void UpdateOverlaysAfterParentInsert();
- PERFETTO_NO_INLINE void UpdateSelfOverlayAfterInsert() {
- IncrementRowCountAndAddToLastOverlay();
- }
+ PERFETTO_NO_INLINE void UpdateSelfOverlayAfterInsert();
PERFETTO_NO_INLINE static std::vector<ColumnLegacy>
CopyColumnsFromParentOrAddRootColumns(MacroTable* self,
- const MacroTable* parent) {
- std::vector<ColumnLegacy> columns;
- if (parent) {
- for (const ColumnLegacy& col : parent->columns()) {
- columns.emplace_back(col, col.index_in_table(), col.overlay_index());
- }
- } else {
- columns.emplace_back(ColumnLegacy::IdColumn(0, 0));
- columns.emplace_back("type", &self->type_, ColumnLegacy::kNonNull, 1, 0);
- }
- return columns;
- }
+ const MacroTable* parent);
PERFETTO_NO_INLINE void OnConstructionCompletedRegularConstructor(
std::initializer_list<RefPtr<column::StorageLayer>> storage_layers,
- std::initializer_list<RefPtr<column::OverlayLayer>> null_layers) {
- std::vector<RefPtr<column::OverlayLayer>> overlay_layers(
- OverlayCount(parent_) + 1);
- for (uint32_t i = 0; i < overlay_layers.size() - 1; ++i) {
- PERFETTO_CHECK(overlays()[i].row_map().IsBitVector());
- overlay_layers[i].reset(new column::SelectorOverlay(
- overlays()[i].row_map().GetIfBitVector()));
- }
- Table::OnConstructionCompleted(storage_layers, null_layers,
- std::move(overlay_layers));
- }
+ std::initializer_list<RefPtr<column::OverlayLayer>> null_layers);
template <typename T>
PERFETTO_NO_INLINE static void AddColumnToVector(
@@ -180,43 +143,36 @@
private:
PERFETTO_NO_INLINE static std::vector<ColumnStorageOverlay>
- EmptyOverlaysFromParent(const MacroTable* parent) {
- std::vector<ColumnStorageOverlay> overlays(
- parent ? parent->overlays().size() : 0);
- for (auto& overlay : overlays) {
- overlay = ColumnStorageOverlay(BitVector());
- }
- overlays.emplace_back();
- return overlays;
- }
+ EmptyOverlaysFromParent(const MacroTable* parent);
PERFETTO_NO_INLINE static std::vector<ColumnStorageOverlay>
SelectedOverlaysFromParent(const macros_internal::MacroTable& parent,
- const RowMap& rm) {
- std::vector<ColumnStorageOverlay> overlays;
- for (const auto& overlay : parent.overlays()) {
- overlays.emplace_back(overlay.SelectRows(rm));
- PERFETTO_DCHECK(overlays.back().size() == rm.size());
- }
- overlays.emplace_back(rm.size());
- return overlays;
- }
+ const RowMap& rm);
const MacroTable* parent_ = nullptr;
};
+class BaseConstIterator {
+ public:
+ explicit operator bool() const;
+ BaseConstIterator& operator++();
+
+ protected:
+ explicit BaseConstIterator(const MacroTable* table, Table::Iterator iterator);
+
+ Table::Iterator iterator_;
+ const MacroTable* table_;
+};
+
// Abstract iterator class for macro tables.
// Extracted to allow sharing with view code.
template <typename Iterator,
typename MacroTable,
typename RowNumber,
typename ConstRowReference>
-class AbstractConstIterator {
+class AbstractConstIterator : public BaseConstIterator {
public:
- explicit operator bool() const { return bool(iterator_); }
-
Iterator& operator++() {
- ++iterator_;
- return *this_it();
+ return static_cast<Iterator&>(BaseConstIterator::operator++());
}
// Returns a RowNumber for the current row.
@@ -226,37 +182,50 @@
// Returns a ConstRowReference to the current row.
ConstRowReference row_reference() const {
- return ConstRowReference(table_, this_it()->CurrentRowNumber());
+ return ConstRowReference(table(), this_it()->CurrentRowNumber());
}
protected:
explicit AbstractConstIterator(const MacroTable* table,
Table::Iterator iterator)
- : iterator_(std::move(iterator)), table_(table) {
- static_assert(std::is_base_of<Table, MacroTable>::value,
- "Template param should be a subclass of Table.");
- }
+ : BaseConstIterator(table, std::move(iterator)) {}
- Table::Iterator iterator_;
- const MacroTable* table_;
+ const MacroTable* table() const {
+ return static_cast<const MacroTable*>(table_);
+ }
private:
Iterator* this_it() { return static_cast<Iterator*>(this); }
const Iterator* this_it() const { return static_cast<const Iterator*>(this); }
};
+class BaseRowNumber {
+ public:
+ // Converts this object to the underlying int value.
+ uint32_t row_number() const { return row_number_; }
+
+ // Allows sorting + storage in a map/set.
+ bool operator<(const BaseRowNumber& other) const {
+ return row_number_ < other.row_number_;
+ }
+
+ protected:
+ explicit BaseRowNumber(uint32_t row_number) : row_number_(row_number) {}
+
+ uint32_t row_number_ = 0;
+};
+
// Abstract RowNumber class for macro tables.
// Extracted to allow sharing with view code.
template <typename MacroTable,
typename ConstRowReference,
typename RowReference = void>
-class AbstractRowNumber {
+class AbstractRowNumber : public BaseRowNumber {
public:
// Converts this RowNumber to a RowReference for the given |table|.
- template <
- typename RR = RowReference,
- typename = typename std::enable_if<!std::is_same<RR, void>::value>::type>
+ template <typename RR = RowReference>
RR ToRowReference(MacroTable* table) const {
+ static_assert(!std::is_same_v<RR, void>);
return RR(table, row_number_);
}
@@ -265,36 +234,34 @@
return ConstRowReference(&table, row_number_);
}
- // Converts this object to the underlying int value.
- uint32_t row_number() const { return row_number_; }
-
- // Allows sorting + storage in a map/set.
- bool operator<(const AbstractRowNumber& other) const {
- return row_number_ < other.row_number_;
- }
-
protected:
- explicit AbstractRowNumber(uint32_t row_number) : row_number_(row_number) {}
+ explicit AbstractRowNumber(uint32_t row_number) : BaseRowNumber(row_number) {}
+};
- private:
+class BaseRowReference {
+ protected:
+ BaseRowReference(const MacroTable* table, uint32_t row_number);
+
+ const MacroTable* table_ = nullptr;
uint32_t row_number_ = 0;
};
// Abstract ConstRowReference class for macro tables.
// Extracted to allow sharing with view code.
template <typename MacroTable, typename RowNumber>
-class AbstractConstRowReference {
+class AbstractConstRowReference : public BaseRowReference {
public:
// Converts this RowReference to a RowNumber object which is more memory
// efficient to store.
RowNumber ToRowNumber() { return RowNumber(row_number_); }
protected:
- AbstractConstRowReference(const MacroTable* table, uint32_t row_number)
- : table_(table), row_number_(row_number) {}
+ const MacroTable* table() const {
+ return static_cast<const MacroTable*>(table_);
+ }
- const MacroTable* table_ = nullptr;
- uint32_t row_number_ = 0;
+ AbstractConstRowReference(const MacroTable* table, uint32_t row_number)
+ : BaseRowReference(table, row_number) {}
};
} // namespace perfetto::trace_processor::macros_internal
diff --git a/src/trace_processor/tables/macros_unittest.cc b/src/trace_processor/tables/macros_unittest.cc
deleted file mode 100644
index f6414cd..0000000
--- a/src/trace_processor/tables/macros_unittest.cc
+++ /dev/null
@@ -1,473 +0,0 @@
-/*
- * Copyright (C) 2019 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/tables/macros.h"
-
-#include "test/gtest_and_gmock.h"
-
-namespace perfetto {
-namespace trace_processor {
-namespace {
-
-// @param arg_set_id {@joinable args.arg_set_id}
-#define PERFETTO_TP_TEST_EVENT_TABLE_DEF(NAME, PARENT, C) \
- NAME(TestEventTable, "event") \
- PARENT(PERFETTO_TP_ROOT_TABLE_PARENT_DEF, C) \
- C(int64_t, ts, Column::Flag::kSorted) \
- C(int64_t, arg_set_id)
-PERFETTO_TP_TABLE(PERFETTO_TP_TEST_EVENT_TABLE_DEF);
-
-#define PERFETTO_TP_TEST_COUNTER_TABLE_DEF(NAME, PARENT, C) \
- NAME(TestCounterTable, "counter") \
- PARENT(PERFETTO_TP_TEST_EVENT_TABLE_DEF, C) \
- C(std::optional<double>, value)
-PERFETTO_TP_TABLE(PERFETTO_TP_TEST_COUNTER_TABLE_DEF);
-
-#define PERFETTO_TP_TEST_SLICE_TABLE_DEF(NAME, PARENT, C) \
- NAME(TestSliceTable, "slice") \
- PARENT(PERFETTO_TP_TEST_EVENT_TABLE_DEF, C) \
- C(std::optional<int64_t>, dur) \
- C(int64_t, depth)
-PERFETTO_TP_TABLE(PERFETTO_TP_TEST_SLICE_TABLE_DEF);
-
-#define PERFETTO_TP_TEST_CPU_SLICE_TABLE_DEF(NAME, PARENT, C) \
- NAME(TestCpuSliceTable, "cpu_slice") \
- PARENT(PERFETTO_TP_TEST_SLICE_TABLE_DEF, C) \
- C(int64_t, cpu) \
- C(int64_t, priority) \
- C(StringPool::Id, end_state)
-PERFETTO_TP_TABLE(PERFETTO_TP_TEST_CPU_SLICE_TABLE_DEF);
-
-#define PERFETTO_TP_TEST_ARGS_TABLE_DEF(NAME, PARENT, C) \
- NAME(TestArgsTable, "args") \
- PARENT(PERFETTO_TP_ROOT_TABLE_PARENT_DEF, C) \
- C(uint32_t, arg_set_id, Column::Flag::kSetId | Column::Flag::kSorted)
-PERFETTO_TP_TABLE(PERFETTO_TP_TEST_ARGS_TABLE_DEF);
-
-#define PERFETTO_TP_TEST_ARGS_CHILD_TABLE_DEF(NAME, PARENT, C) \
- NAME(TestArgsChildTable, "args_child") \
- PARENT(PERFETTO_TP_TEST_ARGS_TABLE_DEF, C) \
- C(uint32_t, child_col)
-PERFETTO_TP_TABLE(PERFETTO_TP_TEST_ARGS_CHILD_TABLE_DEF);
-
-TestEventTable::~TestEventTable() = default;
-TestCounterTable::~TestCounterTable() = default;
-TestSliceTable::~TestSliceTable() = default;
-TestCpuSliceTable::~TestCpuSliceTable() = default;
-TestArgsTable::~TestArgsTable() = default;
-TestArgsChildTable::~TestArgsChildTable() = default;
-
-class TableMacrosUnittest : public ::testing::Test {
- protected:
- StringPool pool_;
-
- TestEventTable event_{&pool_, nullptr};
- TestCounterTable counter_{&pool_, &event_};
- TestSliceTable slice_{&pool_, &event_};
- TestCpuSliceTable cpu_slice_{&pool_, &slice_};
- TestArgsTable args_{&pool_, nullptr};
- TestArgsChildTable args_child_{&pool_, &args_};
-};
-
-TEST_F(TableMacrosUnittest, Name) {
- ASSERT_STREQ(TestEventTable::Name(), "event");
- ASSERT_STREQ(TestSliceTable::Name(), "slice");
- ASSERT_STREQ(TestCpuSliceTable::Name(), "cpu_slice");
-}
-
-TEST_F(TableMacrosUnittest, InsertParent) {
- auto id = event_.Insert(TestEventTable::Row(100, 0)).id;
- ASSERT_EQ(id.value, 0u);
- ASSERT_EQ(event_.type().GetString(0), "event");
- ASSERT_EQ(event_.ts()[0], 100);
- ASSERT_EQ(event_.arg_set_id()[0], 0);
-
- id = slice_.Insert(TestSliceTable::Row(200, 123, 10, 0)).id;
- ASSERT_EQ(id.value, 1u);
-
- ASSERT_EQ(event_.type().GetString(1), "slice");
- ASSERT_EQ(event_.ts()[1], 200);
- ASSERT_EQ(event_.arg_set_id()[1], 123);
- ASSERT_EQ(slice_.type().GetString(0), "slice");
- ASSERT_EQ(slice_.ts()[0], 200);
- ASSERT_EQ(slice_.arg_set_id()[0], 123);
- ASSERT_EQ(slice_.dur()[0], 10);
- ASSERT_EQ(slice_.depth()[0], 0);
-
- id = slice_.Insert(TestSliceTable::Row(210, 456, std::nullopt, 0)).id;
- ASSERT_EQ(id.value, 2u);
-
- ASSERT_EQ(event_.type().GetString(2), "slice");
- ASSERT_EQ(event_.ts()[2], 210);
- ASSERT_EQ(event_.arg_set_id()[2], 456);
- ASSERT_EQ(slice_.type().GetString(1), "slice");
- ASSERT_EQ(slice_.ts()[1], 210);
- ASSERT_EQ(slice_.arg_set_id()[1], 456);
- ASSERT_EQ(slice_.dur()[1], std::nullopt);
- ASSERT_EQ(slice_.depth()[1], 0);
-}
-
-TEST_F(TableMacrosUnittest, InsertChild) {
- event_.Insert(TestEventTable::Row(100, 0));
- slice_.Insert(TestSliceTable::Row(200, 123, 10, 0));
-
- auto reason = pool_.InternString("R");
- auto id =
- cpu_slice_.Insert(TestCpuSliceTable::Row(205, 456, 5, 1, 4, 1024, reason))
- .id;
- ASSERT_EQ(id.value, 2u);
- ASSERT_EQ(event_.type().GetString(2), "cpu_slice");
- ASSERT_EQ(event_.ts()[2], 205);
- ASSERT_EQ(event_.arg_set_id()[2], 456);
-
- ASSERT_EQ(slice_.type().GetString(1), "cpu_slice");
- ASSERT_EQ(slice_.ts()[1], 205);
- ASSERT_EQ(slice_.arg_set_id()[1], 456);
- ASSERT_EQ(slice_.dur()[1], 5);
- ASSERT_EQ(slice_.depth()[1], 1);
-
- ASSERT_EQ(cpu_slice_.type().GetString(0), "cpu_slice");
- ASSERT_EQ(cpu_slice_.ts()[0], 205);
- ASSERT_EQ(cpu_slice_.arg_set_id()[0], 456);
- ASSERT_EQ(cpu_slice_.dur()[0], 5);
- ASSERT_EQ(cpu_slice_.depth()[0], 1);
- ASSERT_EQ(cpu_slice_.cpu()[0], 4);
- ASSERT_EQ(cpu_slice_.priority()[0], 1024);
- ASSERT_EQ(cpu_slice_.end_state()[0], reason);
- ASSERT_EQ(cpu_slice_.end_state().GetString(0), "R");
-}
-
-TEST_F(TableMacrosUnittest, NullableLongComparision) {
- slice_.Insert({});
-
- TestSliceTable::Row row;
- row.dur = 100;
- slice_.Insert(row);
-
- row.dur = 101;
- slice_.Insert(row);
-
- row.dur = 200;
- slice_.Insert(row);
-
- slice_.Insert({});
-
- Table out = slice_.Filter({slice_.dur().is_null()});
- const auto* dur = out.GetColumnByName("dur");
- ASSERT_EQ(out.row_count(), 2u);
- ASSERT_EQ(dur->Get(0).type, SqlValue::kNull);
- ASSERT_EQ(dur->Get(1).type, SqlValue::kNull);
-
- out = slice_.Filter({slice_.dur().is_not_null()});
- dur = out.GetColumnByName("dur");
- ASSERT_EQ(out.row_count(), 3u);
- ASSERT_EQ(dur->Get(0).long_value, 100);
- ASSERT_EQ(dur->Get(1).long_value, 101);
- ASSERT_EQ(dur->Get(2).long_value, 200);
-
- out = slice_.Filter({slice_.dur().lt(101)});
- dur = out.GetColumnByName("dur");
- ASSERT_EQ(out.row_count(), 1u);
- ASSERT_EQ(dur->Get(0).long_value, 100);
-
- out = slice_.Filter({slice_.dur().eq(101)});
- dur = out.GetColumnByName("dur");
- ASSERT_EQ(out.row_count(), 1u);
- ASSERT_EQ(dur->Get(0).long_value, 101);
-
- out = slice_.Filter({slice_.dur().gt(101)});
- dur = out.GetColumnByName("dur");
- ASSERT_EQ(out.row_count(), 1u);
- ASSERT_EQ(dur->Get(0).long_value, 200);
-
- out = slice_.Filter({slice_.dur().ne(100)});
- dur = out.GetColumnByName("dur");
- ASSERT_EQ(out.row_count(), 2u);
- ASSERT_EQ(dur->Get(0).long_value, 101);
- ASSERT_EQ(dur->Get(1).long_value, 200);
-
- out = slice_.Filter({slice_.dur().le(101)});
- dur = out.GetColumnByName("dur");
- ASSERT_EQ(out.row_count(), 2u);
- ASSERT_EQ(dur->Get(0).long_value, 100);
- ASSERT_EQ(dur->Get(1).long_value, 101);
-
- out = slice_.Filter({slice_.dur().ge(101)});
- dur = out.GetColumnByName("dur");
- ASSERT_EQ(out.row_count(), 2u);
- ASSERT_EQ(dur->Get(0).long_value, 101);
- ASSERT_EQ(dur->Get(1).long_value, 200);
-}
-
-TEST_F(TableMacrosUnittest, NullableLongCompareWithDouble) {
- slice_.Insert({});
-
- TestSliceTable::Row row;
- row.dur = 100;
- slice_.Insert(row);
-
- row.dur = std::numeric_limits<int64_t>::max();
- slice_.Insert(row);
-
- row.dur = std::numeric_limits<int64_t>::min();
- slice_.Insert(row);
-
- Table out = slice_.Filter({slice_.dur().eq_value(SqlValue::Double(100.0))});
- const Column* dur = out.GetColumnByName("dur");
- ASSERT_EQ(out.row_count(), 1u);
- ASSERT_EQ(dur->Get(0).long_value, 100);
-
- out = slice_.Filter({slice_.dur().le_value(SqlValue::Double(99.9999))});
- dur = out.GetColumnByName("dur");
- ASSERT_EQ(out.row_count(), 1u);
- ASSERT_EQ(dur->Get(0).long_value, std::numeric_limits<int64_t>::min());
-
- out = slice_.Filter({slice_.dur().ge_value(SqlValue::Double(99.9999))});
- dur = out.GetColumnByName("dur");
- ASSERT_EQ(out.row_count(), 2u);
- ASSERT_EQ(dur->Get(0).long_value, 100);
- ASSERT_EQ(dur->Get(1).long_value, std::numeric_limits<int64_t>::max());
-
- out = slice_.Filter({slice_.dur().eq_value(
- SqlValue::Double(std::numeric_limits<int64_t>::min()))});
- dur = out.GetColumnByName("dur");
- ASSERT_EQ(out.row_count(), 1u);
- ASSERT_EQ(dur->Get(0).long_value, std::numeric_limits<int64_t>::min());
-}
-
-TEST_F(TableMacrosUnittest, NullableLongCompareWrongType) {
- slice_.Insert({});
-
- TestSliceTable::Row row;
- row.dur = 100;
- slice_.Insert(row);
-
- row.dur = 101;
- slice_.Insert(row);
-
- row.dur = 200;
- slice_.Insert(row);
-
- slice_.Insert({});
-
- Table out = slice_.Filter({slice_.dur().ne_value(SqlValue())});
- ASSERT_EQ(out.row_count(), 0u);
-
- out = slice_.Filter({slice_.dur().eq_value(SqlValue::String("100"))});
- ASSERT_EQ(out.row_count(), 0u);
-}
-
-TEST_F(TableMacrosUnittest, NullableDoubleComparision) {
- counter_.Insert({});
-
- TestCounterTable::Row row;
- row.value = 100.0;
- counter_.Insert(row);
-
- row.value = 101.0;
- counter_.Insert(row);
-
- row.value = 200.0;
- counter_.Insert(row);
-
- counter_.Insert({});
-
- Table out = counter_.Filter({counter_.value().is_null()});
- const auto* value = out.GetColumnByName("value");
- ASSERT_EQ(out.row_count(), 2u);
- ASSERT_EQ(value->Get(0).type, SqlValue::kNull);
- ASSERT_EQ(value->Get(1).type, SqlValue::kNull);
-
- out = counter_.Filter({counter_.value().is_not_null()});
- value = out.GetColumnByName("value");
- ASSERT_EQ(out.row_count(), 3u);
- ASSERT_DOUBLE_EQ(value->Get(0).double_value, 100);
- ASSERT_DOUBLE_EQ(value->Get(1).double_value, 101);
- ASSERT_DOUBLE_EQ(value->Get(2).double_value, 200);
-
- out = counter_.Filter({counter_.value().lt(101)});
- value = out.GetColumnByName("value");
- ASSERT_EQ(out.row_count(), 1u);
- ASSERT_DOUBLE_EQ(value->Get(0).double_value, 100);
-
- out = counter_.Filter({counter_.value().eq(101)});
- value = out.GetColumnByName("value");
- ASSERT_EQ(out.row_count(), 1u);
- ASSERT_DOUBLE_EQ(value->Get(0).double_value, 101);
-
- out = counter_.Filter({counter_.value().gt(101)});
- value = out.GetColumnByName("value");
- ASSERT_EQ(out.row_count(), 1u);
- ASSERT_DOUBLE_EQ(value->Get(0).double_value, 200);
-
- out = counter_.Filter({counter_.value().ne(100)});
- value = out.GetColumnByName("value");
- ASSERT_EQ(out.row_count(), 2u);
- ASSERT_DOUBLE_EQ(value->Get(0).double_value, 101);
- ASSERT_DOUBLE_EQ(value->Get(1).double_value, 200);
-
- out = counter_.Filter({counter_.value().le(101)});
- value = out.GetColumnByName("value");
- ASSERT_EQ(out.row_count(), 2u);
- ASSERT_DOUBLE_EQ(value->Get(0).double_value, 100);
- ASSERT_DOUBLE_EQ(value->Get(1).double_value, 101);
-
- out = counter_.Filter({counter_.value().ge(101)});
- value = out.GetColumnByName("value");
- ASSERT_EQ(out.row_count(), 2u);
- ASSERT_DOUBLE_EQ(value->Get(0).double_value, 101);
- ASSERT_DOUBLE_EQ(value->Get(1).double_value, 200);
-}
-
-TEST_F(TableMacrosUnittest, NullableDoubleCompareWithLong) {
- counter_.Insert({});
-
- TestCounterTable::Row row;
- row.value = 100.0;
- counter_.Insert(row);
-
- row.value = 99.9999;
- counter_.Insert(row);
-
- row.value = static_cast<double>(std::numeric_limits<int64_t>::min());
- counter_.Insert(row);
-
- Table out = counter_.Filter({counter_.value().eq_value(SqlValue::Long(100))});
- const Column* value = out.GetColumnByName("value");
- ASSERT_EQ(out.row_count(), 1u);
- ASSERT_DOUBLE_EQ(value->Get(0).double_value, 100.0);
-
- out = counter_.Filter({counter_.value().lt_value(SqlValue::Long(100))});
- value = out.GetColumnByName("value");
- ASSERT_EQ(out.row_count(), 2u);
- ASSERT_DOUBLE_EQ(value->Get(0).double_value, 99.9999);
- ASSERT_DOUBLE_EQ(value->Get(1).double_value,
- std::numeric_limits<int64_t>::min());
-
- out = counter_.Filter({counter_.value().eq_value(
- SqlValue::Long(std::numeric_limits<int64_t>::min()))});
- value = out.GetColumnByName("value");
- ASSERT_EQ(out.row_count(), 1u);
- ASSERT_DOUBLE_EQ(value->Get(0).double_value,
- std::numeric_limits<int64_t>::min());
-}
-
-TEST_F(TableMacrosUnittest, StringComparision) {
- cpu_slice_.Insert({});
-
- TestCpuSliceTable::Row row;
- row.end_state = pool_.InternString("R");
- cpu_slice_.Insert(row);
-
- row.end_state = pool_.InternString("D");
- cpu_slice_.Insert(row);
-
- cpu_slice_.Insert({});
-
- Table out = cpu_slice_.Filter({cpu_slice_.end_state().is_null()});
- const auto* end_state = out.GetColumnByName("end_state");
- ASSERT_EQ(out.row_count(), 2u);
- ASSERT_EQ(end_state->Get(0).type, SqlValue::kNull);
- ASSERT_EQ(end_state->Get(1).type, SqlValue::kNull);
-
- out = cpu_slice_.Filter({cpu_slice_.end_state().is_not_null()});
- end_state = out.GetColumnByName("end_state");
- ASSERT_EQ(out.row_count(), 2u);
- ASSERT_STREQ(end_state->Get(0).string_value, "R");
- ASSERT_STREQ(end_state->Get(1).string_value, "D");
-
- out = cpu_slice_.Filter({cpu_slice_.end_state().lt("R")});
- end_state = out.GetColumnByName("end_state");
- ASSERT_EQ(out.row_count(), 1u);
- ASSERT_STREQ(end_state->Get(0).string_value, "D");
-
- out = cpu_slice_.Filter({cpu_slice_.end_state().eq("D")});
- end_state = out.GetColumnByName("end_state");
- ASSERT_EQ(out.row_count(), 1u);
- ASSERT_STREQ(end_state->Get(0).string_value, "D");
-
- out = cpu_slice_.Filter({cpu_slice_.end_state().gt("D")});
- end_state = out.GetColumnByName("end_state");
- ASSERT_EQ(out.row_count(), 1u);
- ASSERT_STREQ(end_state->Get(0).string_value, "R");
-
- out = cpu_slice_.Filter({cpu_slice_.end_state().ne("D")});
- end_state = out.GetColumnByName("end_state");
- ASSERT_EQ(out.row_count(), 1u);
- ASSERT_STREQ(end_state->Get(0).string_value, "R");
-
- out = cpu_slice_.Filter({cpu_slice_.end_state().le("R")});
- end_state = out.GetColumnByName("end_state");
- ASSERT_EQ(out.row_count(), 2u);
- ASSERT_STREQ(end_state->Get(0).string_value, "R");
- ASSERT_STREQ(end_state->Get(1).string_value, "D");
-
- out = cpu_slice_.Filter({cpu_slice_.end_state().ge("D")});
- end_state = out.GetColumnByName("end_state");
- ASSERT_EQ(out.row_count(), 2u);
- ASSERT_STREQ(end_state->Get(0).string_value, "R");
- ASSERT_STREQ(end_state->Get(1).string_value, "D");
-}
-
-TEST_F(TableMacrosUnittest, FilterIdThenOther) {
- TestCpuSliceTable::Row row;
- row.cpu = 1;
- row.end_state = pool_.InternString("D");
-
- cpu_slice_.Insert(row);
- cpu_slice_.Insert(row);
- cpu_slice_.Insert(row);
-
- auto out =
- cpu_slice_.Filter({cpu_slice_.id().eq(0), cpu_slice_.end_state().eq("D"),
- cpu_slice_.cpu().eq(1)});
- const auto* end_state = out.GetColumnByName("end_state");
- const auto* cpu = out.GetColumnByName("cpu");
-
- ASSERT_EQ(out.row_count(), 1u);
- ASSERT_EQ(cpu->Get(0).long_value, 1u);
- ASSERT_STREQ(end_state->Get(0).string_value, "D");
-}
-
-TEST_F(TableMacrosUnittest, Sort) {
- ASSERT_TRUE(event_.ts().IsSorted());
-
- event_.Insert(TestEventTable::Row(0 /* ts */, 100 /* arg_set_id */));
- event_.Insert(TestEventTable::Row(1 /* ts */, 1 /* arg_set_id */));
- event_.Insert(TestEventTable::Row(2 /* ts */, 3 /* arg_set_id */));
-
- Table out = event_.Sort({event_.arg_set_id().ascending()});
- const auto* ts = out.GetColumnByName("ts");
- const auto* arg_set_id = out.GetColumnByName("arg_set_id");
-
- ASSERT_FALSE(ts->IsSorted());
- ASSERT_TRUE(arg_set_id->IsSorted());
-
- ASSERT_EQ(arg_set_id->Get(0).long_value, 1);
- ASSERT_EQ(arg_set_id->Get(1).long_value, 3);
- ASSERT_EQ(arg_set_id->Get(2).long_value, 100);
-}
-
-TEST_F(TableMacrosUnittest, ChildDoesntInheritArgsSetFlag) {
- ASSERT_FALSE(args_child_.arg_set_id().IsSetId());
- ASSERT_FALSE(TestArgsChildTable::ComputeStaticSchema()
- .columns[args_child_.arg_set_id().index_in_table()]
- .is_set_id);
-}
-
-} // namespace
-} // namespace trace_processor
-} // namespace perfetto
diff --git a/src/trace_processor/tables/py_tables_benchmark.cc b/src/trace_processor/tables/py_tables_benchmark.cc
index ed19da1..2491ca9 100644
--- a/src/trace_processor/tables/py_tables_benchmark.cc
+++ b/src/trace_processor/tables/py_tables_benchmark.cc
@@ -108,7 +108,7 @@
root.Insert({});
for (auto _ : state) {
- benchmark::DoNotOptimize(root.ApplyAndIterateRows(root.QueryToRowMap(q)));
+ benchmark::DoNotOptimize(root.FilterToIterator(q));
}
}
BENCHMARK(BM_TableFilterRootId)->Apply(TableFilterArgs);
@@ -129,7 +129,7 @@
}
for (auto _ : state) {
- benchmark::DoNotOptimize(root.ApplyAndIterateRows(root.QueryToRowMap(q)));
+ benchmark::DoNotOptimize(root.FilterToIterator(q));
}
}
BENCHMARK(BM_TableFilterRootIdAndOther)->Apply(TableFilterArgs);
@@ -148,7 +148,7 @@
}
for (auto _ : state) {
- benchmark::DoNotOptimize(child.ApplyAndIterateRows(child.QueryToRowMap(q)));
+ benchmark::DoNotOptimize(child.FilterToIterator(q));
}
}
BENCHMARK(BM_TableFilterChildId)->Apply(TableFilterArgs);
@@ -172,7 +172,7 @@
}
for (auto _ : state) {
- benchmark::DoNotOptimize(child.ApplyAndIterateRows(child.QueryToRowMap(q)));
+ benchmark::DoNotOptimize(child.FilterToIterator(q));
}
}
BENCHMARK(BM_TableFilterChildIdAndSortedInRoot)->Apply(TableFilterArgs);
@@ -193,7 +193,7 @@
}
for (auto _ : state) {
- benchmark::DoNotOptimize(root.ApplyAndIterateRows(root.QueryToRowMap(q)));
+ benchmark::DoNotOptimize(root.FilterToIterator(q));
}
}
BENCHMARK(BM_TableFilterRootNonNullEqMatchMany)->Apply(TableFilterArgs);
@@ -216,7 +216,7 @@
}
for (auto _ : state) {
- benchmark::DoNotOptimize(root.ApplyAndIterateRows(root.QueryToRowMap(q)));
+ benchmark::DoNotOptimize(root.FilterToIterator(q));
}
}
BENCHMARK(BM_TableFilterRootMultipleNonNull)->Apply(TableFilterArgs);
@@ -241,7 +241,7 @@
}
for (auto _ : state) {
- benchmark::DoNotOptimize(root.ApplyAndIterateRows(root.QueryToRowMap(q)));
+ benchmark::DoNotOptimize(root.FilterToIterator(q));
}
}
BENCHMARK(BM_TableFilterRootNullableEqMatchMany)->Apply(TableFilterArgs);
@@ -265,7 +265,7 @@
}
for (auto _ : state) {
- benchmark::DoNotOptimize(child.ApplyAndIterateRows(child.QueryToRowMap(q)));
+ benchmark::DoNotOptimize(child.FilterToIterator(q));
}
}
BENCHMARK(BM_TableFilterChildNonNullEqMatchMany)->Apply(TableFilterArgs);
@@ -292,7 +292,7 @@
}
for (auto _ : state) {
- benchmark::DoNotOptimize(child.ApplyAndIterateRows(child.QueryToRowMap(q)));
+ benchmark::DoNotOptimize(child.FilterToIterator(q));
}
}
BENCHMARK(BM_TableFilterChildNullableEqMatchMany)->Apply(TableFilterArgs);
@@ -317,7 +317,7 @@
}
for (auto _ : state) {
- benchmark::DoNotOptimize(child.ApplyAndIterateRows(child.QueryToRowMap(q)));
+ benchmark::DoNotOptimize(child.FilterToIterator(q));
}
}
BENCHMARK(BM_TableFilterChildNonNullEqMatchManyInParent)
@@ -343,7 +343,7 @@
Query q;
q.constraints = {child.root_nullable().eq(1)};
for (auto _ : state) {
- benchmark::DoNotOptimize(child.ApplyAndIterateRows(child.QueryToRowMap(q)));
+ benchmark::DoNotOptimize(child.FilterToIterator(q));
}
}
BENCHMARK(BM_TableFilterChildNullableEqMatchManyInParent)
@@ -364,7 +364,7 @@
Query q;
q.constraints = {root.root_sorted().eq(22)};
for (auto _ : state) {
- benchmark::DoNotOptimize(root.ApplyAndIterateRows(root.QueryToRowMap(q)));
+ benchmark::DoNotOptimize(root.FilterToIterator(q));
}
}
BENCHMARK(BM_TableFilterParentSortedEq)->Apply(TableFilterArgs);
@@ -391,7 +391,7 @@
q.constraints = {root.root_sorted().eq(last_group),
root.root_non_null().eq(size - 1)};
for (auto _ : state) {
- benchmark::DoNotOptimize(root.ApplyAndIterateRows(root.QueryToRowMap(q)));
+ benchmark::DoNotOptimize(root.FilterToIterator(q));
}
}
BENCHMARK(BM_TableFilterParentSortedAndOther)->Apply(TableFilterArgs);
@@ -413,7 +413,7 @@
Query q;
q.constraints = {child.child_sorted().eq(22)};
for (auto _ : state) {
- benchmark::DoNotOptimize(child.ApplyAndIterateRows(child.QueryToRowMap(q)));
+ benchmark::DoNotOptimize(child.FilterToIterator(q));
}
}
BENCHMARK(BM_TableFilterChildSortedEq)->Apply(TableFilterArgs);
@@ -438,7 +438,7 @@
Query q;
q.constraints = {child.root_sorted().eq(22)};
for (auto _ : state) {
- benchmark::DoNotOptimize(child.ApplyAndIterateRows(child.QueryToRowMap(q)));
+ benchmark::DoNotOptimize(child.FilterToIterator(q));
}
}
BENCHMARK(BM_TableFilterChildSortedEqInParent)->Apply(TableFilterArgs);
@@ -461,7 +461,7 @@
Query q;
q.orders = {root.root_non_null().ascending()};
for (auto _ : state) {
- benchmark::DoNotOptimize(root.ApplyAndIterateRows(root.QueryToRowMap(q)));
+ benchmark::DoNotOptimize(root.FilterToIterator(q));
}
}
BENCHMARK(BM_TableSortRootNonNull)->Apply(TableSortArgs);
@@ -485,7 +485,7 @@
Query q;
q.orders = {root.root_nullable().ascending()};
for (auto _ : state) {
- benchmark::DoNotOptimize(root.ApplyAndIterateRows(root.QueryToRowMap(q)));
+ benchmark::DoNotOptimize(root.FilterToIterator(q));
}
}
BENCHMARK(BM_TableSortRootNullable)->Apply(TableSortArgs);
@@ -515,7 +515,7 @@
Query q;
q.orders = {child.root_non_null().ascending()};
for (auto _ : state) {
- benchmark::DoNotOptimize(child.ApplyAndIterateRows(child.QueryToRowMap(q)));
+ benchmark::DoNotOptimize(child.FilterToIterator(q));
}
}
BENCHMARK(BM_TableSortChildNonNullInParent)->Apply(TableSortArgs);
@@ -547,7 +547,7 @@
Query q;
q.orders = {child.root_nullable().ascending()};
for (auto _ : state) {
- benchmark::DoNotOptimize(child.ApplyAndIterateRows(child.QueryToRowMap(q)));
+ benchmark::DoNotOptimize(child.FilterToIterator(q));
}
}
BENCHMARK(BM_TableSortChildNullableInParent)->Apply(TableSortArgs);
diff --git a/src/trace_processor/tables/py_tables_unittest.cc b/src/trace_processor/tables/py_tables_unittest.cc
index 1f4a4ef..344e17b 100644
--- a/src/trace_processor/tables/py_tables_unittest.cc
+++ b/src/trace_processor/tables/py_tables_unittest.cc
@@ -20,6 +20,7 @@
#include "src/trace_processor/containers/string_pool.h"
#include "src/trace_processor/db/column.h"
+#include "src/trace_processor/db/column/types.h"
#include "src/trace_processor/db/column_storage.h"
#include "src/trace_processor/tables/py_tables_unittest_py.h"
@@ -73,9 +74,9 @@
TEST_F(PyTablesUnittest, InsertEvent) {
event_.Insert(TestEventTable::Row(100, 0));
- ASSERT_EQ(event_.type().GetString(0).ToStdString(), "event");
- ASSERT_EQ(event_.ts()[0], 100);
- ASSERT_EQ(event_.arg_set_id()[0], 0u);
+ ASSERT_EQ(pool_.Get(event_[0].type()).ToStdString(), "event");
+ ASSERT_EQ(event_[0].ts(), 100);
+ ASSERT_EQ(event_[0].arg_set_id(), 0u);
}
TEST_F(PyTablesUnittest, InsertEventSpecifyCols) {
@@ -84,16 +85,16 @@
row.arg_set_id = 0;
event_.Insert(row);
- ASSERT_EQ(event_.type().GetString(0).ToStdString(), "event");
- ASSERT_EQ(event_.ts()[0], 100);
- ASSERT_EQ(event_.arg_set_id()[0], 0u);
+ ASSERT_EQ(pool_.Get(event_[0].type()).ToStdString(), "event");
+ ASSERT_EQ(event_[0].ts(), 100);
+ ASSERT_EQ(event_[0].arg_set_id(), 0u);
}
TEST_F(PyTablesUnittest, MutableColumn) {
event_.Insert(TestEventTable::Row(100, 0));
- ASSERT_EQ((*event_.mutable_ts())[0], 100);
- ASSERT_EQ((*event_.mutable_arg_set_id())[0], 0u);
+ ASSERT_EQ(event_[0].ts(), 100);
+ ASSERT_EQ(event_[0].arg_set_id(), 0u);
}
TEST_F(PyTablesUnittest, ShrinkToFit) {
@@ -142,32 +143,32 @@
slice_.Insert(TestSliceTable::Row(200, 3, 20));
ASSERT_EQ(event_.row_count(), 4u);
- ASSERT_EQ(event_.id()[0], TestEventTable::Id{0});
- ASSERT_EQ(event_.type().GetString(0), "event");
- ASSERT_EQ(event_.ts()[0], 50);
+ ASSERT_EQ(event_[0].id(), TestEventTable::Id{0});
+ ASSERT_EQ(pool_.Get(event_[0].type()), "event");
+ ASSERT_EQ(event_[0].ts(), 50);
- ASSERT_EQ(event_.id()[1], TestEventTable::Id{1});
- ASSERT_EQ(event_.type().GetString(1), "slice");
- ASSERT_EQ(event_.ts()[1], 100);
+ ASSERT_EQ(event_[1].id(), TestEventTable::Id{1});
+ ASSERT_EQ(pool_.Get(event_[1].type()), "slice");
+ ASSERT_EQ(event_[1].ts(), 100);
- ASSERT_EQ(event_.id()[2], TestEventTable::Id{2});
- ASSERT_EQ(event_.type().GetString(2), "event");
- ASSERT_EQ(event_.ts()[2], 150);
+ ASSERT_EQ(event_[2].id(), TestEventTable::Id{2});
+ ASSERT_EQ(pool_.Get(event_[2].type()), "event");
+ ASSERT_EQ(event_[2].ts(), 150);
- ASSERT_EQ(event_.id()[3], TestEventTable::Id{3});
- ASSERT_EQ(event_.type().GetString(3), "slice");
- ASSERT_EQ(event_.ts()[3], 200);
+ ASSERT_EQ(event_[3].id(), TestEventTable::Id{3});
+ ASSERT_EQ(pool_.Get(event_[3].type()), "slice");
+ ASSERT_EQ(event_[3].ts(), 200);
ASSERT_EQ(slice_.row_count(), 2u);
- ASSERT_EQ(slice_.id()[0], TestEventTable::Id{1});
- ASSERT_EQ(slice_.type().GetString(0), "slice");
- ASSERT_EQ(slice_.ts()[0], 100);
- ASSERT_EQ(slice_.dur()[0], 10);
+ ASSERT_EQ(slice_[0].id(), TestEventTable::Id{1});
+ ASSERT_EQ(pool_.Get(slice_[0].type()), "slice");
+ ASSERT_EQ(slice_[0].ts(), 100);
+ ASSERT_EQ(slice_[0].dur(), 10);
- ASSERT_EQ(slice_.id()[1], TestEventTable::Id{3});
- ASSERT_EQ(slice_.type().GetString(1), "slice");
- ASSERT_EQ(slice_.ts()[1], 200);
- ASSERT_EQ(slice_.dur()[1], 20);
+ ASSERT_EQ(slice_[1].id(), TestEventTable::Id{3});
+ ASSERT_EQ(pool_.Get(slice_[1].type()), "slice");
+ ASSERT_EQ(slice_[1].ts(), 200);
+ ASSERT_EQ(slice_[1].dur(), 20);
}
TEST_F(PyTablesUnittest, Extend) {
@@ -182,24 +183,12 @@
auto slice_ext = TestSliceTable::ExtendParent(event_, std::move(dur));
ASSERT_EQ(slice_ext->row_count(), 3u);
- ASSERT_EQ(
- slice_ext->columns()[TestSliceTable::ColumnIndex::ts].Get(0).AsLong(),
- 50);
- ASSERT_EQ(
- slice_ext->columns()[TestSliceTable::ColumnIndex::dur].Get(0).AsLong(),
- 512);
- ASSERT_EQ(
- slice_ext->columns()[TestSliceTable::ColumnIndex::ts].Get(1).AsLong(),
- 100);
- ASSERT_EQ(
- slice_ext->columns()[TestSliceTable::ColumnIndex::dur].Get(1).AsLong(),
- 1024);
- ASSERT_EQ(
- slice_ext->columns()[TestSliceTable::ColumnIndex::ts].Get(2).AsLong(),
- 150);
- ASSERT_EQ(
- slice_ext->columns()[TestSliceTable::ColumnIndex::dur].Get(2).AsLong(),
- 2048);
+ ASSERT_EQ((*slice_ext)[0].ts(), 50);
+ ASSERT_EQ((*slice_ext)[0].dur(), 512);
+ ASSERT_EQ((*slice_ext)[1].ts(), 100);
+ ASSERT_EQ((*slice_ext)[1].dur(), 1024);
+ ASSERT_EQ((*slice_ext)[2].ts(), 150);
+ ASSERT_EQ((*slice_ext)[2].dur(), 2048);
}
TEST_F(PyTablesUnittest, SelectAndExtend) {
@@ -215,12 +204,8 @@
auto slice_ext = TestSliceTable::SelectAndExtendParent(
event_, std::move(rows), std::move(dur));
ASSERT_EQ(slice_ext->row_count(), 1u);
- ASSERT_EQ(
- slice_ext->columns()[TestSliceTable::ColumnIndex::ts].Get(0).AsLong(),
- 100);
- ASSERT_EQ(
- slice_ext->columns()[TestSliceTable::ColumnIndex::dur].Get(0).AsLong(),
- 1024);
+ ASSERT_EQ((*slice_ext)[0].ts(), 100);
+ ASSERT_EQ((*slice_ext)[0].dur(), 1024);
}
TEST_F(PyTablesUnittest, SetIdColumns) {
@@ -245,56 +230,47 @@
static constexpr uint32_t kFilterArgSetId = 1;
Query q;
q.constraints = {table.arg_set_id().eq(kFilterArgSetId)};
- auto res = table.QueryToRowMap(q);
- ASSERT_TRUE(res.empty());
+ auto res = table.FilterToIterator(q);
+ ASSERT_TRUE(!res);
}
{
static constexpr uint32_t kFilterArgSetId = 9;
Query q;
q.constraints = {table.arg_set_id().eq(kFilterArgSetId)};
- auto res = table.QueryToRowMap(q);
- ASSERT_TRUE(res.empty());
+ auto it = table.FilterToIterator(q);
+ ASSERT_TRUE(!it);
}
- auto arg_set_id_col_idx =
- static_cast<uint32_t>(TestArgsTable::ColumnIndex::arg_set_id);
-
// Verify that filtering equality for real arg set ids works as expected.
{
static constexpr uint32_t kFilterArgSetId = 4;
Query q;
q.constraints = {table.arg_set_id().eq(kFilterArgSetId)};
- auto res = table.QueryToRowMap(q);
- ASSERT_EQ(res.size(), 4u);
- for (auto it = table.ApplyAndIterateRows(std::move(res)); it; ++it) {
- auto arg_set_id =
- static_cast<uint32_t>(it.Get(arg_set_id_col_idx).AsLong());
- ASSERT_EQ(arg_set_id, kFilterArgSetId);
+ uint32_t cnt = 0;
+ for (auto it = table.FilterToIterator(q); it; ++it, ++cnt) {
+ ASSERT_EQ(it.arg_set_id(), kFilterArgSetId);
}
+ ASSERT_EQ(cnt, 4u);
}
{
static constexpr uint32_t kFilterArgSetId = 0;
Query q;
q.constraints = {table.arg_set_id().eq(kFilterArgSetId)};
- auto res = table.QueryToRowMap(q);
- ASSERT_EQ(res.size(), 2u);
- for (auto it = table.ApplyAndIterateRows(std::move(res)); it; ++it) {
- auto arg_set_id =
- static_cast<uint32_t>(it.Get(arg_set_id_col_idx).AsLong());
- ASSERT_EQ(arg_set_id, kFilterArgSetId);
+ uint32_t cnt = 0;
+ for (auto it = table.FilterToIterator(q); it; ++it, ++cnt) {
+ ASSERT_EQ(it.arg_set_id(), kFilterArgSetId);
}
+ ASSERT_EQ(cnt, 2u);
}
{
static constexpr uint32_t kFilterArgSetId = 8;
Query q;
q.constraints = {table.arg_set_id().eq(kFilterArgSetId)};
- auto res = table.QueryToRowMap(q);
- ASSERT_EQ(res.size(), 1u);
- for (auto it = table.ApplyAndIterateRows(std::move(res)); it; ++it) {
- auto arg_set_id =
- static_cast<uint32_t>(it.Get(arg_set_id_col_idx).AsLong());
- ASSERT_EQ(arg_set_id, kFilterArgSetId);
+ uint32_t cnt = 0;
+ for (auto it = table.FilterToIterator(q); it; ++it, ++cnt) {
+ ASSERT_EQ(it.arg_set_id(), kFilterArgSetId);
}
+ ASSERT_EQ(cnt, 1u);
}
// Verify that filtering equality for arg set ids after filtering another
@@ -304,13 +280,11 @@
Query q;
q.constraints = {table.int_value().eq(200),
table.arg_set_id().eq(kFilterArgSetId)};
- auto res = table.QueryToRowMap(q);
- ASSERT_EQ(res.size(), 2u);
- for (auto it = table.ApplyAndIterateRows(std::move(res)); it; ++it) {
- uint32_t arg_set_id =
- static_cast<uint32_t>(it.Get(arg_set_id_col_idx).AsLong());
- ASSERT_EQ(arg_set_id, kFilterArgSetId);
+ uint32_t cnt = 0;
+ for (auto it = table.FilterToIterator(q); it; ++it, ++cnt) {
+ ASSERT_EQ(it.arg_set_id(), kFilterArgSetId);
}
+ ASSERT_EQ(cnt, 2u);
}
}
diff --git a/src/trace_processor/trace_processor_impl.cc b/src/trace_processor/trace_processor_impl.cc
index 2536e87..c4a1cb2 100644
--- a/src/trace_processor/trace_processor_impl.cc
+++ b/src/trace_processor/trace_processor_impl.cc
@@ -302,6 +302,61 @@
return modules;
}
+std::pair<int64_t, int64_t> GetTraceTimestampBoundsNs(
+ const TraceStorage& storage) {
+ int64_t start_ns = std::numeric_limits<int64_t>::max();
+ int64_t end_ns = std::numeric_limits<int64_t>::min();
+ for (auto it = storage.raw_table().IterateRows(); it; ++it) {
+ start_ns = std::min(it.ts(), start_ns);
+ end_ns = std::max(it.ts(), end_ns);
+ }
+ for (auto it = storage.sched_slice_table().IterateRows(); it; ++it) {
+ start_ns = std::min(it.ts(), start_ns);
+ end_ns = std::max(it.ts() + it.dur(), end_ns);
+ }
+ for (auto it = storage.counter_table().IterateRows(); it; ++it) {
+ start_ns = std::min(it.ts(), start_ns);
+ end_ns = std::max(it.ts(), end_ns);
+ }
+ for (auto it = storage.slice_table().IterateRows(); it; ++it) {
+ start_ns = std::min(it.ts(), start_ns);
+ end_ns = std::max(it.ts() + it.dur(), end_ns);
+ }
+ for (auto it = storage.heap_profile_allocation_table().IterateRows(); it;
+ ++it) {
+ start_ns = std::min(it.ts(), start_ns);
+ end_ns = std::max(it.ts(), end_ns);
+ }
+ for (auto it = storage.thread_state_table().IterateRows(); it; ++it) {
+ start_ns = std::min(it.ts(), start_ns);
+ end_ns = std::max(it.ts() + it.dur(), end_ns);
+ }
+ for (auto it = storage.android_log_table().IterateRows(); it; ++it) {
+ start_ns = std::min(it.ts(), start_ns);
+ end_ns = std::max(it.ts(), end_ns);
+ }
+ for (auto it = storage.heap_graph_object_table().IterateRows(); it; ++it) {
+ start_ns = std::min(it.graph_sample_ts(), start_ns);
+ end_ns = std::max(it.graph_sample_ts(), end_ns);
+ }
+ for (auto it = storage.perf_sample_table().IterateRows(); it; ++it) {
+ start_ns = std::min(it.ts(), start_ns);
+ end_ns = std::max(it.ts(), end_ns);
+ }
+ for (auto it = storage.cpu_profile_stack_sample_table().IterateRows(); it;
+ ++it) {
+ start_ns = std::min(it.ts(), start_ns);
+ end_ns = std::max(it.ts(), end_ns);
+ }
+ if (start_ns == std::numeric_limits<int64_t>::max()) {
+ return std::make_pair(0, 0);
+ }
+ if (start_ns == end_ns) {
+ end_ns += 1;
+ }
+ return std::make_pair(start_ns, end_ns);
+}
+
} // namespace
TraceProcessorImpl::TraceProcessorImpl(const Config& cfg)
@@ -403,7 +458,7 @@
void TraceProcessorImpl::Flush() {
TraceProcessorStorageImpl::Flush();
BuildBoundsTable(engine_->sqlite_engine()->db(),
- context_.storage->GetTraceTimestampBoundsNs());
+ GetTraceTimestampBoundsNs(*context_.storage));
}
base::Status TraceProcessorImpl::NotifyEndOfFile() {
@@ -431,7 +486,7 @@
// trace bounds: this is important for parsers like ninja which wait until
// the end to flush all their data.
BuildBoundsTable(engine_->sqlite_engine()->db(),
- context_.storage->GetTraceTimestampBoundsNs());
+ GetTraceTimestampBoundsNs(*context_.storage));
TraceProcessorStorageImpl::DestroyContext();
return base::OkStatus();
@@ -972,7 +1027,7 @@
}
// Fill trace bounds table.
- BuildBoundsTable(db, context_.storage->GetTraceTimestampBoundsNs());
+ BuildBoundsTable(db, GetTraceTimestampBoundsNs(*context_.storage));
}
namespace {
diff --git a/test/gtest_and_gmock.h b/test/gtest_and_gmock.h
index 24d8bed..69c112a 100644
--- a/test/gtest_and_gmock.h
+++ b/test/gtest_and_gmock.h
@@ -46,12 +46,14 @@
#endif // defined(__clang__)
-#include <gmock/gmock-matchers.h> // IWYU pragma: export
-#include <gmock/gmock-more-matchers.h> // IWYU pragma: export
-#include <gmock/gmock-spec-builders.h> // IWYU pragma: export
-#include <gmock/gmock.h> // IWYU pragma: export
-#include <gtest/gtest-matchers.h> // IWYU pragma: export
-#include <gtest/gtest.h> // IWYU pragma: export
+#include <gmock/gmock-actions.h> // IWYU pragma: export
+#include <gmock/gmock-function-mocker.h> // IWYU pragma: export
+#include <gmock/gmock-matchers.h> // IWYU pragma: export
+#include <gmock/gmock-more-matchers.h> // IWYU pragma: export
+#include <gmock/gmock-spec-builders.h> // IWYU pragma: export
+#include <gmock/gmock.h> // IWYU pragma: export
+#include <gtest/gtest-matchers.h> // IWYU pragma: export
+#include <gtest/gtest.h> // IWYU pragma: export
#if defined(__GNUC__) || defined(__clang__)
#pragma GCC diagnostic pop
diff --git a/test/trace_processor/diff_tests/metrics/android/tests.py b/test/trace_processor/diff_tests/metrics/android/tests.py
index 03619ec..76508c2 100644
--- a/test/trace_processor/diff_tests/metrics/android/tests.py
+++ b/test/trace_processor/diff_tests/metrics/android/tests.py
@@ -425,9 +425,9 @@
def test_wattson_estimate_output(self):
return DiffTestBlueprint(
trace=DataPath('wattson_eos_suspend.pb'),
- query=Metric("wattson_trace_estimate"),
+ query=Metric("wattson_trace_rails"),
out=Csv("""
- wattson_trace_estimate {
+ wattson_trace_rails {
metric_version: 2
period_info {
period_id: 1
diff --git a/ui/src/plugins/dev.perfetto.PinAndroidPerfMetrics/handlers/pinCujScoped.ts b/ui/src/plugins/dev.perfetto.PinAndroidPerfMetrics/handlers/pinCujScoped.ts
index 14065f3..f1c2b8b 100644
--- a/ui/src/plugins/dev.perfetto.PinAndroidPerfMetrics/handlers/pinCujScoped.ts
+++ b/ui/src/plugins/dev.perfetto.PinAndroidPerfMetrics/handlers/pinCujScoped.ts
@@ -145,7 +145,7 @@
private async findFirstJank(
ctx: PluginContextTrace,
- ): Promise<SliceIdentifier> {
+ ): Promise<SliceIdentifier | undefined> {
const queryForFirstJankyFrame = `
SELECT slice_id, track_id, ts, dur FROM slice
WHERE type = "actual_frame_timeline_slice"
@@ -155,6 +155,9 @@
AS VARCHAR(20) );
`;
const queryResult = await ctx.engine.query(queryForFirstJankyFrame);
+ if (queryResult.numRows() === 0) {
+ return undefined;
+ }
const row = queryResult.firstRow({
slice_id: NUM,
track_id: NUM,
@@ -172,7 +175,9 @@
private async focusOnFirstJank(ctx: PluginContextTrace) {
const slice = await this.findFirstJank(ctx);
- focusOnSlice(slice);
+ if (slice) {
+ focusOnSlice(slice);
+ }
}
}