trace_processor: migrate args to macro tables
Context: go/perfetto-tp-refactor
Bug: 135177627
Change-Id: I3e99a70a6628cb1444fed1f31e02fd31a76faaca
diff --git a/Android.bp b/Android.bp
index 5ed362b..75fe075 100644
--- a/Android.bp
+++ b/Android.bp
@@ -5726,7 +5726,6 @@
filegroup {
name: "perfetto_src_trace_processor_lib",
srcs: [
- "src/trace_processor/args_table.cc",
"src/trace_processor/filtered_row_index.cc",
"src/trace_processor/gfp_flags.cc",
"src/trace_processor/process_table.cc",
@@ -5830,6 +5829,7 @@
"src/trace_processor/event_tracker.cc",
"src/trace_processor/forwarding_trace_parser.cc",
"src/trace_processor/ftrace_utils.cc",
+ "src/trace_processor/global_args_tracker.cc",
"src/trace_processor/gzip_trace_parser.cc",
"src/trace_processor/heap_profile_tracker.cc",
"src/trace_processor/importers/ftrace/ftrace_module.cc",
@@ -5855,6 +5855,7 @@
"src/trace_processor/trace_sorter.cc",
"src/trace_processor/trace_storage.cc",
"src/trace_processor/track_tracker.cc",
+ "src/trace_processor/variadic.cc",
"src/trace_processor/virtual_destructors.cc",
],
}
@@ -5876,7 +5877,6 @@
filegroup {
name: "perfetto_src_trace_processor_unittests",
srcs: [
- "src/trace_processor/args_table_unittest.cc",
"src/trace_processor/clock_tracker_unittest.cc",
"src/trace_processor/event_tracker_unittest.cc",
"src/trace_processor/filtered_row_index_unittest.cc",
diff --git a/BUILD b/BUILD
index 5303bde..7842996 100644
--- a/BUILD
+++ b/BUILD
@@ -785,8 +785,6 @@
filegroup(
name = "src_trace_processor_lib",
srcs = [
- "src/trace_processor/args_table.cc",
- "src/trace_processor/args_table.h",
"src/trace_processor/filtered_row_index.cc",
"src/trace_processor/filtered_row_index.h",
"src/trace_processor/gfp_flags.cc",
@@ -891,6 +889,8 @@
"src/trace_processor/forwarding_trace_parser.h",
"src/trace_processor/ftrace_utils.cc",
"src/trace_processor/ftrace_utils.h",
+ "src/trace_processor/global_args_tracker.cc",
+ "src/trace_processor/global_args_tracker.h",
"src/trace_processor/gzip_trace_parser.cc",
"src/trace_processor/gzip_trace_parser.h",
"src/trace_processor/heap_profile_tracker.cc",
@@ -954,6 +954,7 @@
"src/trace_processor/trace_storage.h",
"src/trace_processor/track_tracker.cc",
"src/trace_processor/track_tracker.h",
+ "src/trace_processor/variadic.cc",
"src/trace_processor/variadic.h",
"src/trace_processor/virtual_destructors.cc",
],
diff --git a/src/protozero/test/example_proto/test_messages.descriptor.h b/src/protozero/test/example_proto/test_messages.descriptor.h
index 9c2bcfa..f26c058 100644
--- a/src/protozero/test/example_proto/test_messages.descriptor.h
+++ b/src/protozero/test/example_proto/test_messages.descriptor.h
@@ -224,19 +224,19 @@
0x72, 0x42, 0x61, 0x7a, 0x12, 0x16, 0x0a, 0x06, 0x62, 0x61, 0x72, 0x42,
0x61, 0x7a, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x62, 0x61,
0x72, 0x42, 0x61, 0x7a, 0x12, 0x16, 0x0a, 0x06, 0x4d, 0x6f, 0x6f, 0x4d,
- 0x6f, 0x6f, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x6d, 0x6f,
+ 0x6f, 0x6f, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x4d, 0x6f,
0x6f, 0x4d, 0x6f, 0x6f, 0x12, 0x1e, 0x0a, 0x0a, 0x55, 0x52, 0x4c, 0x45,
0x6e, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08,
- 0x52, 0x0a, 0x75, 0x52, 0x4c, 0x45, 0x6e, 0x63, 0x6f, 0x64, 0x65, 0x72,
+ 0x52, 0x0a, 0x55, 0x52, 0x4c, 0x45, 0x6e, 0x63, 0x6f, 0x64, 0x65, 0x72,
0x12, 0x12, 0x0a, 0x04, 0x58, 0x4d, 0x61, 0x70, 0x18, 0x05, 0x20, 0x01,
- 0x28, 0x08, 0x52, 0x04, 0x78, 0x4d, 0x61, 0x70, 0x12, 0x21, 0x0a, 0x0d,
+ 0x28, 0x08, 0x52, 0x04, 0x58, 0x4d, 0x61, 0x70, 0x12, 0x21, 0x0a, 0x0d,
0x55, 0x72, 0x4c, 0x45, 0x5f, 0x6e, 0x63, 0x6f, 0x5f, 0x5f, 0x64, 0x65,
- 0x72, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0a, 0x75, 0x72, 0x4c,
+ 0x72, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0a, 0x55, 0x72, 0x4c,
0x45, 0x4e, 0x63, 0x6f, 0x44, 0x65, 0x72, 0x12, 0x1a, 0x0a, 0x09, 0x5f,
0x5f, 0x62, 0x69, 0x67, 0x42, 0x61, 0x6e, 0x67, 0x18, 0x07, 0x20, 0x01,
- 0x28, 0x08, 0x52, 0x07, 0x62, 0x69, 0x67, 0x42, 0x61, 0x6e, 0x67, 0x12,
+ 0x28, 0x08, 0x52, 0x07, 0x42, 0x69, 0x67, 0x42, 0x61, 0x6e, 0x67, 0x12,
0x0e, 0x0a, 0x02, 0x55, 0x32, 0x18, 0x08, 0x20, 0x01, 0x28, 0x08, 0x52,
- 0x02, 0x75, 0x32, 0x12, 0x1a, 0x0a, 0x09, 0x62, 0x61, 0x6e, 0x67, 0x42,
+ 0x02, 0x55, 0x32, 0x12, 0x1a, 0x0a, 0x09, 0x62, 0x61, 0x6e, 0x67, 0x42,
0x69, 0x67, 0x5f, 0x5f, 0x18, 0x09, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07,
0x62, 0x61, 0x6e, 0x67, 0x42, 0x69, 0x67, 0x22, 0x8f, 0x01, 0x0a, 0x14,
0x50, 0x61, 0x63, 0x6b, 0x65, 0x64, 0x52, 0x65, 0x70, 0x65, 0x61, 0x74,
diff --git a/src/trace_processor/BUILD.gn b/src/trace_processor/BUILD.gn
index a6fd002..1ba92b1 100644
--- a/src/trace_processor/BUILD.gn
+++ b/src/trace_processor/BUILD.gn
@@ -86,6 +86,8 @@
"forwarding_trace_parser.cc",
"forwarding_trace_parser.h",
"ftrace_utils.h",
+ "global_args_tracker.cc",
+ "global_args_tracker.h",
"gzip_trace_parser.cc",
"gzip_trace_parser.h",
"heap_profile_tracker.cc",
@@ -136,6 +138,7 @@
"trace_storage.h",
"track_tracker.cc",
"track_tracker.h",
+ "variadic.cc",
"variadic.h",
"virtual_destructors.cc",
]
@@ -282,8 +285,6 @@
source_set("lib") {
sources = [
- "args_table.cc",
- "args_table.h",
"filtered_row_index.cc",
"filtered_row_index.h",
"gfp_flags.cc",
@@ -368,7 +369,6 @@
perfetto_unittest_source_set("unittests") {
testonly = true
sources = [
- "args_table_unittest.cc",
"clock_tracker_unittest.cc",
"event_tracker_unittest.cc",
"filtered_row_index_unittest.cc",
diff --git a/src/trace_processor/args_table.cc b/src/trace_processor/args_table.cc
deleted file mode 100644
index 64b407c..0000000
--- a/src/trace_processor/args_table.cc
+++ /dev/null
@@ -1,265 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "src/trace_processor/args_table.h"
-
-#include "src/trace_processor/sqlite/sqlite_utils.h"
-
-namespace perfetto {
-namespace trace_processor {
-
-namespace {
-PERFETTO_ALWAYS_INLINE
-bool TreatedAsInteger(Variadic v) {
- return v.type == Variadic::Type::kInt || v.type == Variadic::Type::kBool ||
- v.type == Variadic::Type::kPointer || v.type == Variadic::Type::kUint;
-}
-
-PERFETTO_ALWAYS_INLINE
-bool TreatedAsString(Variadic v) {
- return v.type == Variadic::Type::kString || v.type == Variadic::Type::kJson;
-}
-
-PERFETTO_ALWAYS_INLINE
-int64_t AsInt64(Variadic v) {
- if (v.type == Variadic::Type::kInt)
- return v.int_value;
- if (v.type == Variadic::Type::kBool)
- return static_cast<int64_t>(v.bool_value);
- if (v.type == Variadic::Type::kUint)
- return static_cast<int64_t>(v.uint_value);
- if (v.type == Variadic::Type::kPointer)
- return static_cast<int64_t>(v.pointer_value);
- PERFETTO_FATAL("invalid Variadic type");
-}
-
-PERFETTO_ALWAYS_INLINE
-StringId AsStringId(Variadic v) {
- if (v.type == Variadic::Type::kString)
- return v.string_value;
- if (v.type == Variadic::Type::kJson)
- return v.json_value;
- PERFETTO_FATAL("invalid Variadic type");
-}
-} // namespace
-
-ArgsTable::ArgsTable(sqlite3*, const TraceStorage* storage)
- : storage_(storage) {}
-
-void ArgsTable::RegisterTable(sqlite3* db, const TraceStorage* storage) {
- SqliteTable::Register<ArgsTable>(db, storage, "args");
-}
-
-StorageSchema ArgsTable::CreateStorageSchema() {
- const auto& args = storage_->args();
- return StorageSchema::Builder()
- .AddOrderedNumericColumn("arg_set_id", &args.set_ids())
- .AddStringColumn("flat_key", &args.flat_keys(), &storage_->string_pool())
- .AddStringColumn("key", &args.keys(), &storage_->string_pool())
- .AddColumn<ValueColumn>("int_value", Variadic::Type::kInt, storage_)
- .AddColumn<ValueColumn>("string_value", Variadic::Type::kString, storage_)
- .AddColumn<ValueColumn>("real_value", Variadic::Type::kReal, storage_)
- .Build({"arg_set_id", "key"});
-}
-
-uint32_t ArgsTable::RowCount() {
- return static_cast<uint32_t>(storage_->args().args_count());
-}
-
-int ArgsTable::BestIndex(const QueryConstraints& qc, BestIndexInfo* info) {
- if (HasEqConstraint(qc, "arg_set_id")) {
- info->estimated_cost = 1;
- } else {
- info->estimated_cost = static_cast<uint32_t>(storage_->args().args_count());
- }
- return SQLITE_OK;
-}
-
-ArgsTable::ValueColumn::ValueColumn(std::string col_name,
- Variadic::Type type,
- const TraceStorage* storage)
- : StorageColumn(col_name, false /* hidden */),
- type_(type),
- storage_(storage) {
- PERFETTO_CHECK(type == Variadic::Type::kInt ||
- type == Variadic::Type::kReal ||
- type == Variadic::Type::kString);
-}
-
-void ArgsTable::ValueColumn::ReportResult(sqlite3_context* ctx,
- uint32_t row) const {
- const auto& value = storage_->args().arg_values()[row];
- switch (type_) {
- // Integer column, returns all integer-like variadic values (as an int64_t).
- case Variadic::Type::kInt: {
- if (!TreatedAsInteger(value)) {
- sqlite3_result_null(ctx);
- return;
- }
- sqlite_utils::ReportSqliteResult(ctx, AsInt64(value));
- return;
- }
-
- // Float column, returns only float values.
- case Variadic::Type::kReal: {
- if (value.type != Variadic::Type::kReal) {
- sqlite3_result_null(ctx);
- return;
- }
- sqlite_utils::ReportSqliteResult(ctx, value.real_value);
- return;
- }
-
- // String column, returns string & json variadic values (as a string).
- case Variadic::Type::kString: {
- if (!TreatedAsString(value)) {
- sqlite3_result_null(ctx);
- return;
- }
- const char* str = storage_->GetString(AsStringId(value)).c_str();
- sqlite3_result_text(ctx, str, -1, sqlite_utils::kSqliteStatic);
- return;
- }
-
- case Variadic::Type::kBool:
- case Variadic::Type::kUint:
- case Variadic::Type::kPointer:
- case Variadic::Type::kJson:
- PERFETTO_FATAL("Unexpected column type");
- }
-}
-
-ArgsTable::ValueColumn::Bounds ArgsTable::ValueColumn::BoundFilter(
- int,
- sqlite3_value*) const {
- return Bounds{};
-}
-
-void ArgsTable::ValueColumn::Filter(int op,
- sqlite3_value* value,
- FilteredRowIndex* index) const {
- switch (type_) {
- // Integer column, returns all integer-like variadic values (as an int64_t).
- case Variadic::Type::kInt: {
- bool op_is_null = sqlite_utils::IsOpIsNull(op);
- auto predicate = sqlite_utils::CreateNumericPredicate<int64_t>(op, value);
- index->FilterRows(
- [this, predicate, op_is_null](uint32_t row) PERFETTO_ALWAYS_INLINE {
- const Variadic& arg = storage_->args().arg_values()[row];
- if (!TreatedAsInteger(arg)) {
- return op_is_null;
- }
- return predicate(AsInt64(arg));
- });
- break;
- }
-
- // Float column, returns only float values.
- case Variadic::Type::kReal: {
- bool op_is_null = sqlite_utils::IsOpIsNull(op);
- auto predicate = sqlite_utils::CreateNumericPredicate<double>(op, value);
- index->FilterRows(
- [this, predicate, op_is_null](uint32_t row) PERFETTO_ALWAYS_INLINE {
- const auto& arg = storage_->args().arg_values()[row];
- return arg.type == Variadic::Type::kReal ? predicate(arg.real_value)
- : op_is_null;
- });
- break;
- }
-
- // String column, returns string & json variadic values (as a string).
- case Variadic::Type::kString: {
- auto predicate = sqlite_utils::CreateStringPredicate(op, value);
- index->FilterRows(
- [this, &predicate](uint32_t row) PERFETTO_ALWAYS_INLINE {
- const auto& arg = storage_->args().arg_values()[row];
- if (!TreatedAsString(arg)) {
- return predicate(nullptr);
- }
- return predicate(storage_->GetString(AsStringId(arg)).c_str());
- });
- break;
- }
- case Variadic::Type::kBool:
- case Variadic::Type::kUint:
- case Variadic::Type::kPointer:
- case Variadic::Type::kJson:
- PERFETTO_FATAL("Unexpected column type");
- }
-}
-
-ArgsTable::ValueColumn::Comparator ArgsTable::ValueColumn::Sort(
- const QueryConstraints::OrderBy& ob) const {
- if (ob.desc) {
- return [this](uint32_t f, uint32_t s) { return -CompareRefsAsc(f, s); };
- }
- return [this](uint32_t f, uint32_t s) { return CompareRefsAsc(f, s); };
-}
-
-int ArgsTable::ValueColumn::CompareRefsAsc(uint32_t f, uint32_t s) const {
- const auto& arg_f = storage_->args().arg_values()[f];
- const auto& arg_s = storage_->args().arg_values()[s];
- switch (type_) {
- // Integer column, returns all integer-like variadic values (as an int64_t).
- case Variadic::Type::kInt: {
- if (TreatedAsInteger(arg_f) && TreatedAsInteger(arg_s)) {
- return sqlite_utils::CompareValuesAsc(AsInt64(arg_f), AsInt64(arg_s));
- } else if (TreatedAsInteger(arg_f)) {
- return 1; // second value treated as null
- } else if (TreatedAsInteger(arg_s)) {
- return -1; // first value treated as null
- }
- return 0;
- }
-
- // Float column, returns only float values.
- case Variadic::Type::kReal: {
- if (arg_f.type == Variadic::Type::kReal &&
- arg_s.type == Variadic::Type::kReal) {
- return sqlite_utils::CompareValuesAsc(arg_f.real_value,
- arg_s.real_value);
- } else if (arg_f.type == Variadic::Type::kReal) {
- return 1; // second value treated as null
- } else if (arg_s.type == Variadic::Type::kReal) {
- return -1; // first value treated as null
- }
- return 0;
- }
-
- // String column, returns string & json variadic values (as a string).
- case Variadic::Type::kString: {
- if (TreatedAsString(arg_f) && TreatedAsString(arg_s)) {
- const auto& f_str = storage_->GetString(AsStringId(arg_f));
- const auto& s_str = storage_->GetString(AsStringId(arg_s));
- return sqlite_utils::CompareValuesAsc(f_str, s_str);
- } else if (TreatedAsString(arg_f)) {
- return 1; // second value treated as null
- } else if (TreatedAsString(arg_s)) {
- return -1; // first value treated as null
- }
- return 0;
- }
- case Variadic::Type::kBool:
- case Variadic::Type::kUint:
- case Variadic::Type::kPointer:
- case Variadic::Type::kJson:
- PERFETTO_FATAL("Unexpected column type");
- }
- PERFETTO_FATAL("Never reached"); // for gcc
-}
-
-} // namespace trace_processor
-} // namespace perfetto
diff --git a/src/trace_processor/args_table.h b/src/trace_processor/args_table.h
deleted file mode 100644
index 8243457..0000000
--- a/src/trace_processor/args_table.h
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef SRC_TRACE_PROCESSOR_ARGS_TABLE_H_
-#define SRC_TRACE_PROCESSOR_ARGS_TABLE_H_
-
-#include "src/trace_processor/storage_table.h"
-#include "src/trace_processor/trace_storage.h"
-#include "src/trace_processor/variadic.h"
-
-namespace perfetto {
-namespace trace_processor {
-
-class ArgsTable : public StorageTable {
- public:
- static void RegisterTable(sqlite3* db, const TraceStorage* storage);
-
- ArgsTable(sqlite3*, const TraceStorage*);
-
- // StorageTable implementation.
- StorageSchema CreateStorageSchema() override;
- uint32_t RowCount() override;
- int BestIndex(const QueryConstraints&, BestIndexInfo*) override;
-
- private:
- class ValueColumn final : public StorageColumn {
- public:
- ValueColumn(std::string col_name,
- Variadic::Type type,
- const TraceStorage* storage);
-
- void ReportResult(sqlite3_context* ctx, uint32_t row) const override;
-
- Bounds BoundFilter(int op, sqlite3_value* sqlite_val) const override;
-
- void Filter(int op, sqlite3_value* value, FilteredRowIndex*) const override;
-
- Comparator Sort(const QueryConstraints::OrderBy& ob) const override;
-
- bool HasOrdering() const override { return false; }
-
- SqlValue::Type GetType() const override {
- switch (type_) {
- case Variadic::Type::kInt:
- case Variadic::Type::kUint:
- case Variadic::Type::kPointer:
- case Variadic::Type::kBool:
- return SqlValue::Type::kLong;
- case Variadic::Type::kJson:
- case Variadic::Type::kString:
- return SqlValue::Type::kString;
- case Variadic::Type::kReal:
- return SqlValue::Type::kDouble;
- }
- PERFETTO_FATAL("Not reached"); // For gcc
- }
-
- private:
- int CompareRefsAsc(uint32_t f, uint32_t s) const;
-
- Variadic::Type type_;
- const TraceStorage* storage_ = nullptr;
- };
-
- const TraceStorage* const storage_;
-};
-
-} // namespace trace_processor
-} // namespace perfetto
-
-#endif // SRC_TRACE_PROCESSOR_ARGS_TABLE_H_
diff --git a/src/trace_processor/args_table_unittest.cc b/src/trace_processor/args_table_unittest.cc
deleted file mode 100644
index de6bec7..0000000
--- a/src/trace_processor/args_table_unittest.cc
+++ /dev/null
@@ -1,313 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "src/trace_processor/args_table.h"
-#include "src/trace_processor/sqlite/scoped_db.h"
-#include "src/trace_processor/trace_processor_context.h"
-#include "src/trace_processor/trace_storage.h"
-#include "test/gtest_and_gmock.h"
-
-namespace perfetto {
-namespace trace_processor {
-namespace {
-
-class ArgsTableUnittest : public ::testing::Test {
- public:
- ArgsTableUnittest() {
- sqlite3* db = nullptr;
- PERFETTO_CHECK(sqlite3_initialize() == SQLITE_OK);
- PERFETTO_CHECK(sqlite3_open(":memory:", &db) == SQLITE_OK);
- db_.reset(db);
-
- context_.storage.reset(new TraceStorage());
- ArgsTable::RegisterTable(db_.get(), context_.storage.get());
- }
-
- void PrepareValidStatement(const std::string& sql) {
- int size = static_cast<int>(sql.size());
- sqlite3_stmt* stmt;
- ASSERT_EQ(sqlite3_prepare_v2(*db_, sql.c_str(), size, &stmt, nullptr),
- SQLITE_OK);
- stmt_.reset(stmt);
- }
-
- const char* GetColumnAsText(int colId) {
- return reinterpret_cast<const char*>(sqlite3_column_text(*stmt_, colId));
- }
-
- void AssertArgRowValues(int arg_set_id,
- const char* flat_key,
- const char* key,
- base::Optional<int64_t> int_value,
- base::Optional<const char*> string_value,
- base::Optional<double> real_value);
-
- protected:
- TraceProcessorContext context_;
- ScopedDb db_;
- ScopedStmt stmt_;
-};
-
-// Test helper.
-void ArgsTableUnittest::AssertArgRowValues(
- int arg_set_id,
- const char* flat_key,
- const char* key,
- base::Optional<int64_t> int_value,
- base::Optional<const char*> string_value,
- base::Optional<double> real_value) {
- ASSERT_EQ(sqlite3_column_int(*stmt_, 0), arg_set_id);
- ASSERT_STREQ(GetColumnAsText(1), flat_key);
- ASSERT_STREQ(GetColumnAsText(2), key);
- if (int_value.has_value()) {
- ASSERT_EQ(sqlite3_column_int64(*stmt_, 3), int_value.value());
- } else {
- ASSERT_EQ(sqlite3_column_type(*stmt_, 3), SQLITE_NULL);
- }
- if (string_value.has_value()) {
- ASSERT_STREQ(GetColumnAsText(4), string_value.value());
- } else {
- ASSERT_EQ(sqlite3_column_type(*stmt_, 4), SQLITE_NULL);
- }
- if (real_value.has_value()) {
- ASSERT_DOUBLE_EQ(sqlite3_column_double(*stmt_, 5), real_value.value());
- } else {
- ASSERT_EQ(sqlite3_column_type(*stmt_, 5), SQLITE_NULL);
- }
-}
-
-TEST_F(ArgsTableUnittest, IntValue) {
- static const char kFlatKey[] = "flat_key";
- static const char kKey[] = "key";
- static const int kValue = 123;
-
- TraceStorage::Args::Arg arg;
- arg.flat_key = context_.storage->InternString(kFlatKey);
- arg.key = context_.storage->InternString(kKey);
- arg.value = Variadic::Integer(kValue);
-
- context_.storage->mutable_args()->AddArgSet({arg}, 0, 1);
-
- PrepareValidStatement("SELECT * FROM args");
-
- ASSERT_EQ(sqlite3_step(*stmt_), SQLITE_ROW);
- AssertArgRowValues(1, kFlatKey, kKey, kValue, base::nullopt, base::nullopt);
- ASSERT_EQ(sqlite3_step(*stmt_), SQLITE_DONE);
-}
-
-TEST_F(ArgsTableUnittest, StringValue) {
- static const char kFlatKey[] = "flat_key";
- static const char kKey[] = "key";
- static const char kValue[] = "123";
-
- TraceStorage::Args::Arg arg;
- arg.flat_key = context_.storage->InternString(kFlatKey);
- arg.key = context_.storage->InternString(kKey);
- arg.value = Variadic::String(context_.storage->InternString(kValue));
-
- context_.storage->mutable_args()->AddArgSet({arg}, 0, 1);
-
- PrepareValidStatement("SELECT * FROM args");
-
- ASSERT_EQ(sqlite3_step(*stmt_), SQLITE_ROW);
- AssertArgRowValues(1, kFlatKey, kKey, base::nullopt, kValue, base::nullopt);
- ASSERT_EQ(sqlite3_step(*stmt_), SQLITE_DONE);
-}
-
-TEST_F(ArgsTableUnittest, RealValue) {
- static const char kFlatKey[] = "flat_key";
- static const char kKey[] = "key";
- static const double kValue = 0.123;
-
- TraceStorage::Args::Arg arg;
- arg.flat_key = context_.storage->InternString(kFlatKey);
- arg.key = context_.storage->InternString(kKey);
- arg.value = Variadic::Real(kValue);
-
- context_.storage->mutable_args()->AddArgSet({arg}, 0, 1);
-
- PrepareValidStatement("SELECT * FROM args");
-
- ASSERT_EQ(sqlite3_step(*stmt_), SQLITE_ROW);
- AssertArgRowValues(1, kFlatKey, kKey, base::nullopt, base::nullopt, kValue);
- ASSERT_EQ(sqlite3_step(*stmt_), SQLITE_DONE);
-}
-
-TEST_F(ArgsTableUnittest, BoolValueTreatedAsInt) {
- static const char kFlatKey[] = "flat_key";
- static const char kKey[] = "key";
- static const bool kValue = true;
-
- TraceStorage::Args::Arg arg;
- arg.flat_key = context_.storage->InternString(kFlatKey);
- arg.key = context_.storage->InternString(kKey);
- arg.value = Variadic::Boolean(kValue);
-
- context_.storage->mutable_args()->AddArgSet({arg}, 0, 1);
-
- // Boolean returned in the "int_value" column, and is comparable to an integer
- // literal.
- PrepareValidStatement("SELECT * FROM args WHERE int_value = 1");
- ASSERT_EQ(sqlite3_step(*stmt_), SQLITE_ROW);
- AssertArgRowValues(1, kFlatKey, kKey, kValue, base::nullopt, base::nullopt);
- ASSERT_EQ(sqlite3_step(*stmt_), SQLITE_DONE);
-}
-
-TEST_F(ArgsTableUnittest, PointerValueTreatedAsInt) {
- static const uint64_t kSmallValue = 1ull << 30;
- static const uint64_t kTopBitSetValue = 1ull << 63;
-
- TraceStorage::Args::Arg arg;
- arg.flat_key = context_.storage->InternString("flat_key_small");
- arg.key = context_.storage->InternString("key_small");
- arg.value = Variadic::Pointer(kSmallValue);
-
- TraceStorage::Args::Arg arg2;
- arg2.flat_key = context_.storage->InternString("flat_key_large");
- arg2.key = context_.storage->InternString("key_large");
- arg2.value = Variadic::Pointer(kTopBitSetValue);
-
- context_.storage->mutable_args()->AddArgSet({arg, arg2}, 0, 2);
-
- // Pointer returned in the "int_value" column, as a signed 64 bit. And is
- // comparable to an integer literal.
-
- static const int64_t kExpectedSmallValue = static_cast<int64_t>(kSmallValue);
- PrepareValidStatement(std::string("SELECT * FROM args WHERE int_value = ") +
- std::to_string(kExpectedSmallValue));
- ASSERT_EQ(sqlite3_step(*stmt_), SQLITE_ROW);
- AssertArgRowValues(1, "flat_key_small", "key_small", kExpectedSmallValue,
- base::nullopt, base::nullopt);
- ASSERT_EQ(sqlite3_step(*stmt_), SQLITE_DONE);
-
- static const int64_t kExpectedTopBitSetValue =
- static_cast<int64_t>(kTopBitSetValue); // negative
- PrepareValidStatement(std::string("SELECT * FROM args WHERE int_value = ") +
- std::to_string(kExpectedTopBitSetValue));
- ASSERT_EQ(sqlite3_step(*stmt_), SQLITE_ROW);
- AssertArgRowValues(1, "flat_key_large", "key_large", kExpectedTopBitSetValue,
- base::nullopt, base::nullopt);
- ASSERT_EQ(sqlite3_step(*stmt_), SQLITE_DONE);
-}
-
-TEST_F(ArgsTableUnittest, UintValueTreatedAsInt) {
- static const uint64_t kSmallValue = 1ull << 30;
- static const uint64_t kTopBitSetValue = 1ull << 63;
-
- TraceStorage::Args::Arg arg;
- arg.flat_key = context_.storage->InternString("flat_key_small");
- arg.key = context_.storage->InternString("key_small");
- arg.value = Variadic::UnsignedInteger(kSmallValue);
-
- TraceStorage::Args::Arg arg2;
- arg2.flat_key = context_.storage->InternString("flat_key_large");
- arg2.key = context_.storage->InternString("key_large");
- arg2.value = Variadic::UnsignedInteger(kTopBitSetValue);
-
- context_.storage->mutable_args()->AddArgSet({arg, arg2}, 0, 2);
-
- // Unsigned returned in the "int_value" column, as a signed 64 bit. And is
- // comparable to an integer literal.
-
- static const int64_t kExpectedSmallValue = static_cast<int64_t>(kSmallValue);
- PrepareValidStatement(std::string("SELECT * FROM args WHERE int_value = ") +
- std::to_string(kExpectedSmallValue));
- ASSERT_EQ(sqlite3_step(*stmt_), SQLITE_ROW);
- AssertArgRowValues(1, "flat_key_small", "key_small", kExpectedSmallValue,
- base::nullopt, base::nullopt);
- ASSERT_EQ(sqlite3_step(*stmt_), SQLITE_DONE);
-
- static const int64_t kExpectedTopBitSetValue =
- static_cast<int64_t>(kTopBitSetValue); // negative
- PrepareValidStatement(std::string("SELECT * FROM args WHERE int_value = ") +
- std::to_string(kExpectedTopBitSetValue));
- ASSERT_EQ(sqlite3_step(*stmt_), SQLITE_ROW);
- AssertArgRowValues(1, "flat_key_large", "key_large", kExpectedTopBitSetValue,
- base::nullopt, base::nullopt);
- ASSERT_EQ(sqlite3_step(*stmt_), SQLITE_DONE);
-}
-
-TEST_F(ArgsTableUnittest, IntegerLikeValuesSortByIntRepresentation) {
- static const char kFlatKey[] = "flat_key";
- static const char kKey[] = "key";
-
- TraceStorage::Args::Arg bool_arg_true;
- bool_arg_true.flat_key = context_.storage->InternString(kFlatKey);
- bool_arg_true.key = context_.storage->InternString(kKey);
- bool_arg_true.value = Variadic::Boolean(true);
-
- TraceStorage::Args::Arg bool_arg_false;
- bool_arg_false.flat_key = context_.storage->InternString(kFlatKey);
- bool_arg_false.key = context_.storage->InternString(kKey);
- bool_arg_false.value = Variadic::Boolean(false);
-
- TraceStorage::Args::Arg pointer_arg_42;
- pointer_arg_42.flat_key = context_.storage->InternString(kFlatKey);
- pointer_arg_42.key = context_.storage->InternString(kKey);
- pointer_arg_42.value = Variadic::Pointer(42);
-
- TraceStorage::Args::Arg unsigned_arg_10;
- unsigned_arg_10.flat_key = context_.storage->InternString(kFlatKey);
- unsigned_arg_10.key = context_.storage->InternString(kKey);
- unsigned_arg_10.value = Variadic::UnsignedInteger(10);
-
- // treated as null by the int_value column
- TraceStorage::Args::Arg string_arg;
- string_arg.flat_key = context_.storage->InternString(kFlatKey);
- string_arg.key = context_.storage->InternString(kKey);
- string_arg.value =
- Variadic::String(context_.storage->InternString("string_content"));
-
- context_.storage->mutable_args()->AddArgSet(
- {bool_arg_true, bool_arg_false, pointer_arg_42, unsigned_arg_10,
- string_arg},
- 0, 5);
-
- // Ascending sort by int representations:
- // { null (string), 0 (false), 1 (true), 10, 42 }
- PrepareValidStatement("SELECT * FROM args ORDER BY int_value ASC");
- ASSERT_EQ(sqlite3_step(*stmt_), SQLITE_ROW);
- AssertArgRowValues(1, kFlatKey, kKey, base::nullopt, "string_content",
- base::nullopt);
- ASSERT_EQ(sqlite3_step(*stmt_), SQLITE_ROW);
- AssertArgRowValues(1, kFlatKey, kKey, 0, base::nullopt, base::nullopt);
- ASSERT_EQ(sqlite3_step(*stmt_), SQLITE_ROW);
- AssertArgRowValues(1, kFlatKey, kKey, 1, base::nullopt, base::nullopt);
- ASSERT_EQ(sqlite3_step(*stmt_), SQLITE_ROW);
- AssertArgRowValues(1, kFlatKey, kKey, 10, base::nullopt, base::nullopt);
- ASSERT_EQ(sqlite3_step(*stmt_), SQLITE_ROW);
- AssertArgRowValues(1, kFlatKey, kKey, 42, base::nullopt, base::nullopt);
- ASSERT_EQ(sqlite3_step(*stmt_), SQLITE_DONE);
-
- // Desceding order.
- PrepareValidStatement("SELECT * FROM args ORDER BY int_value DESC");
- ASSERT_EQ(sqlite3_step(*stmt_), SQLITE_ROW);
- AssertArgRowValues(1, kFlatKey, kKey, 42, base::nullopt, base::nullopt);
- ASSERT_EQ(sqlite3_step(*stmt_), SQLITE_ROW);
- AssertArgRowValues(1, kFlatKey, kKey, 10, base::nullopt, base::nullopt);
- ASSERT_EQ(sqlite3_step(*stmt_), SQLITE_ROW);
- AssertArgRowValues(1, kFlatKey, kKey, 1, base::nullopt, base::nullopt);
- ASSERT_EQ(sqlite3_step(*stmt_), SQLITE_ROW);
- AssertArgRowValues(1, kFlatKey, kKey, 0, base::nullopt, base::nullopt);
- ASSERT_EQ(sqlite3_step(*stmt_), SQLITE_ROW);
- AssertArgRowValues(1, kFlatKey, kKey, base::nullopt, "string_content",
- base::nullopt);
- ASSERT_EQ(sqlite3_step(*stmt_), SQLITE_DONE);
-}
-
-} // namespace
-} // namespace trace_processor
-} // namespace perfetto
diff --git a/src/trace_processor/args_tracker.cc b/src/trace_processor/args_tracker.cc
index 4f143c5..678bf57 100644
--- a/src/trace_processor/args_tracker.cc
+++ b/src/trace_processor/args_tracker.cc
@@ -43,7 +43,7 @@
}
void ArgsTracker::Flush() {
- using Arg = TraceStorage::Args::Arg;
+ using Arg = GlobalArgsTracker::Arg;
if (args_.empty())
return;
@@ -69,7 +69,7 @@
}
ArgSetId set_id =
- storage->mutable_args()->AddArgSet(args_, i, next_rid_idx);
+ context_->global_args_tracker->AddArgSet(args_, i, next_rid_idx);
switch (table_id) {
case TableId::kRawEvents:
storage->mutable_raw_events()->set_arg_set_id(row, set_id);
diff --git a/src/trace_processor/args_tracker.h b/src/trace_processor/args_tracker.h
index 90062a8..3eebcb8 100644
--- a/src/trace_processor/args_tracker.h
+++ b/src/trace_processor/args_tracker.h
@@ -17,6 +17,7 @@
#ifndef SRC_TRACE_PROCESSOR_ARGS_TRACKER_H_
#define SRC_TRACE_PROCESSOR_ARGS_TRACKER_H_
+#include "src/trace_processor/global_args_tracker.h"
#include "src/trace_processor/trace_processor_context.h"
#include "src/trace_processor/trace_storage.h"
#include "src/trace_processor/variadic.h"
@@ -67,7 +68,7 @@
virtual void Flush();
private:
- std::vector<TraceStorage::Args::Arg> args_;
+ std::vector<GlobalArgsTracker::Arg> args_;
TraceProcessorContext* const context_;
};
diff --git a/src/trace_processor/db/column.cc b/src/trace_processor/db/column.cc
index fd9f6b2..fedfa7c 100644
--- a/src/trace_processor/db/column.cc
+++ b/src/trace_processor/db/column.cc
@@ -239,6 +239,7 @@
return cmp(sparse_vector<T>().GetNonNull(idx)) >= 0;
});
break;
+ case FilterOp::kGlob:
case FilterOp::kLike:
rm->Intersect(RowMap());
break;
@@ -312,10 +313,11 @@
return v.data() != nullptr && compare::String(v, str_value) >= 0;
});
break;
+ case FilterOp::kGlob:
case FilterOp::kLike:
// TODO(lalitm): either call through to SQLite or reimplement
// like ourselves.
- PERFETTO_DLOG("Ignoring like constraint on string column");
+ PERFETTO_DLOG("Ignoring like/glob constraint on string column");
break;
case FilterOp::kIsNull:
case FilterOp::kIsNotNull:
@@ -372,6 +374,7 @@
return compare::Numeric(idx, id_value) >= 0;
});
break;
+ case FilterOp::kGlob:
case FilterOp::kLike:
rm->Intersect(RowMap());
break;
diff --git a/src/trace_processor/db/column.h b/src/trace_processor/db/column.h
index ee12912..7ce1eeb 100644
--- a/src/trace_processor/db/column.h
+++ b/src/trace_processor/db/column.h
@@ -41,6 +41,7 @@
kIsNull,
kIsNotNull,
kLike,
+ kGlob,
};
// Represents a constraint on a column.
@@ -451,6 +452,7 @@
rm->Intersect(RowMap(beg, row_map().size()));
return true;
}
+ case FilterOp::kGlob:
case FilterOp::kNe:
case FilterOp::kIsNull:
case FilterOp::kIsNotNull:
diff --git a/src/trace_processor/event_tracker_unittest.cc b/src/trace_processor/event_tracker_unittest.cc
index 4fadf41..75abbaa 100644
--- a/src/trace_processor/event_tracker_unittest.cc
+++ b/src/trace_processor/event_tracker_unittest.cc
@@ -35,6 +35,7 @@
public:
EventTrackerTest() {
context.storage.reset(new TraceStorage());
+ context.global_args_tracker.reset(new GlobalArgsTracker(&context));
context.args_tracker.reset(new ArgsTracker(&context));
context.process_tracker.reset(new ProcessTracker(&context));
context.event_tracker.reset(new EventTracker(&context));
diff --git a/src/trace_processor/export_json.cc b/src/trace_processor/export_json.cc
index 4aa62b9..54d3ffc 100644
--- a/src/trace_processor/export_json.cc
+++ b/src/trace_processor/export_json.cc
@@ -329,16 +329,18 @@
nan_value_(Json::StaticString("NaN")),
inf_value_(Json::StaticString("Infinity")),
neg_inf_value_(Json::StaticString("-Infinity")) {
- const TraceStorage::Args& args = storage->args();
- if (args.args_count() == 0) {
+ const auto& arg_table = storage->arg_table();
+ uint32_t count = arg_table.row_count();
+ if (count == 0) {
args_sets_.resize(1, empty_value_);
return;
}
- args_sets_.resize(args.set_ids().back() + 1, empty_value_);
- for (size_t i = 0; i < args.args_count(); ++i) {
- ArgSetId set_id = args.set_ids()[i];
- const char* key = GetNonNullString(storage_, args.keys()[i]);
- Variadic value = args.arg_values()[i];
+ args_sets_.resize(arg_table.arg_set_id()[count - 1] + 1, empty_value_);
+
+ for (uint32_t i = 0; i < count; ++i) {
+ ArgSetId set_id = arg_table.arg_set_id()[i];
+ const char* key = GetNonNullString(storage_, arg_table.key()[i]);
+ Variadic value = storage_->GetArgValue(i);
AppendArg(set_id, key, VariadicToJson(value));
}
PostprocessArgs();
diff --git a/src/trace_processor/export_json_unittest.cc b/src/trace_processor/export_json_unittest.cc
index 7cac7cd..58b03fb 100644
--- a/src/trace_processor/export_json_unittest.cc
+++ b/src/trace_processor/export_json_unittest.cc
@@ -65,6 +65,7 @@
class ExportJsonTest : public ::testing::Test {
public:
ExportJsonTest() {
+ context_.global_args_tracker.reset(new GlobalArgsTracker(&context_));
context_.args_tracker.reset(new ArgsTracker(&context_));
context_.storage.reset(new TraceStorage());
context_.track_tracker.reset(new TrackTracker(&context_));
@@ -415,11 +416,11 @@
base::StringView("task.posted_from.file_name"));
StringId arg_value_id =
context_.storage->InternString(base::StringView(kSrc));
- TraceStorage::Args::Arg arg;
+ GlobalArgsTracker::Arg arg;
arg.flat_key = arg_key_id;
arg.key = arg_key_id;
arg.value = Variadic::String(arg_value_id);
- ArgSetId args = context_.storage->mutable_args()->AddArgSet({arg}, 0, 1);
+ ArgSetId args = context_.global_args_tracker->AddArgSet({arg}, 0, 1);
context_.storage->mutable_slice_table()->mutable_arg_set_id()->Set(0, args);
base::TempFile temp_file = base::TempFile::Create();
@@ -512,16 +513,15 @@
base::StringView("debug.draw_duration_ms[0]"));
StringId arg_key1_id = context_.storage->InternString(
base::StringView("debug.draw_duration_ms[1]"));
- TraceStorage::Args::Arg arg0;
+ GlobalArgsTracker::Arg arg0;
arg0.flat_key = arg_flat_key_id;
arg0.key = arg_key0_id;
arg0.value = Variadic::Real(kValues[0]);
- TraceStorage::Args::Arg arg1;
+ GlobalArgsTracker::Arg arg1;
arg1.flat_key = arg_flat_key_id;
arg1.key = arg_key1_id;
arg1.value = Variadic::Real(kValues[1]);
- ArgSetId args =
- context_.storage->mutable_args()->AddArgSet({arg0, arg1}, 0, 2);
+ ArgSetId args = context_.global_args_tracker->AddArgSet({arg0, arg1}, 0, 2);
context_.storage->mutable_slice_table()->mutable_arg_set_id()->Set(0, args);
base::TempFile temp_file = base::TempFile::Create();
@@ -560,16 +560,15 @@
context_.storage->InternString(base::StringView("arg0"));
StringId arg_key1_id =
context_.storage->InternString(base::StringView("arg1"));
- TraceStorage::Args::Arg arg0;
+ GlobalArgsTracker::Arg arg0;
arg0.flat_key = arg_key0_id;
arg0.key = arg_key0_id;
arg0.value = Variadic::Pointer(kValue0);
- TraceStorage::Args::Arg arg1;
+ GlobalArgsTracker::Arg arg1;
arg1.flat_key = arg_key1_id;
arg1.key = arg_key1_id;
arg1.value = Variadic::Pointer(kValue1);
- ArgSetId args =
- context_.storage->mutable_args()->AddArgSet({arg0, arg1}, 0, 2);
+ ArgSetId args = context_.global_args_tracker->AddArgSet({arg0, arg1}, 0, 2);
context_.storage->mutable_slice_table()->mutable_arg_set_id()->Set(0, args);
base::TempFile temp_file = base::TempFile::Create();
@@ -608,16 +607,15 @@
context_.storage->InternString(base::StringView("a[0].b"));
StringId arg_key1_id =
context_.storage->InternString(base::StringView("a[1].b"));
- TraceStorage::Args::Arg arg0;
+ GlobalArgsTracker::Arg arg0;
arg0.flat_key = arg_flat_key_id;
arg0.key = arg_key0_id;
arg0.value = Variadic::Integer(kValues[0]);
- TraceStorage::Args::Arg arg1;
+ GlobalArgsTracker::Arg arg1;
arg1.flat_key = arg_flat_key_id;
arg1.key = arg_key1_id;
arg1.value = Variadic::Integer(kValues[1]);
- ArgSetId args =
- context_.storage->mutable_args()->AddArgSet({arg0, arg1}, 0, 2);
+ ArgSetId args = context_.global_args_tracker->AddArgSet({arg0, arg1}, 0, 2);
context_.storage->mutable_slice_table()->mutable_arg_set_id()->Set(0, args);
base::TempFile temp_file = base::TempFile::Create();
@@ -657,16 +655,15 @@
context_.storage->InternString(base::StringView("a[0][0]"));
StringId arg_key1_id =
context_.storage->InternString(base::StringView("a[0][1]"));
- TraceStorage::Args::Arg arg0;
+ GlobalArgsTracker::Arg arg0;
arg0.flat_key = arg_flat_key_id;
arg0.key = arg_key0_id;
arg0.value = Variadic::Integer(kValues[0]);
- TraceStorage::Args::Arg arg1;
+ GlobalArgsTracker::Arg arg1;
arg1.flat_key = arg_flat_key_id;
arg1.key = arg_key1_id;
arg1.value = Variadic::Integer(kValues[1]);
- ArgSetId args =
- context_.storage->mutable_args()->AddArgSet({arg0, arg1}, 0, 2);
+ ArgSetId args = context_.global_args_tracker->AddArgSet({arg0, arg1}, 0, 2);
context_.storage->mutable_slice_table()->mutable_arg_set_id()->Set(0, args);
base::TempFile temp_file = base::TempFile::Create();
@@ -703,11 +700,11 @@
StringId arg_key_id = context_.storage->InternString(base::StringView("a"));
StringId arg_value_id =
context_.storage->InternString(base::StringView("{\"b\":123}"));
- TraceStorage::Args::Arg arg;
+ GlobalArgsTracker::Arg arg;
arg.flat_key = arg_key_id;
arg.key = arg_key_id;
arg.value = Variadic::Json(arg_value_id);
- ArgSetId args = context_.storage->mutable_args()->AddArgSet({arg}, 0, 1);
+ ArgSetId args = context_.global_args_tracker->AddArgSet({arg}, 0, 1);
context_.storage->mutable_slice_table()->mutable_arg_set_id()->Set(0, args);
base::TempFile temp_file = base::TempFile::Create();
@@ -813,11 +810,11 @@
{kTimestamp, kDuration, track.value, cat_id, name_id, 0, 0, 0});
StringId arg_key_id =
context_.storage->InternString(base::StringView(kArgName));
- TraceStorage::Args::Arg arg;
+ GlobalArgsTracker::Arg arg;
arg.flat_key = arg_key_id;
arg.key = arg_key_id;
arg.value = Variadic::Integer(kArgValue);
- ArgSetId args = context_.storage->mutable_args()->AddArgSet({arg}, 0, 1);
+ ArgSetId args = context_.global_args_tracker->AddArgSet({arg}, 0, 1);
context_.storage->mutable_slice_table()->mutable_arg_set_id()->Set(0, args);
// Child event with same timestamps as first one.
@@ -1002,11 +999,11 @@
{kTimestamp, 0, track.value, cat_id, name_id, 0, 0, 0});
StringId arg_key_id =
context_.storage->InternString(base::StringView("arg_name"));
- TraceStorage::Args::Arg arg;
+ GlobalArgsTracker::Arg arg;
arg.flat_key = arg_key_id;
arg.key = arg_key_id;
arg.value = Variadic::Integer(kArgValue);
- ArgSetId args = context_.storage->mutable_args()->AddArgSet({arg}, 0, 1);
+ ArgSetId args = context_.global_args_tracker->AddArgSet({arg}, 0, 1);
context_.storage->mutable_slice_table()->mutable_arg_set_id()->Set(0, args);
base::TempFile temp_file = base::TempFile::Create();
diff --git a/src/trace_processor/global_args_tracker.cc b/src/trace_processor/global_args_tracker.cc
new file mode 100644
index 0000000..9966108
--- /dev/null
+++ b/src/trace_processor/global_args_tracker.cc
@@ -0,0 +1,26 @@
+/*
+ * 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/global_args_tracker.h"
+
+namespace perfetto {
+namespace trace_processor {
+
+GlobalArgsTracker::GlobalArgsTracker(TraceProcessorContext* context)
+ : context_(context) {}
+
+} // namespace trace_processor
+} // namespace perfetto
diff --git a/src/trace_processor/global_args_tracker.h b/src/trace_processor/global_args_tracker.h
new file mode 100644
index 0000000..92784e1
--- /dev/null
+++ b/src/trace_processor/global_args_tracker.h
@@ -0,0 +1,141 @@
+/*
+ * 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.
+ */
+
+#ifndef SRC_TRACE_PROCESSOR_GLOBAL_ARGS_TRACKER_H_
+#define SRC_TRACE_PROCESSOR_GLOBAL_ARGS_TRACKER_H_
+
+#include "src/trace_processor/trace_processor_context.h"
+#include "src/trace_processor/trace_storage.h"
+#include "src/trace_processor/variadic.h"
+
+namespace perfetto {
+namespace trace_processor {
+
+// Interns args into the storage from all ArgsTrackers across trace processor.
+// Note: most users will want to use ArgsTracker to push args to the strorage
+// and not this class. This class is really intended for ArgsTracker to use for
+// that purpose.
+class GlobalArgsTracker {
+ public:
+ struct Arg {
+ StringId flat_key = 0;
+ StringId key = 0;
+ Variadic value = Variadic::Integer(0);
+
+ TableId table;
+ uint32_t row;
+ };
+
+ struct ArgHasher {
+ uint64_t operator()(const Arg& arg) const noexcept {
+ base::Hash hash;
+ hash.Update(arg.key);
+ // We don't hash arg.flat_key because it's a subsequence of arg.key.
+ switch (arg.value.type) {
+ case Variadic::Type::kInt:
+ hash.Update(arg.value.int_value);
+ break;
+ case Variadic::Type::kUint:
+ hash.Update(arg.value.uint_value);
+ break;
+ case Variadic::Type::kString:
+ hash.Update(arg.value.string_value);
+ break;
+ case Variadic::Type::kReal:
+ hash.Update(arg.value.real_value);
+ break;
+ case Variadic::Type::kPointer:
+ hash.Update(arg.value.pointer_value);
+ break;
+ case Variadic::Type::kBool:
+ hash.Update(arg.value.bool_value);
+ break;
+ case Variadic::Type::kJson:
+ hash.Update(arg.value.json_value);
+ break;
+ }
+ return hash.digest();
+ }
+ };
+
+ GlobalArgsTracker(TraceProcessorContext* context);
+
+ ArgSetId AddArgSet(const std::vector<Arg>& args,
+ uint32_t begin,
+ uint32_t end) {
+ base::Hash hash;
+ for (uint32_t i = begin; i < end; i++) {
+ hash.Update(ArgHasher()(args[i]));
+ }
+
+ auto* arg_table = context_->storage->mutable_arg_table();
+
+ ArgSetHash digest = hash.digest();
+ auto it = arg_row_for_hash_.find(digest);
+ if (it != arg_row_for_hash_.end())
+ return arg_table->arg_set_id()[it->second];
+
+ // The +1 ensures that nothing has an id == kInvalidArgSetId == 0.
+ ArgSetId id = static_cast<uint32_t>(arg_row_for_hash_.size()) + 1;
+ arg_row_for_hash_.emplace(digest, arg_table->row_count());
+ for (uint32_t i = begin; i < end; i++) {
+ const auto& arg = args[i];
+
+ tables::ArgTable::Row row;
+ row.arg_set_id = id;
+ row.flat_key = arg.flat_key;
+ row.key = arg.key;
+ switch (arg.value.type) {
+ case Variadic::Type::kInt:
+ row.int_value = arg.value.int_value;
+ break;
+ case Variadic::Type::kUint:
+ row.int_value = static_cast<int64_t>(arg.value.uint_value);
+ break;
+ case Variadic::Type::kString:
+ row.string_value = arg.value.string_value;
+ break;
+ case Variadic::Type::kReal:
+ row.real_value = arg.value.real_value;
+ break;
+ case Variadic::Type::kPointer:
+ row.int_value = static_cast<int64_t>(arg.value.pointer_value);
+ break;
+ case Variadic::Type::kBool:
+ row.int_value = arg.value.bool_value;
+ break;
+ case Variadic::Type::kJson:
+ row.string_value = arg.value.json_value;
+ break;
+ }
+ row.value_type = context_->storage->GetIdForVariadicType(arg.value.type);
+ arg_table->Insert(row);
+ }
+ return id;
+ }
+
+ private:
+ using ArgSetHash = uint64_t;
+
+ std::unordered_map<ArgSetHash, uint32_t> arg_row_for_hash_;
+
+ TraceProcessorContext* context_;
+};
+
+} // namespace trace_processor
+} // namespace perfetto
+
+#endif // SRC_TRACE_PROCESSOR_GLOBAL_ARGS_TRACKER_H_
diff --git a/src/trace_processor/importers/proto/args_table_utils_unittest.cc b/src/trace_processor/importers/proto/args_table_utils_unittest.cc
index 4cc03e9..d5e3eb1 100644
--- a/src/trace_processor/importers/proto/args_table_utils_unittest.cc
+++ b/src/trace_processor/importers/proto/args_table_utils_unittest.cc
@@ -44,24 +44,22 @@
ArgsTableUtilsTest() {
context_.storage.reset(new TraceStorage);
storage_ = context_.storage.get();
+ context_.global_args_tracker.reset(new GlobalArgsTracker(&context_));
context_.args_tracker.reset(new ArgsTracker(&context_));
sequence_state_.reset(new PacketSequenceState(&context_));
}
bool HasArg(ArgSetId set_id, const base::StringView& key, Variadic value) {
- const auto& args = storage_->args();
+ const auto& args = storage_->arg_table();
auto key_id = storage_->string_pool().GetId(key);
EXPECT_TRUE(key_id);
- auto rows =
- std::equal_range(args.set_ids().begin(), args.set_ids().end(), set_id);
+
+ RowMap rm = args.FilterToRowMap({args.arg_set_id().eq(set_id)});
bool found = false;
- for (; rows.first != rows.second; rows.first++) {
- size_t index = static_cast<size_t>(
- std::distance(args.set_ids().begin(), rows.first));
- if (args.keys()[index] == key_id) {
- EXPECT_EQ(args.flat_keys()[index], key_id);
- if (args.flat_keys()[index] == key_id &&
- args.arg_values()[index] == value) {
+ for (auto it = rm.IterateRows(); it; it.Next()) {
+ if (args.key()[it.row()] == key_id) {
+ EXPECT_EQ(args.flat_key()[it.row()], key_id);
+ if (storage_->GetArgValue(it.row()) == value) {
found = true;
break;
}
diff --git a/src/trace_processor/importers/proto/proto_trace_parser_unittest.cc b/src/trace_processor/importers/proto/proto_trace_parser_unittest.cc
index f90418d..d6daa73 100644
--- a/src/trace_processor/importers/proto/proto_trace_parser_unittest.cc
+++ b/src/trace_processor/importers/proto/proto_trace_parser_unittest.cc
@@ -218,6 +218,7 @@
storage_ = new NiceMock<MockTraceStorage>();
context_.storage.reset(storage_);
context_.track_tracker.reset(new TrackTracker(&context_));
+ context_.global_args_tracker.reset(new GlobalArgsTracker(&context_));
context_.args_tracker.reset(new ArgsTracker(&context_));
context_.metadata_tracker.reset(new MetadataTracker(&context_));
event_ = new MockEventTracker(&context_);
@@ -260,22 +261,19 @@
}
bool HasArg(ArgSetId set_id, StringId key_id, Variadic value) {
- const auto& args = storage_->args();
- auto rows =
- std::equal_range(args.set_ids().begin(), args.set_ids().end(), set_id);
- for (; rows.first != rows.second; rows.first++) {
- size_t index = static_cast<size_t>(
- std::distance(args.set_ids().begin(), rows.first));
- if (args.keys()[index] == key_id) {
- EXPECT_EQ(args.flat_keys()[index], key_id);
- EXPECT_EQ(args.arg_values()[index], value);
- if (args.flat_keys()[index] == key_id &&
- args.arg_values()[index] == value) {
- return true;
+ const auto& args = storage_->arg_table();
+ RowMap rm = args.FilterToRowMap({args.arg_set_id().eq(set_id)});
+ bool found = false;
+ for (auto it = rm.IterateRows(); it; it.Next()) {
+ if (args.key()[it.row()] == key_id) {
+ EXPECT_EQ(args.flat_key()[it.row()], key_id);
+ if (storage_->GetArgValue(it.row()) == value) {
+ found = true;
+ break;
}
}
}
- return false;
+ return found;
}
protected:
@@ -350,18 +348,16 @@
const auto& raw = context_.storage->raw_events();
ASSERT_EQ(raw.raw_event_count(), 2u);
- const auto& args = context_.storage->args();
- ASSERT_EQ(args.args_count(), 6u);
- ASSERT_EQ(args.arg_values()[0].int_value, 123);
- ASSERT_STREQ(
- context_.storage->GetString(args.arg_values()[1].string_value).c_str(),
- task_newtask);
- ASSERT_EQ(args.arg_values()[2].int_value, 12);
- ASSERT_EQ(args.arg_values()[3].int_value, 15);
- ASSERT_EQ(args.arg_values()[4].int_value, 20);
- ASSERT_STREQ(
- context_.storage->GetString(args.arg_values()[5].string_value).c_str(),
- buf_value);
+ const auto& args = context_.storage->arg_table();
+ ASSERT_EQ(args.row_count(), 6u);
+ ASSERT_EQ(args.int_value()[0], 123);
+ ASSERT_STREQ(context_.storage->GetString(args.string_value()[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(context_.storage->GetString(args.string_value()[5]).c_str(),
+ buf_value);
// TODO(taylori): Add test ftrace event with all field types
// and test here.
@@ -409,17 +405,15 @@
auto set_id = raw.arg_set_ids().back();
- const auto& args = storage_->args();
- auto id_it =
- std::equal_range(args.set_ids().begin(), args.set_ids().end(), set_id);
+ const auto& args = storage_->arg_table();
+ RowMap rm = args.FilterToRowMap({args.arg_set_id().eq(set_id)});
// Ignore string calls as they are handled by checking InternString calls
// above.
- auto it = id_it.first;
- auto row = static_cast<size_t>(std::distance(args.set_ids().begin(), it));
- ASSERT_EQ(args.arg_values()[++row].int_value, -2);
- ASSERT_EQ(args.arg_values()[++row].int_value, 3);
+ auto row = rm.Get(0);
+ ASSERT_EQ(args.int_value()[++row], -2);
+ ASSERT_EQ(args.int_value()[++row], 3);
}
TEST_F(ProtoTraceParserTest, LoadMultipleEvents) {
@@ -2148,7 +2142,7 @@
EXPECT_EQ(raw_events.utids()[0], 1u);
EXPECT_EQ(raw_events.arg_set_ids()[0], 1u);
- EXPECT_GE(storage_->args().args_count(), 13u);
+ EXPECT_GE(storage_->arg_table().row_count(), 13u);
EXPECT_TRUE(HasArg(1u, storage_->InternString("legacy_event.category"),
Variadic::String(1u)));
@@ -2282,7 +2276,7 @@
storage_->InternString("chrome_event.metadata"));
EXPECT_EQ(raw_events.arg_set_ids()[0], 1u);
- EXPECT_EQ(storage_->args().args_count(), 2u);
+ EXPECT_EQ(storage_->arg_table().row_count(), 2u);
EXPECT_TRUE(HasArg(1u, storage_->InternString(kStringName),
Variadic::String(storage_->InternString(kStringValue))));
EXPECT_TRUE(HasArg(1u, storage_->InternString(kIntName),
@@ -2316,7 +2310,7 @@
storage_->InternString("chrome_event.legacy_system_trace"));
EXPECT_EQ(raw_events.arg_set_ids()[0], 1u);
- EXPECT_EQ(storage_->args().args_count(), 1u);
+ EXPECT_EQ(storage_->arg_table().row_count(), 1u);
EXPECT_TRUE(HasArg(1u, storage_->InternString("data"),
Variadic::String(storage_->InternString(kFullData))));
}
@@ -2347,7 +2341,7 @@
storage_->InternString("chrome_event.legacy_user_trace"));
EXPECT_EQ(raw_events.arg_set_ids()[0], 1u);
- EXPECT_EQ(storage_->args().args_count(), 1u);
+ EXPECT_EQ(storage_->arg_table().row_count(), 1u);
EXPECT_TRUE(
HasArg(1u, storage_->InternString("data"),
Variadic::String(storage_->InternString(kUserTraceEvent))));
@@ -2430,7 +2424,7 @@
// The relevant arg sets have the info about the packages. To simplify test
// structure, make an assumption that metadata storage is filled in in the
// FIFO order of seen packages.
- const auto& args = context_.storage->args();
+ const auto& args = context_.storage->arg_table();
const auto& metadata = context_.storage->metadata_table();
Table package_list = metadata.Filter(
@@ -2443,10 +2437,10 @@
// helper to look up arg values
auto find_arg = [&args, this](ArgSetId set_id, const char* arg_name) {
- for (size_t i = 0; i < args.set_ids().size(); i++) {
- if (args.set_ids()[i] == set_id &&
- args.keys()[i] == storage_->InternString(arg_name))
- return args.arg_values()[i];
+ for (uint32_t i = 0; i < args.row_count(); i++) {
+ if (args.arg_set_id()[i] == set_id &&
+ args.key()[i] == storage_->InternString(arg_name))
+ return storage_->GetArgValue(i);
}
PERFETTO_FATAL("Didn't find expected argument");
};
diff --git a/src/trace_processor/process_tracker_unittest.cc b/src/trace_processor/process_tracker_unittest.cc
index 802ba42..6b6000e 100644
--- a/src/trace_processor/process_tracker_unittest.cc
+++ b/src/trace_processor/process_tracker_unittest.cc
@@ -34,6 +34,7 @@
public:
ProcessTrackerTest() {
context.storage.reset(new TraceStorage());
+ context.global_args_tracker.reset(new GlobalArgsTracker(&context));
context.args_tracker.reset(new ArgsTracker(&context));
context.process_tracker.reset(new ProcessTracker(&context));
context.event_tracker.reset(new EventTracker(&context));
diff --git a/src/trace_processor/raw_table.cc b/src/trace_processor/raw_table.cc
index ac8127f..f082695 100644
--- a/src/trace_processor/raw_table.cc
+++ b/src/trace_processor/raw_table.cc
@@ -121,12 +121,16 @@
void RawTable::FormatSystraceArgs(NullTermStringView event_name,
ArgSetId arg_set_id,
base::StringWriter* writer) {
- const auto& set_ids = storage_->args().set_ids();
- auto lb = std::lower_bound(set_ids.begin(), set_ids.end(), arg_set_id);
- auto ub = std::find(lb, set_ids.end(), arg_set_id + 1);
+ const auto& set_ids = storage_->arg_table().arg_set_id();
- auto start_row = static_cast<uint32_t>(std::distance(set_ids.begin(), lb));
- auto end_row = static_cast<uint32_t>(std::distance(set_ids.begin(), ub));
+ // TODO(lalitm): this code is quite hacky for performance reasons. We assume
+ // that the row map is a contiguous range (which is always the case
+ // because arg_set_ids are contiguous by definition). We also assume that
+ // the proto field order is also the order of insertion (which happens to
+ // be true but proabably shouldn't be relied on).
+ RowMap rm = storage_->arg_table().FilterToRowMap({set_ids.eq(arg_set_id)});
+
+ uint32_t start_row = rm.Get(0);
using ValueWriter = std::function<void(const Variadic&)>;
auto write_value = [this, writer](const Variadic& value) {
switch (value.type) {
@@ -159,24 +163,22 @@
};
auto write_value_at_index = [this, start_row](uint32_t arg_idx,
ValueWriter value_fn) {
- value_fn(storage_->args().arg_values()[start_row + arg_idx]);
+ value_fn(storage_->GetArgValue(start_row + arg_idx));
};
auto write_arg = [this, writer, start_row](uint32_t arg_idx,
ValueWriter value_fn) {
uint32_t arg_row = start_row + arg_idx;
- const auto& args = storage_->args();
- const auto& key = storage_->GetString(args.keys()[arg_row]);
+ const auto& args = storage_->arg_table();
+ const auto& key = storage_->GetString(args.key()[arg_row]);
+ auto value = storage_->GetArgValue(arg_row);
writer->AppendChar(' ');
writer->AppendString(key.c_str(), key.size());
writer->AppendChar('=');
- if (key == "gfp_flags" &&
- ParseGfpFlags(args.arg_values()[arg_row], writer)) {
+ if (key == "gfp_flags" && ParseGfpFlags(value, writer))
return;
- }
-
- value_fn(args.arg_values()[arg_row]);
+ value_fn(value);
};
if (event_name == "sched_switch") {
@@ -291,9 +293,8 @@
} else if (event_name == "print") {
// 'ip' may be the first field or it may be dropped. We only care
// about the 'buf' field which will always appear last.
- uint32_t arg_row = end_row - 1;
- const auto& args = storage_->args();
- const auto& value = args.arg_values()[arg_row];
+ uint32_t arg_row = rm.Get(rm.size() - 1);
+ const auto& value = storage_->GetArgValue(arg_row);
const auto& str = storage_->GetString(value.string_value);
// If the last character is a newline in a print, just drop it.
auto chars_to_print = !str.empty() && str.c_str()[str.size() - 1] == '\n'
@@ -365,9 +366,8 @@
return;
}
- uint32_t arg = 0;
- for (auto it = lb; it != ub; it++) {
- write_arg(arg++, write_value);
+ for (auto it = rm.IterateRows(); it; it.Next()) {
+ write_arg(it.index(), write_value);
}
}
diff --git a/src/trace_processor/sched_slice_table_unittest.cc b/src/trace_processor/sched_slice_table_unittest.cc
index f9131ae..7e624d0 100644
--- a/src/trace_processor/sched_slice_table_unittest.cc
+++ b/src/trace_processor/sched_slice_table_unittest.cc
@@ -41,6 +41,7 @@
db_.reset(db);
context_.storage.reset(new TraceStorage());
+ context_.global_args_tracker.reset(new GlobalArgsTracker(&context_));
context_.args_tracker.reset(new ArgsTracker(&context_));
context_.process_tracker.reset(new ProcessTracker(&context_));
context_.event_tracker.reset(new EventTracker(&context_));
diff --git a/src/trace_processor/slice_tracker_unittest.cc b/src/trace_processor/slice_tracker_unittest.cc
index a38709e..fc74b01 100644
--- a/src/trace_processor/slice_tracker_unittest.cc
+++ b/src/trace_processor/slice_tracker_unittest.cc
@@ -73,6 +73,7 @@
TEST(SliceTrackerTest, OneSliceWithArgs) {
TraceProcessorContext context;
context.storage.reset(new TraceStorage());
+ context.global_args_tracker.reset(new GlobalArgsTracker(&context));
SliceTracker tracker(&context);
constexpr TrackId track{22u};
@@ -97,15 +98,15 @@
EXPECT_EQ(slices.depth()[0], 0u);
auto set_id = slices.arg_set_id()[0];
- auto args = context.storage->args();
- EXPECT_EQ(args.set_ids()[0], set_id);
- EXPECT_EQ(args.flat_keys()[0], 1u);
- EXPECT_EQ(args.keys()[0], 2u);
- EXPECT_EQ(args.arg_values()[0], Variadic::Integer(10));
- EXPECT_EQ(args.set_ids()[1], set_id);
- EXPECT_EQ(args.flat_keys()[1], 3u);
- EXPECT_EQ(args.keys()[1], 4u);
- EXPECT_EQ(args.arg_values()[1], Variadic::Integer(20));
+ const auto& args = context.storage->arg_table();
+ EXPECT_EQ(args.arg_set_id()[0], set_id);
+ EXPECT_EQ(args.flat_key()[0], 1u);
+ EXPECT_EQ(args.key()[0], 2u);
+ EXPECT_EQ(args.int_value()[0], 10);
+ EXPECT_EQ(args.arg_set_id()[1], set_id);
+ EXPECT_EQ(args.flat_key()[1], 3u);
+ EXPECT_EQ(args.key()[1], 4u);
+ EXPECT_EQ(args.int_value()[1], 20);
}
TEST(SliceTrackerTest, TwoSliceDetailed) {
diff --git a/src/trace_processor/sqlite/db_sqlite_table.cc b/src/trace_processor/sqlite/db_sqlite_table.cc
index 65ed66e..09c113d 100644
--- a/src/trace_processor/sqlite/db_sqlite_table.cc
+++ b/src/trace_processor/sqlite/db_sqlite_table.cc
@@ -45,6 +45,8 @@
return FilterOp::kIsNotNull;
case SQLITE_INDEX_CONSTRAINT_LIKE:
return FilterOp::kLike;
+ case SQLITE_INDEX_CONSTRAINT_GLOB:
+ return FilterOp::kGlob;
default:
PERFETTO_FATAL("Currently unsupported constraint");
}
diff --git a/src/trace_processor/tables/metadata_tables.h b/src/trace_processor/tables/metadata_tables.h
index 9a2095d..6e4e883 100644
--- a/src/trace_processor/tables/metadata_tables.h
+++ b/src/trace_processor/tables/metadata_tables.h
@@ -23,6 +23,19 @@
namespace trace_processor {
namespace tables {
+#define PERFETTO_TP_ARG_TABLE_DEF(NAME, PARENT, C) \
+ NAME(ArgTable, "args") \
+ PERFETTO_TP_ROOT_TABLE(PARENT, C) \
+ C(uint32_t, arg_set_id, Column::Flag::kSorted) \
+ C(StringPool::Id, flat_key) \
+ C(StringPool::Id, key) \
+ C(base::Optional<int64_t>, int_value) \
+ C(base::Optional<StringPool::Id>, string_value) \
+ C(base::Optional<double>, real_value) \
+ C(StringPool::Id, value_type)
+
+PERFETTO_TP_TABLE(PERFETTO_TP_ARG_TABLE_DEF);
+
#define PERFETTO_TP_METADATA_TABLE_DEF(NAME, PARENT, C) \
NAME(MetadataTable, "metadata") \
PERFETTO_TP_ROOT_TABLE(PARENT, C) \
diff --git a/src/trace_processor/thread_table_unittest.cc b/src/trace_processor/thread_table_unittest.cc
index 03c6647..fda86e1 100644
--- a/src/trace_processor/thread_table_unittest.cc
+++ b/src/trace_processor/thread_table_unittest.cc
@@ -38,6 +38,7 @@
db_.reset(db);
context_.storage.reset(new TraceStorage());
+ context_.global_args_tracker.reset(new GlobalArgsTracker(&context_));
context_.args_tracker.reset(new ArgsTracker(&context_));
context_.process_tracker.reset(new ProcessTracker(&context_));
context_.event_tracker.reset(new EventTracker(&context_));
diff --git a/src/trace_processor/trace_processor_context.cc b/src/trace_processor/trace_processor_context.cc
index 52ec6de..bb5b6a0 100644
--- a/src/trace_processor/trace_processor_context.cc
+++ b/src/trace_processor/trace_processor_context.cc
@@ -20,6 +20,7 @@
#include "src/trace_processor/chunked_trace_reader.h"
#include "src/trace_processor/clock_tracker.h"
#include "src/trace_processor/event_tracker.h"
+#include "src/trace_processor/global_args_tracker.h"
#include "src/trace_processor/heap_profile_tracker.h"
#include "src/trace_processor/importers/ftrace/ftrace_module.h"
#include "src/trace_processor/importers/json/json_trace_parser.h"
diff --git a/src/trace_processor/trace_processor_context.h b/src/trace_processor/trace_processor_context.h
index 10e6eb4..310005f 100644
--- a/src/trace_processor/trace_processor_context.h
+++ b/src/trace_processor/trace_processor_context.h
@@ -33,6 +33,7 @@
class ClockTracker;
class EventTracker;
class FtraceModule;
+class GlobalArgsTracker;
class HeapGraphTracker;
class HeapProfileTracker;
class MetadataTracker;
@@ -52,7 +53,6 @@
std::unique_ptr<TraceStorage> storage;
std::unique_ptr<TrackTracker> track_tracker;
- std::unique_ptr<ArgsTracker> args_tracker;
std::unique_ptr<SliceTracker> slice_tracker;
std::unique_ptr<ProcessTracker> process_tracker;
std::unique_ptr<EventTracker> event_tracker;
@@ -63,6 +63,11 @@
std::unique_ptr<HeapProfileTracker> heap_profile_tracker;
std::unique_ptr<MetadataTracker> metadata_tracker;
+ // Keep the global tracker before the args tracker as we access the global
+ // tracker in the destructor of the args tracker.
+ std::unique_ptr<GlobalArgsTracker> global_args_tracker;
+ std::unique_ptr<ArgsTracker> args_tracker;
+
// These fields are stored as pointers to Destructible objects rather than
// their actual type (a subclass of Destructible), as the concrete subclass
// type is only available in the storage_full target. To access these fields,
diff --git a/src/trace_processor/trace_processor_impl.cc b/src/trace_processor/trace_processor_impl.cc
index c843df7..6863de2 100644
--- a/src/trace_processor/trace_processor_impl.cc
+++ b/src/trace_processor/trace_processor_impl.cc
@@ -23,7 +23,6 @@
#include "perfetto/base/time.h"
#include "perfetto/ext/base/string_splitter.h"
#include "perfetto/ext/base/string_utils.h"
-#include "src/trace_processor/args_table.h"
#include "src/trace_processor/importers/ftrace/sched_event_tracker.h"
#include "src/trace_processor/process_table.h"
#include "src/trace_processor/raw_table.h"
@@ -369,7 +368,6 @@
SetupMetrics(this, *db_, &sql_metrics_);
- ArgsTable::RegisterTable(*db_, context_.storage.get());
ProcessTable::RegisterTable(*db_, context_.storage.get());
SchedSliceTable::RegisterTable(*db_, context_.storage.get());
SqlStatsTable::RegisterTable(*db_, context_.storage.get());
@@ -382,6 +380,9 @@
// New style db-backed tables.
const TraceStorage* storage = context_.storage.get();
+ DbSqliteTable::RegisterTable(*db_, &storage->arg_table(),
+ storage->arg_table().table_name());
+
DbSqliteTable::RegisterTable(*db_, &storage->slice_table(),
storage->slice_table().table_name());
DbSqliteTable::RegisterTable(*db_, &storage->instant_table(),
diff --git a/src/trace_processor/trace_processor_storage_impl.cc b/src/trace_processor/trace_processor_storage_impl.cc
index 0ad11ee..a8d8dee 100644
--- a/src/trace_processor/trace_processor_storage_impl.cc
+++ b/src/trace_processor/trace_processor_storage_impl.cc
@@ -48,6 +48,7 @@
context_.clock_tracker.reset(new ClockTracker(&context_));
context_.heap_profile_tracker.reset(new HeapProfileTracker(&context_));
context_.metadata_tracker.reset(new MetadataTracker(&context_));
+ context_.global_args_tracker.reset(new GlobalArgsTracker(&context_));
context_.modules.emplace_back(new FtraceModule());
// Ftrace module is special, because it has one extra method for parsing
diff --git a/src/trace_processor/trace_storage.cc b/src/trace_processor/trace_storage.cc
index 4d96c7e..aa25f59 100644
--- a/src/trace_processor/trace_storage.cc
+++ b/src/trace_processor/trace_storage.cc
@@ -82,6 +82,10 @@
// Upid/utid 0 is reserved for idle processes/threads.
unique_processes_.emplace_back(0);
unique_threads_.emplace_back(0);
+
+ for (uint32_t i = 0; i < variadic_type_ids_.size(); ++i) {
+ variadic_type_ids_[i] = InternString(Variadic::kTypeNames[i]);
+ }
}
TraceStorage::~TraceStorage() {}
diff --git a/src/trace_processor/trace_storage.h b/src/trace_processor/trace_storage.h
index 83a609b..39f021f 100644
--- a/src/trace_processor/trace_storage.h
+++ b/src/trace_processor/trace_storage.h
@@ -137,96 +137,6 @@
uint32_t tid = 0;
};
- // Generic key value storage which can be referenced by other tables.
- class Args {
- public:
- struct Arg {
- StringId flat_key = 0;
- StringId key = 0;
- Variadic value = Variadic::Integer(0);
-
- TableId table;
- uint32_t row;
- };
-
- struct ArgHasher {
- uint64_t operator()(const Arg& arg) const noexcept {
- base::Hash hash;
- hash.Update(arg.key);
- // We don't hash arg.flat_key because it's a subsequence of arg.key.
- switch (arg.value.type) {
- case Variadic::Type::kInt:
- hash.Update(arg.value.int_value);
- break;
- case Variadic::Type::kUint:
- hash.Update(arg.value.uint_value);
- break;
- case Variadic::Type::kString:
- hash.Update(arg.value.string_value);
- break;
- case Variadic::Type::kReal:
- hash.Update(arg.value.real_value);
- break;
- case Variadic::Type::kPointer:
- hash.Update(arg.value.pointer_value);
- break;
- case Variadic::Type::kBool:
- hash.Update(arg.value.bool_value);
- break;
- case Variadic::Type::kJson:
- hash.Update(arg.value.json_value);
- break;
- }
- return hash.digest();
- }
- };
-
- const std::deque<ArgSetId>& set_ids() const { return set_ids_; }
- const std::deque<StringId>& flat_keys() const { return flat_keys_; }
- const std::deque<StringId>& keys() const { return keys_; }
- const std::deque<Variadic>& arg_values() const { return arg_values_; }
- uint32_t args_count() const {
- return static_cast<uint32_t>(set_ids_.size());
- }
-
- ArgSetId AddArgSet(const std::vector<Arg>& args,
- uint32_t begin,
- uint32_t end) {
- base::Hash hash;
- for (uint32_t i = begin; i < end; i++) {
- hash.Update(ArgHasher()(args[i]));
- }
-
- ArgSetHash digest = hash.digest();
- auto it = arg_row_for_hash_.find(digest);
- if (it != arg_row_for_hash_.end()) {
- return set_ids_[it->second];
- }
-
- // The +1 ensures that nothing has an id == kInvalidArgSetId == 0.
- ArgSetId id = static_cast<uint32_t>(arg_row_for_hash_.size()) + 1;
- arg_row_for_hash_.emplace(digest, args_count());
- for (uint32_t i = begin; i < end; i++) {
- const auto& arg = args[i];
- set_ids_.emplace_back(id);
- flat_keys_.emplace_back(arg.flat_key);
- keys_.emplace_back(arg.key);
- arg_values_.emplace_back(arg.value);
- }
- return id;
- }
-
- private:
- using ArgSetHash = uint64_t;
-
- std::deque<ArgSetId> set_ids_;
- std::deque<StringId> flat_keys_;
- std::deque<StringId> keys_;
- std::deque<Variadic> arg_values_;
-
- std::unordered_map<ArgSetHash, uint32_t> arg_row_for_hash_;
- };
-
class Slices {
public:
inline size_t AddSlice(uint32_t cpu,
@@ -704,8 +614,8 @@
}
tables::MetadataTable* mutable_metadata_table() { return &metadata_table_; }
- const Args& args() const { return args_; }
- Args* mutable_args() { return &args_; }
+ const tables::ArgTable& arg_table() const { return arg_table_; }
+ tables::ArgTable* mutable_arg_table() { return &arg_table_; }
const RawEvents& raw_events() const { return raw_events_; }
RawEvents* mutable_raw_events() { return &raw_events_; }
@@ -828,6 +738,43 @@
stack_profile_frame_index_[pair].emplace_back(row);
}
+ Variadic GetArgValue(uint32_t row) const {
+ Variadic v;
+ v.type = *GetVariadicTypeForId(arg_table_.value_type()[row]);
+
+ // 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]);
+ break;
+ case Variadic::Type::kInt:
+ v.int_value = *arg_table_.int_value()[row];
+ break;
+ case Variadic::Type::kUint:
+ v.uint_value = static_cast<uint64_t>(*arg_table_.int_value()[row]);
+ break;
+ case Variadic::Type::kString:
+ v.string_value = arg_table_.string_value()[row];
+ break;
+ case Variadic::Type::kPointer:
+ v.pointer_value = static_cast<uint64_t>(*arg_table_.int_value()[row]);
+ break;
+ case Variadic::Type::kReal:
+ v.real_value = *arg_table_.real_value()[row];
+ break;
+ case Variadic::Type::kJson:
+ v.json_value = arg_table_.string_value()[row];
+ break;
+ }
+ return v;
+ }
+
+ StringId GetIdForVariadicType(Variadic::Type type) const {
+ return variadic_type_ids_[type];
+ }
+
private:
using StringHash = uint64_t;
@@ -837,6 +784,16 @@
TraceStorage(TraceStorage&&) = delete;
TraceStorage& operator=(TraceStorage&&) = delete;
+ base::Optional<Variadic::Type> GetVariadicTypeForId(StringId id) const {
+ auto it =
+ std::find(variadic_type_ids_.begin(), variadic_type_ids_.end(), id);
+ if (it == variadic_type_ids_.end())
+ return base::nullopt;
+
+ int64_t idx = std::distance(variadic_type_ids_.begin(), it);
+ return static_cast<Variadic::Type>(idx);
+ }
+
// TODO(lalitm): remove this when we find a better home for this.
using MappingKey = std::pair<StringId /* name */, StringId /* build id */>;
std::map<MappingKey, std::vector<int64_t>> stack_profile_mapping_index_;
@@ -881,7 +838,7 @@
Slices slices_;
// Args for all other tables.
- Args args_;
+ tables::ArgTable arg_table_{&string_pool_, nullptr};
// One entry for each UniquePid, with UniquePid as the index.
// Never hold on to pointers to Process, as vector resize will
@@ -942,6 +899,10 @@
tables::VulkanMemoryAllocationsTable vulkan_memory_allocations_table_{
&string_pool_, nullptr};
+
+ // The below array allow us to map between enums and their string
+ // representations.
+ std::array<StringId, Variadic::kMaxType + 1> variadic_type_ids_;
};
} // namespace trace_processor
diff --git a/src/trace_processor/variadic.cc b/src/trace_processor/variadic.cc
new file mode 100644
index 0000000..edfde74
--- /dev/null
+++ b/src/trace_processor/variadic.cc
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "src/trace_processor/variadic.h"
+
+namespace perfetto {
+namespace trace_processor {
+
+constexpr const char* Variadic::kTypeNames[];
+
+} // namespace trace_processor
+} // namespace perfetto
diff --git a/src/trace_processor/variadic.h b/src/trace_processor/variadic.h
index 0444721..58aa935 100644
--- a/src/trace_processor/variadic.h
+++ b/src/trace_processor/variadic.h
@@ -24,7 +24,19 @@
// Variadic type representing value of different possible types.
struct Variadic {
- enum Type { kInt, kUint, kString, kReal, kPointer, kBool, kJson };
+ enum Type : size_t {
+ kInt,
+ kUint,
+ kString,
+ kReal,
+ kPointer,
+ kBool,
+ kJson,
+ kMaxType = kJson,
+ };
+
+ static constexpr const char* const kTypeNames[] = {
+ "int", "uint", "string", "real", "pointer", "bool", "json"};
static Variadic Integer(int64_t int_value) {
Variadic variadic;