tp: migrate all table functions to use Python based tables
This CL removes the last usage of macros for actual tables from the
codebase. This allows removing all table macro code in a follow-up CL:
we need to keep around the slice table for C++ views but this too will
be migrated once C++ views themselves have been migrated.
Change-Id: I28a5a834bfaa380fa2ba478fce9fdfba43c92d54
diff --git a/Android.bp b/Android.bp
index 9734c15..2077923 100644
--- a/Android.bp
+++ b/Android.bp
@@ -2246,6 +2246,7 @@
"perfetto_src_trace_processor_metrics_gen_cc_all_webview_metrics_descriptor",
"perfetto_src_trace_processor_metrics_gen_cc_metrics_descriptor",
"perfetto_src_trace_processor_metrics_sql_gen_amalgamated_sql_metrics",
+ "perfetto_src_trace_processor_prelude_table_functions_tables",
"perfetto_src_trace_processor_prelude_tables_views_tables_views",
"perfetto_src_trace_processor_stdlib_gen_amalgamated_stdlib",
"perfetto_src_trace_processor_tables_tables_python",
@@ -10069,6 +10070,43 @@
],
}
+// GN: //src/trace_processor/prelude/table_functions:tables
+genrule {
+ name: "perfetto_src_trace_processor_prelude_table_functions_tables",
+ srcs: [
+ "src/trace_processor/prelude/table_functions/tables.py",
+ ],
+ tools: [
+ "perfetto_src_trace_processor_prelude_table_functions_tables_binary",
+ ],
+ cmd: "$(location perfetto_src_trace_processor_prelude_table_functions_tables_binary) --gen-dir=$(genDir) --relative-input-dir=external/perfetto --inputs $(in)",
+ out: [
+ "src/trace_processor/prelude/table_functions/tables_py.h",
+ ],
+}
+
+// GN: //src/trace_processor/prelude/table_functions:tables
+python_binary_host {
+ name: "perfetto_src_trace_processor_prelude_table_functions_tables_binary",
+ srcs: [
+ "python/generators/trace_processor_table/public.py",
+ "python/generators/trace_processor_table/serialize.py",
+ "python/generators/trace_processor_table/util.py",
+ "src/trace_processor/prelude/table_functions/tables.py",
+ "src/trace_processor/tables/android_tables.py",
+ "src/trace_processor/tables/counter_tables.py",
+ "src/trace_processor/tables/flow_tables.py",
+ "src/trace_processor/tables/memory_tables.py",
+ "src/trace_processor/tables/metadata_tables.py",
+ "src/trace_processor/tables/profiler_tables.py",
+ "src/trace_processor/tables/slice_tables.py",
+ "src/trace_processor/tables/trace_proto_tables.py",
+ "src/trace_processor/tables/track_tables.py",
+ "tools/gen_tp_table_headers.py",
+ ],
+ main: "tools/gen_tp_table_headers.py",
+}
+
// GN: //src/trace_processor/prelude/table_functions:unittests
filegroup {
name: "perfetto_src_trace_processor_prelude_table_functions_unittests",
@@ -10234,7 +10272,7 @@
tools: [
"perfetto_src_trace_processor_tables_py_tables_unittest_binary",
],
- cmd: "$(location perfetto_src_trace_processor_tables_py_tables_unittest_binary) --gen-dir=$(genDir) --inputs $(in) --outputs $(out)",
+ cmd: "$(location perfetto_src_trace_processor_tables_py_tables_unittest_binary) --gen-dir=$(genDir) --relative-input-dir=external/perfetto --inputs $(in)",
out: [
"src/trace_processor/tables/py_tables_unittest_py.h",
],
@@ -10278,7 +10316,7 @@
tools: [
"perfetto_src_trace_processor_tables_tables_python_binary",
],
- cmd: "$(location perfetto_src_trace_processor_tables_tables_python_binary) --gen-dir=$(genDir) --inputs $(in) --outputs $(out)",
+ cmd: "$(location perfetto_src_trace_processor_tables_tables_python_binary) --gen-dir=$(genDir) --relative-input-dir=external/perfetto --inputs $(in)",
out: [
"src/trace_processor/tables/android_tables_py.h",
"src/trace_processor/tables/counter_tables_py.h",
@@ -12048,6 +12086,7 @@
"perfetto_src_trace_processor_metrics_gen_cc_all_webview_metrics_descriptor",
"perfetto_src_trace_processor_metrics_gen_cc_metrics_descriptor",
"perfetto_src_trace_processor_metrics_sql_gen_amalgamated_sql_metrics",
+ "perfetto_src_trace_processor_prelude_table_functions_tables",
"perfetto_src_trace_processor_prelude_tables_views_tables_views",
"perfetto_src_trace_processor_stdlib_gen_amalgamated_stdlib",
"perfetto_src_trace_processor_tables_py_tables_unittest",
@@ -12565,6 +12604,7 @@
"perfetto_src_trace_processor_metrics_gen_cc_all_webview_metrics_descriptor",
"perfetto_src_trace_processor_metrics_gen_cc_metrics_descriptor",
"perfetto_src_trace_processor_metrics_sql_gen_amalgamated_sql_metrics",
+ "perfetto_src_trace_processor_prelude_table_functions_tables",
"perfetto_src_trace_processor_prelude_tables_views_tables_views",
"perfetto_src_trace_processor_stdlib_gen_amalgamated_stdlib",
"perfetto_src_trace_processor_tables_tables_python",
@@ -12789,6 +12829,7 @@
"perfetto_src_trace_processor_metrics_gen_cc_all_webview_metrics_descriptor",
"perfetto_src_trace_processor_metrics_gen_cc_metrics_descriptor",
"perfetto_src_trace_processor_metrics_sql_gen_amalgamated_sql_metrics",
+ "perfetto_src_trace_processor_prelude_table_functions_tables",
"perfetto_src_trace_processor_prelude_tables_views_tables_views",
"perfetto_src_trace_processor_stdlib_gen_amalgamated_stdlib",
"perfetto_src_trace_processor_tables_tables_python",
diff --git a/BUILD b/BUILD
index c30c684..6481aa5 100644
--- a/BUILD
+++ b/BUILD
@@ -1849,6 +1849,20 @@
],
)
+# GN target: //src/trace_processor/prelude/table_functions:tables
+perfetto_cc_tp_tables(
+ name = "src_trace_processor_prelude_table_functions_tables",
+ srcs = [
+ "src/trace_processor/prelude/table_functions/tables.py",
+ ],
+ deps = [
+ ":src_trace_processor_tables_tables_python",
+ ],
+ outs = [
+ "src/trace_processor/prelude/table_functions/tables_py.h",
+ ],
+)
+
# GN target: //src/trace_processor/prelude/tables_views:sources
perfetto_filegroup(
name = "src_trace_processor_prelude_tables_views_sources",
@@ -2023,11 +2037,8 @@
perfetto_filegroup(
name = "src_trace_processor_tables_tables",
srcs = [
- "src/trace_processor/tables/counter_tables.h",
- "src/trace_processor/tables/flow_tables.h",
"src/trace_processor/tables/macros.h",
"src/trace_processor/tables/macros_internal.h",
- "src/trace_processor/tables/profiler_tables.h",
"src/trace_processor/tables/slice_tables.h",
"src/trace_processor/tables/table_destructors.cc",
],
@@ -4736,6 +4747,7 @@
":src_trace_processor_prelude_functions_functions",
":src_trace_processor_prelude_operators_operators",
":src_trace_processor_prelude_table_functions_table_functions",
+ ":src_trace_processor_prelude_table_functions_tables",
":src_trace_processor_sorter_sorter",
":src_trace_processor_sqlite_sqlite",
":src_trace_processor_sqlite_sqlite_minimal",
@@ -4889,6 +4901,7 @@
":src_trace_processor_prelude_functions_functions",
":src_trace_processor_prelude_operators_operators",
":src_trace_processor_prelude_table_functions_table_functions",
+ ":src_trace_processor_prelude_table_functions_tables",
":src_trace_processor_rpc_httpd",
":src_trace_processor_rpc_rpc",
":src_trace_processor_sorter_sorter",
@@ -5101,6 +5114,7 @@
":src_trace_processor_prelude_functions_functions",
":src_trace_processor_prelude_operators_operators",
":src_trace_processor_prelude_table_functions_table_functions",
+ ":src_trace_processor_prelude_table_functions_tables",
":src_trace_processor_sorter_sorter",
":src_trace_processor_sqlite_sqlite",
":src_trace_processor_sqlite_sqlite_minimal",
diff --git a/bazel/rules.bzl b/bazel/rules.bzl
index 4021c58..7a626c1 100644
--- a/bazel/rules.bzl
+++ b/bazel/rules.bzl
@@ -308,7 +308,7 @@
**kwargs,
)
-def perfetto_cc_tp_tables(name, srcs, outs, **kwargs):
+def perfetto_cc_tp_tables(name, srcs, outs, deps = [], **kwargs):
if PERFETTO_CONFIG.root[:2] != "//":
fail("Expected PERFETTO_CONFIG.root to start with //")
@@ -317,12 +317,21 @@
else:
python_path = PERFETTO_CONFIG.root + "/python"
- perfetto_py_binary(
- name = name + "_tool",
+ perfetto_py_library(
+ name = name + "_lib",
deps = [
python_path + ":trace_processor_table_generator",
],
- srcs = srcs + [
+ srcs = srcs,
+ )
+
+ perfetto_py_binary(
+ name = name + "_tool",
+ deps = [
+ ":" + name + "_lib",
+ python_path + ":trace_processor_table_generator",
+ ] + [d + "_lib" for d in deps],
+ srcs = [
"tools/gen_tp_table_headers.py",
],
main = "tools/gen_tp_table_headers.py",
@@ -332,7 +341,6 @@
cmd = ["$(location " + name + "_tool)"]
cmd += ["--gen-dir", "$(RULEDIR)"]
cmd += ["--inputs", "$(SRCS)"]
- cmd += ["--outputs", "$(OUTS)"]
if PERFETTO_CONFIG.root != "//":
cmd += ["--header-prefix", PERFETTO_CONFIG.root[2:]]
diff --git a/gn/perfetto_tp_tables.gni b/gn/perfetto_tp_tables.gni
index da8cfae..0a9d902 100644
--- a/gn/perfetto_tp_tables.gni
+++ b/gn/perfetto_tp_tables.gni
@@ -17,6 +17,10 @@
template("perfetto_tp_tables") {
config_name = target_name + "_config"
action_name = target_name
+ relative_args = [
+ "--relative-input-dir",
+ rebase_path(perfetto_root_path, root_build_dir),
+ ]
config(config_name) {
include_dirs = [ root_gen_dir ]
@@ -32,6 +36,9 @@
}
deps = [ "$perfetto_root_path/python:trace_processor_table_generator" ]
+ if (defined(invoker.deps)) {
+ deps += invoker.deps
+ }
public_configs = [ ":$config_name" ]
gen_args = [
@@ -39,8 +46,7 @@
rebase_path("$root_gen_dir", root_build_dir),
]
input_args = [ "--inputs" ] + rebase_path(invoker.sources, root_build_dir)
- output_args = [ "--outputs" ] + rebase_path(outputs, root_build_dir)
- args = gen_args + input_args + output_args
+ args = gen_args + input_args + relative_args
metadata = {
perfetto_action_type_for_generator = [ "tp_tables" ]
@@ -56,7 +62,7 @@
deps = [ "$perfetto_root_path/python:trace_processor_table_generator" ]
outputs = [ "$target_gen_dir/$docs_name.json" ]
args = [ "--out" ] + rebase_path(outputs, root_build_dir) +
- rebase_path(invoker.sources, root_build_dir)
+ rebase_path(invoker.sources, root_build_dir) + relative_args
}
}
}
diff --git a/python/generators/trace_processor_table/public.py b/python/generators/trace_processor_table/public.py
index abd0aec..c8bdb0b 100644
--- a/python/generators/trace_processor_table/public.py
+++ b/python/generators/trace_processor_table/public.py
@@ -119,6 +119,8 @@
Representation of of a C++ table.
Attributes:
+ python_module: Path to the Python module this table is defined in. Always
+ pass __file__.
class_name: Name of the C++ table class.
sql_name: Name of the table in SQL.
columns: The columns in this table.
@@ -129,6 +131,7 @@
specified table.
wrapping_sql_view: See |WrappingSqlView|.
"""
+ python_module: str
class_name: str
sql_name: str
columns: List[Column]
diff --git a/python/generators/trace_processor_table/serialize.py b/python/generators/trace_processor_table/serialize.py
index 2636733..875b3de 100644
--- a/python/generators/trace_processor_table/serialize.py
+++ b/python/generators/trace_processor_table/serialize.py
@@ -19,6 +19,8 @@
from python.generators.trace_processor_table.public import ColumnFlag
from python.generators.trace_processor_table.util import ParsedTable
from python.generators.trace_processor_table.util import ParsedColumn
+from python.generators.trace_processor_table.util import parse_type
+from python.generators.trace_processor_table.util import typed_column_type
class ColumnSerializer:
@@ -30,8 +32,9 @@
self.col = self.parsed_col.column
self.name = self.col.name
self.flags = self.col.flags
- self.typed_column_type = table.typed_column_type(self.parsed_col)
- self.cpp_type = table.parse_type(self.col.type).cpp_type_with_optionality()
+ self.typed_column_type = typed_column_type(table.table, self.parsed_col)
+ self.cpp_type = parse_type(table.table,
+ self.col.type).cpp_type_with_optionality()
self.is_implicit_id = self.parsed_col.is_implicit_id
self.is_implicit_type = self.parsed_col.is_implicit_type
@@ -180,11 +183,11 @@
if self.is_implicit_id or self.is_implicit_type:
return None
return f'''
- schema.columns.emplace_back(Table::Schema::Column{{
- "{self.name}", ColumnType::{self.name}::SqlValueType(), false,
- {str(ColumnFlag.SORTED in self.flags).lower()},
- {str(ColumnFlag.HIDDEN in self.flags).lower()},
- {str(ColumnFlag.SET_ID in self.flags).lower()}}});
+ schema.columns.emplace_back(Table::Schema::Column{{
+ "{self.name}", ColumnType::{self.name}::SqlValueType(), false,
+ {str(ColumnFlag.SORTED in self.flags).lower()},
+ {str(ColumnFlag.HIDDEN in self.flags).lower()},
+ {str(ColumnFlag.SET_ID in self.flags).lower()}}});
'''
def row_eq(self) -> Optional[str]:
@@ -192,6 +195,42 @@
return None
return f'ColumnType::{self.name}::Equals({self.name}, other.{self.name})'
+ def extend_parent_param(self) -> Optional[str]:
+ if self.is_implicit_id or self.is_implicit_type:
+ return None
+ if self.is_ancestor:
+ return None
+ return f'ColumnStorage<ColumnType::{self.name}::stored_type> {self.name}'
+
+ def extend_parent_param_arg(self) -> Optional[str]:
+ if self.is_implicit_id or self.is_implicit_type:
+ return None
+ if self.is_ancestor:
+ return None
+ return f'std::move({self.name})'
+
+ def static_assert_flags(self) -> Optional[str]:
+ if self.is_implicit_id or self.is_implicit_type:
+ return None
+ if self.is_ancestor:
+ return None
+ return f'''
+ static_assert(
+ Column::IsFlagsAndTypeValid<ColumnType::{self.name}::stored_type>(
+ ColumnFlag::{self.name}),
+ "Column type and flag combination is not valid");
+ '''
+
+ def extend_nullable_vector(self) -> Optional[str]:
+ if self.is_implicit_id or self.is_implicit_type:
+ return None
+ if self.is_ancestor:
+ return None
+ return f'''
+ PERFETTO_DCHECK({self.name}.size() == parent_overlay.size());
+ {self.name}_ = std::move({self.name});
+ '''
+
class TableSerializer(object):
"""Functions for seralizing a single Table into C++."""
@@ -317,6 +356,7 @@
explicit {self.table_name}(StringPool* pool{parent_param})
: macros_internal::MacroTable(pool, {parent_arg}),
{parent_init}{storage_init} {{
+ {self.foreach_col(ColumnSerializer.static_assert_flags)}
{olay}
{col_init}
}}
@@ -389,6 +429,60 @@
}};
'''
+ def extend(self) -> str:
+ if not self.table.parent:
+ return ''
+ params = self.foreach_col(
+ ColumnSerializer.extend_parent_param, delimiter='\n, ')
+ args = self.foreach_col(
+ ColumnSerializer.extend_parent_param_arg, delimiter=', ')
+ delim = ',' if params else ''
+ return f'''
+ static std::unique_ptr<Table> ExtendParent(
+ const {self.parent_class_name}& parent{delim}
+ {params}) {{
+ return std::unique_ptr<Table>(new {self.table_name}(
+ parent.string_pool(), parent, RowMap(0, parent.row_count()){delim}
+ {args}));
+ }}
+
+ static std::unique_ptr<Table> SelectAndExtendParent(
+ const {self.parent_class_name}& parent,
+ std::vector<{self.parent_class_name}::RowNumber> parent_overlay{delim}
+ {params}) {{
+ std::vector<uint32_t> prs_untyped(parent_overlay.size());
+ 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}(
+ parent.string_pool(), parent, RowMap(std::move(prs_untyped)){delim}
+ {args}));
+ }}
+ '''
+
+ def extend_constructor(self) -> str:
+ if not self.table.parent:
+ return ''
+ params = self.foreach_col(
+ ColumnSerializer.extend_parent_param, delimiter='\n, ')
+ if params:
+ olay = 'uint32_t olay_idx = static_cast<uint32_t>(overlays_.size()) - 1;'
+ else:
+ olay = ''
+ return f'''
+ {self.table_name}(StringPool* pool,
+ const {self.parent_class_name}& parent,
+ const RowMap& parent_overlay{',' if params else ''}
+ {params})
+ : macros_internal::MacroTable(pool, parent, parent_overlay) {{
+ {self.foreach_col(ColumnSerializer.static_assert_flags)}
+ {self.foreach_col(ColumnSerializer.extend_nullable_vector)}
+
+ {olay}
+ {self.foreach_col(ColumnSerializer.column_init)}
+ }}
+ '''
+
def serialize(self) -> str:
return f'''
class {self.table_name} : public macros_internal::MacroTable {{
@@ -488,11 +582,14 @@
RowNumber(row_number)}};
}}
+ {self.extend().strip()}
+
{self.foreach_col(ColumnSerializer.accessor)}
{self.foreach_col(ColumnSerializer.mutable_accessor)}
private:
+ {self.extend_constructor().strip()}
{self.parent_field().strip()}
{self.foreach_col(ColumnSerializer.storage)}
}};
diff --git a/python/generators/trace_processor_table/util.py b/python/generators/trace_processor_table/util.py
index 015f02c..1f0dc0c 100644
--- a/python/generators/trace_processor_table/util.py
+++ b/python/generators/trace_processor_table/util.py
@@ -14,7 +14,8 @@
import dataclasses
from dataclasses import dataclass
-import runpy
+import importlib
+import sys
from typing import Dict
from typing import List
from typing import Set
@@ -92,71 +93,78 @@
table: Table
columns: List[ParsedColumn]
- input_path: str
- def parse_type(self, col_type: CppColumnType) -> ParsedType:
- """Parses a CppColumnType into its constiuent parts."""
- if isinstance(col_type, CppInt64):
- return ParsedType('int64_t')
- if isinstance(col_type, CppInt32):
- return ParsedType('int32_t')
- if isinstance(col_type, CppUint32):
- return ParsedType('uint32_t')
- if isinstance(col_type, CppDouble):
- return ParsedType('double')
- if isinstance(col_type, CppString):
- return ParsedType('StringPool::Id')
+def parse_type_with_cols(table: Table, cols: List[Column],
+ col_type: CppColumnType) -> ParsedType:
+ """Parses a CppColumnType into its constiuent parts."""
- if isinstance(col_type, Alias):
- col = next(c for c in self.columns
- if c.column.name == col_type.underlying_column)
- return ParsedType(
- self.parse_type(col.column.type).cpp_type,
- is_alias=True,
- alias_underlying_name=col.column.name)
+ if isinstance(col_type, CppInt64):
+ return ParsedType('int64_t')
+ if isinstance(col_type, CppInt32):
+ return ParsedType('int32_t')
+ if isinstance(col_type, CppUint32):
+ return ParsedType('uint32_t')
+ if isinstance(col_type, CppDouble):
+ return ParsedType('double')
+ if isinstance(col_type, CppString):
+ return ParsedType('StringPool::Id')
- if isinstance(col_type, CppTableId):
- return ParsedType(
- f'{col_type.table.class_name}::Id', id_table=col_type.table)
+ if isinstance(col_type, Alias):
+ col = next(c for c in cols if c.name == col_type.underlying_column)
+ return ParsedType(
+ parse_type(table, col.type).cpp_type,
+ is_alias=True,
+ alias_underlying_name=col.name)
- if isinstance(col_type, CppSelfTableId):
- return ParsedType(
- f'{self.table.class_name}::Id', is_self_id=True, id_table=self.table)
+ if isinstance(col_type, CppTableId):
+ return ParsedType(
+ f'{col_type.table.class_name}::Id', id_table=col_type.table)
- if isinstance(col_type, CppOptional):
- inner = self.parse_type(col_type.inner)
- assert not inner.is_optional, 'Nested optional not allowed'
- return dataclasses.replace(inner, is_optional=True)
+ if isinstance(col_type, CppSelfTableId):
+ return ParsedType(
+ f'{table.class_name}::Id', is_self_id=True, id_table=table)
- raise Exception(f'Unknown type {col_type}')
+ if isinstance(col_type, CppOptional):
+ inner = parse_type(table, col_type.inner)
+ assert not inner.is_optional, 'Nested optional not allowed'
+ return dataclasses.replace(inner, is_optional=True)
- def typed_column_type(self, col: ParsedColumn) -> str:
- """Returns the TypedColumn/IdColumn C++ type for a given column."""
+ raise Exception(f'Unknown type {col_type}')
- parsed = self.parse_type(col.column.type)
- if col.is_implicit_id:
- return f'IdColumn<{parsed.cpp_type}>'
- return f'TypedColumn<{parsed.cpp_type_with_optionality()}>'
- def find_table_deps(self) -> Set[str]:
- """Finds all the other table class names this table depends on.
+def parse_type(table: Table, col_type: CppColumnType) -> ParsedType:
+ """Parses a CppColumnType into its constiuent parts."""
+ return parse_type_with_cols(table, table.columns, col_type)
- By "depends", we mean this table in C++ would need the dependency to be
- defined (or included) before this table is defined."""
- deps: Set[str] = set()
- if self.table.parent:
- deps.add(self.table.parent.class_name)
- for c in self.table.columns:
- # Aliases cannot have dependencies so simply ignore them: trying to parse
- # them before adding implicit columns can cause issues.
- if isinstance(c.type, Alias):
- continue
- id_table = self.parse_type(c.type).id_table
- if id_table:
- deps.add(id_table.class_name)
- return deps
+def typed_column_type(table: Table, col: ParsedColumn) -> str:
+ """Returns the TypedColumn/IdColumn C++ type for a given column."""
+
+ parsed = parse_type(table, col.column.type)
+ if col.is_implicit_id:
+ return f'IdColumn<{parsed.cpp_type}>'
+ return f'TypedColumn<{parsed.cpp_type_with_optionality()}>'
+
+
+def find_table_deps(table: Table) -> List[Table]:
+ """Finds all the other table class names this table depends on.
+
+ By "depends", we mean this table in C++ would need the dependency to be
+ defined (or included) before this table is defined."""
+
+ deps: Dict[str, Table] = {}
+ if table.parent:
+ deps[table.parent.class_name] = table.parent
+ for c in table.columns:
+ # Aliases cannot have dependencies so simply ignore them: trying to parse
+ # them before adding implicit columns can cause issues.
+ if isinstance(c.type, Alias):
+ continue
+ id_table = parse_type(table, c.type).id_table
+ if id_table:
+ deps[id_table.class_name] = id_table
+ return list(deps.values())
def public_sql_name(table: Table) -> str:
@@ -165,10 +173,9 @@
wrapping_view = table.wrapping_sql_view
return wrapping_view.view_name if wrapping_view else table.sql_name
-def _create_implicit_columns_for_root(parsed: ParsedTable
- ) -> List[ParsedColumn]:
+
+def _create_implicit_columns_for_root(table: Table) -> List[ParsedColumn]:
"""Given a root table, returns the implicit id and type columns."""
- table = parsed.table
assert table.parent is None
sql_name = public_sql_name(table)
@@ -191,26 +198,25 @@
]
-def _topological_sort_tables(parsed: List[ParsedTable]) -> List[ParsedTable]:
+def _topological_sort_table_and_deps(parsed: List[Table]) -> List[Table]:
"""Topologically sorts a list of tables (i.e. dependenices appear earlier).
See [1] for information on a topological sort. We do this to allow
dependencies to be processed and appear ealier than their dependents.
[1] https://en.wikipedia.org/wiki/Topological_sorting"""
- table_to_parsed_table = {p.table.class_name: p for p in parsed}
visited: Set[str] = set()
- result: List[ParsedTable] = []
+ result: List[Table] = []
# Topological sorting is really just a DFS where we put the nodes in the list
# after any dependencies.
- def dfs(t: ParsedTable):
- if t.table.class_name in visited:
+ def dfs(t: Table):
+ if t.class_name in visited:
return
- visited.add(t.table.class_name)
+ visited.add(t.class_name)
- for dep in t.find_table_deps():
- dfs(table_to_parsed_table[dep])
+ for dep in find_table_deps(t):
+ dfs(dep)
result.append(t)
for p in parsed:
@@ -226,26 +232,27 @@
return ColumnDoc(doc=doc)
-def parse_tables_from_files(input_paths: List[str]) -> List[ParsedTable]:
+def parse_tables_from_modules(modules: List[str]) -> List[ParsedTable]:
"""Creates a list of tables with the associated paths."""
# Create a mapping from the table to a "parsed" version of the table.
+ tables: Dict[str, Table] = {}
+ for module in modules:
+ imported = importlib.import_module(module)
+ run_tables: List[Table] = imported.__dict__['ALL_TABLES']
+ for table in run_tables:
+ existing_table = tables.get(table.class_name)
+ assert not existing_table or existing_table == table
+ tables[table.class_name] = table
+
+ # Sort all the tables: note that this list may include tables which are not
+ # in |tables| dictionary due to dependencies on tables which live in a file
+ # not covered by |input_paths|.
+ sorted_tables = _topological_sort_table_and_deps(list(tables.values()))
+
parsed_tables: Dict[str, ParsedTable] = {}
- for in_path in input_paths:
- tables: List[Table] = runpy.run_path(in_path)['ALL_TABLES']
- for table in tables:
- existing_table = parsed_tables.get(table.class_name)
- assert not existing_table or existing_table.table == table
- parsed_tables[table.class_name] = ParsedTable(table, [], in_path)
-
- # Sort all the tables to be in order.
- sorted_tables = _topological_sort_tables(list(parsed_tables.values()))
-
- # Create the list of parsed columns
- for i, parsed in enumerate(sorted_tables):
+ for table in sorted_tables:
parsed_columns: List[ParsedColumn]
- table = parsed.table
-
if table.parent:
parsed_parent = parsed_tables[table.parent.class_name]
parsed_columns = [
@@ -253,13 +260,17 @@
for c in parsed_parent.columns
]
else:
- parsed_columns = _create_implicit_columns_for_root(parsed)
+ parsed_columns = _create_implicit_columns_for_root(table)
for c in table.columns:
doc = table.tabledoc.columns.get(c.name) if table.tabledoc else None
parsed_columns.append(ParsedColumn(c, _to_column_doc(doc)))
+ parsed_tables[table.class_name] = ParsedTable(table, parsed_columns)
- sorted_tables[i] = dataclasses.replace(parsed, columns=parsed_columns)
- parsed_tables[parsed.table.class_name] = sorted_tables[i]
-
- return sorted_tables
+ # Only return tables which come directly from |input_paths|. This stops us
+ # generating tables which were not requested.
+ return [
+ parsed_tables[p.class_name]
+ for p in sorted_tables
+ if p.class_name in tables
+ ]
diff --git a/src/trace_processor/prelude/table_functions/BUILD.gn b/src/trace_processor/prelude/table_functions/BUILD.gn
index 4f5ced3..1125c22 100644
--- a/src/trace_processor/prelude/table_functions/BUILD.gn
+++ b/src/trace_processor/prelude/table_functions/BUILD.gn
@@ -13,6 +13,7 @@
# limitations under the License.
import("../../../../gn/perfetto.gni")
+import("../../../../gn/perfetto_tp_tables.gni")
assert(enable_perfetto_trace_processor_sqlite)
@@ -44,6 +45,7 @@
"view.h",
]
deps = [
+ ":tables",
"../../../../gn:default_deps",
"../../../../gn:sqlite",
"../../../base",
@@ -59,6 +61,11 @@
]
}
+perfetto_tp_tables("tables") {
+ sources = [ "tables.py" ]
+ deps = [ "../../tables:tables_python" ]
+}
+
source_set("unittests") {
testonly = true
sources = [
@@ -71,6 +78,7 @@
]
deps = [
":table_functions",
+ ":tables",
"../../../../gn:default_deps",
"../../../../gn:gtest_and_gmock",
"../../containers",
diff --git a/src/trace_processor/prelude/table_functions/ancestor.cc b/src/trace_processor/prelude/table_functions/ancestor.cc
index c1656d9..9089b82 100644
--- a/src/trace_processor/prelude/table_functions/ancestor.cc
+++ b/src/trace_processor/prelude/table_functions/ancestor.cc
@@ -19,6 +19,7 @@
#include <memory>
#include <set>
+#include "src/trace_processor/prelude/table_functions/tables_py.h"
#include "src/trace_processor/sqlite/sqlite_utils.h"
#include "src/trace_processor/types/trace_processor_context.h"
#include "src/trace_processor/util/status_macros.h"
diff --git a/src/trace_processor/prelude/table_functions/ancestor.h b/src/trace_processor/prelude/table_functions/ancestor.h
index c625f16..755a482 100644
--- a/src/trace_processor/prelude/table_functions/ancestor.h
+++ b/src/trace_processor/prelude/table_functions/ancestor.h
@@ -16,40 +16,14 @@
#ifndef SRC_TRACE_PROCESSOR_PRELUDE_TABLE_FUNCTIONS_ANCESTOR_H_
#define SRC_TRACE_PROCESSOR_PRELUDE_TABLE_FUNCTIONS_ANCESTOR_H_
+
#include <optional>
#include "src/trace_processor/prelude/table_functions/table_function.h"
#include "src/trace_processor/storage/trace_storage.h"
-#include "src/trace_processor/tables/profiler_tables.h"
-#include "src/trace_processor/tables/slice_tables.h"
namespace perfetto {
namespace trace_processor {
-namespace tables {
-
-#define PERFETTO_TP_ANCESTOR_SLICE_TABLE_DEF(NAME, PARENT, C) \
- NAME(AncestorSliceTable, "ancestor_slice") \
- PARENT(PERFETTO_TP_SLICE_TABLE_DEF, C) \
- C(tables::SliceTable::Id, start_id, Column::Flag::kHidden)
-
-PERFETTO_TP_TABLE(PERFETTO_TP_ANCESTOR_SLICE_TABLE_DEF);
-
-#define PERFETTO_TP_ANCESTOR_STACK_PROFILE_CALLSITE_TABLE_DEF(NAME, PARENT, C) \
- NAME(AncestorStackProfileCallsiteTable, \
- "experimental_ancestor_stack_profile_callsite") \
- PARENT(PERFETTO_TP_STACK_PROFILE_CALLSITE_DEF, C) \
- C(tables::StackProfileCallsiteTable::Id, start_id, Column::Flag::kHidden)
-
-PERFETTO_TP_TABLE(PERFETTO_TP_ANCESTOR_STACK_PROFILE_CALLSITE_TABLE_DEF);
-
-#define PERFETTO_TP_ANCESTOR_SLICE_BY_STACK_TABLE_DEF(NAME, PARENT, C) \
- NAME(AncestorSliceByStackTable, "ancestor_slice_by_stack") \
- PARENT(PERFETTO_TP_SLICE_TABLE_DEF, C) \
- C(int64_t, start_stack_id, Column::Flag::kHidden)
-
-PERFETTO_TP_TABLE(PERFETTO_TP_ANCESTOR_SLICE_BY_STACK_TABLE_DEF);
-
-} // namespace tables
class TraceProcessorContext;
diff --git a/src/trace_processor/prelude/table_functions/ancestor_unittest.cc b/src/trace_processor/prelude/table_functions/ancestor_unittest.cc
index 08fdad4..afc2d33 100644
--- a/src/trace_processor/prelude/table_functions/ancestor_unittest.cc
+++ b/src/trace_processor/prelude/table_functions/ancestor_unittest.cc
@@ -16,6 +16,7 @@
#include "src/trace_processor/prelude/table_functions/ancestor.h"
+#include "src/trace_processor/prelude/table_functions/tables_py.h"
#include "test/gtest_and_gmock.h"
namespace perfetto {
diff --git a/src/trace_processor/prelude/table_functions/connected_flow.h b/src/trace_processor/prelude/table_functions/connected_flow.h
index c05e25e..3ef3fc3 100644
--- a/src/trace_processor/prelude/table_functions/connected_flow.h
+++ b/src/trace_processor/prelude/table_functions/connected_flow.h
@@ -18,24 +18,14 @@
#define SRC_TRACE_PROCESSOR_PRELUDE_TABLE_FUNCTIONS_CONNECTED_FLOW_H_
#include "src/trace_processor/prelude/table_functions/table_function.h"
+#include "src/trace_processor/prelude/table_functions/tables_py.h"
#include "src/trace_processor/storage/trace_storage.h"
-#include "src/trace_processor/tables/flow_tables.h"
#include <queue>
#include <set>
namespace perfetto {
namespace trace_processor {
-namespace tables {
-
-#define PERFETTO_TP_CONNECTED_FLOW_TABLE_DEF(NAME, PARENT, C) \
- NAME(ConnectedFlowTable, "not_exposed_to_sql") \
- PARENT(PERFETTO_TP_FLOW_TABLE_DEF, C) \
- C(uint32_t, start_id, Column::Flag::kHidden)
-
-PERFETTO_TP_TABLE(PERFETTO_TP_CONNECTED_FLOW_TABLE_DEF);
-
-} // namespace tables
class TraceProcessorContext;
diff --git a/src/trace_processor/prelude/table_functions/descendant.cc b/src/trace_processor/prelude/table_functions/descendant.cc
index 75cb8c9..382edf2 100644
--- a/src/trace_processor/prelude/table_functions/descendant.cc
+++ b/src/trace_processor/prelude/table_functions/descendant.cc
@@ -19,6 +19,7 @@
#include <memory>
#include <set>
+#include "src/trace_processor/prelude/table_functions/tables_py.h"
#include "src/trace_processor/sqlite/sqlite_utils.h"
#include "src/trace_processor/types/trace_processor_context.h"
#include "src/trace_processor/util/status_macros.h"
diff --git a/src/trace_processor/prelude/table_functions/descendant.h b/src/trace_processor/prelude/table_functions/descendant.h
index 8e93811..bffd9b5 100644
--- a/src/trace_processor/prelude/table_functions/descendant.h
+++ b/src/trace_processor/prelude/table_functions/descendant.h
@@ -24,23 +24,6 @@
namespace perfetto {
namespace trace_processor {
-namespace tables {
-
-#define PERFETTO_TP_DESCENDANT_SLICE_TABLE_DEF(NAME, PARENT, C) \
- NAME(DescendantSliceTable, "descendant_slice") \
- PARENT(PERFETTO_TP_SLICE_TABLE_DEF, C) \
- C(uint32_t, start_id, Column::Flag::kHidden)
-
-PERFETTO_TP_TABLE(PERFETTO_TP_DESCENDANT_SLICE_TABLE_DEF);
-
-#define PERFETTO_TP_DESCENDANT_SLICE_BY_STACK_TABLE_DEF(NAME, PARENT, C) \
- NAME(DescendantSliceByStackTable, "descendant_slice_by_stack") \
- PARENT(PERFETTO_TP_SLICE_TABLE_DEF, C) \
- C(int64_t, start_stack_id, Column::Flag::kHidden)
-
-PERFETTO_TP_TABLE(PERFETTO_TP_DESCENDANT_SLICE_BY_STACK_TABLE_DEF);
-
-} // namespace tables
class TraceProcessorContext;
diff --git a/src/trace_processor/prelude/table_functions/descendant_unittest.cc b/src/trace_processor/prelude/table_functions/descendant_unittest.cc
index f1ef1ca..67399d1 100644
--- a/src/trace_processor/prelude/table_functions/descendant_unittest.cc
+++ b/src/trace_processor/prelude/table_functions/descendant_unittest.cc
@@ -16,6 +16,7 @@
#include "src/trace_processor/prelude/table_functions/descendant.h"
+#include "src/trace_processor/prelude/table_functions/tables_py.h"
#include "test/gtest_and_gmock.h"
namespace perfetto {
diff --git a/src/trace_processor/prelude/table_functions/experimental_annotated_stack.cc b/src/trace_processor/prelude/table_functions/experimental_annotated_stack.cc
index 8198376..09363f2 100644
--- a/src/trace_processor/prelude/table_functions/experimental_annotated_stack.cc
+++ b/src/trace_processor/prelude/table_functions/experimental_annotated_stack.cc
@@ -19,24 +19,15 @@
#include <optional>
#include "perfetto/ext/base/string_utils.h"
+#include "src/trace_processor/prelude/table_functions/tables_py.h"
#include "src/trace_processor/sqlite/sqlite_utils.h"
#include "src/trace_processor/storage/trace_storage.h"
-#include "src/trace_processor/tables/profiler_tables.h"
#include "src/trace_processor/types/trace_processor_context.h"
namespace perfetto {
namespace trace_processor {
namespace tables {
-#define PERFETTO_TP_ANNOTATED_CALLSTACK_TABLE_DEF(NAME, PARENT, C) \
- NAME(ExperimentalAnnotatedCallstackTable, \
- "experimental_annotated_callstack") \
- PARENT(PERFETTO_TP_STACK_PROFILE_CALLSITE_DEF, C) \
- C(StringId, annotation) \
- C(tables::StackProfileCallsiteTable::Id, start_id, Column::Flag::kHidden)
-
-PERFETTO_TP_TABLE(PERFETTO_TP_ANNOTATED_CALLSTACK_TABLE_DEF);
-
ExperimentalAnnotatedCallstackTable::~ExperimentalAnnotatedCallstackTable() =
default;
diff --git a/src/trace_processor/prelude/table_functions/experimental_counter_dur.cc b/src/trace_processor/prelude/table_functions/experimental_counter_dur.cc
index 3513c89..a7d9814 100644
--- a/src/trace_processor/prelude/table_functions/experimental_counter_dur.cc
+++ b/src/trace_processor/prelude/table_functions/experimental_counter_dur.cc
@@ -16,20 +16,12 @@
#include "src/trace_processor/prelude/table_functions/experimental_counter_dur.h"
-#include "src/trace_processor/tables/counter_tables.h"
+#include "src/trace_processor/prelude/table_functions/tables_py.h"
namespace perfetto {
namespace trace_processor {
namespace tables {
-#define PERFETTO_TP_COUNTER_DUR_TABLE_DEF(NAME, PARENT, C) \
- NAME(ExperimentalCounterDurTable, "experimental_counter_dur") \
- PARENT(PERFETTO_TP_COUNTER_TABLE_DEF, C) \
- C(int64_t, dur) \
- C(double, delta)
-
-PERFETTO_TP_TABLE(PERFETTO_TP_COUNTER_DUR_TABLE_DEF);
-
ExperimentalCounterDurTable::~ExperimentalCounterDurTable() = default;
} // namespace tables
diff --git a/src/trace_processor/prelude/table_functions/experimental_sched_upid.cc b/src/trace_processor/prelude/table_functions/experimental_sched_upid.cc
index 45a76ea..ba3a0c6 100644
--- a/src/trace_processor/prelude/table_functions/experimental_sched_upid.cc
+++ b/src/trace_processor/prelude/table_functions/experimental_sched_upid.cc
@@ -16,17 +16,14 @@
#include "src/trace_processor/prelude/table_functions/experimental_sched_upid.h"
+#include "src/trace_processor/prelude/table_functions/tables_py.h"
+
namespace perfetto {
namespace trace_processor {
namespace tables {
-#define PERFETTO_TP_SCHED_UPID_TABLE_DEF(NAME, PARENT, C) \
- NAME(ExperimentalSchedUpidTable, "experimental_sched_upid") \
- PARENT(PERFETTO_TP_SCHED_SLICE_TABLE_DEF, C) \
- C(std::optional<UniquePid>, upid)
-
-PERFETTO_TP_TABLE(PERFETTO_TP_SCHED_UPID_TABLE_DEF);
ExperimentalSchedUpidTable::~ExperimentalSchedUpidTable() = default;
+
} // namespace tables
ExperimentalSchedUpid::ExperimentalSchedUpid(
diff --git a/src/trace_processor/prelude/table_functions/experimental_slice_layout.cc b/src/trace_processor/prelude/table_functions/experimental_slice_layout.cc
index e544dbb..d6276dc 100644
--- a/src/trace_processor/prelude/table_functions/experimental_slice_layout.cc
+++ b/src/trace_processor/prelude/table_functions/experimental_slice_layout.cc
@@ -20,11 +20,13 @@
#include "perfetto/ext/base/string_splitter.h"
#include "perfetto/ext/base/string_utils.h"
+#include "src/trace_processor/prelude/table_functions/tables_py.h"
#include "src/trace_processor/sqlite/sqlite_utils.h"
namespace perfetto {
namespace trace_processor {
namespace tables {
+
ExperimentalSliceLayoutTable::~ExperimentalSliceLayoutTable() = default;
}
diff --git a/src/trace_processor/prelude/table_functions/experimental_slice_layout.h b/src/trace_processor/prelude/table_functions/experimental_slice_layout.h
index 19af803..3aa61bb 100644
--- a/src/trace_processor/prelude/table_functions/experimental_slice_layout.h
+++ b/src/trace_processor/prelude/table_functions/experimental_slice_layout.h
@@ -25,18 +25,6 @@
namespace perfetto {
namespace trace_processor {
-namespace tables {
-
-#define PERFETTO_TP_SLICE_LAYOUT_TABLE_DEF(NAME, PARENT, C) \
- NAME(ExperimentalSliceLayoutTable, "experimental_slice_layout") \
- PARENT(PERFETTO_TP_SLICE_TABLE_DEF, C) \
- C(uint32_t, layout_depth) \
- C(StringPool::Id, filter_track_ids, Column::kHidden)
-
-PERFETTO_TP_TABLE(PERFETTO_TP_SLICE_LAYOUT_TABLE_DEF);
-
-} // namespace tables
-
class ExperimentalSliceLayout : public TableFunction {
public:
ExperimentalSliceLayout(StringPool* string_pool,
diff --git a/src/trace_processor/prelude/table_functions/experimental_slice_layout_unittest.cc b/src/trace_processor/prelude/table_functions/experimental_slice_layout_unittest.cc
index 43c986d..164dfbb 100644
--- a/src/trace_processor/prelude/table_functions/experimental_slice_layout_unittest.cc
+++ b/src/trace_processor/prelude/table_functions/experimental_slice_layout_unittest.cc
@@ -19,6 +19,7 @@
#include <algorithm>
#include "src/trace_processor/containers/bit_vector.h"
+#include "src/trace_processor/prelude/table_functions/tables_py.h"
#include "test/gtest_and_gmock.h"
namespace perfetto {
diff --git a/src/trace_processor/prelude/table_functions/tables.py b/src/trace_processor/prelude/table_functions/tables.py
new file mode 100644
index 0000000..4ffc526
--- /dev/null
+++ b/src/trace_processor/prelude/table_functions/tables.py
@@ -0,0 +1,166 @@
+# Copyright (C) 2023 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.
+"""Contains tables for finding ancestor events."""
+
+from python.generators.trace_processor_table.public import Column as C
+from python.generators.trace_processor_table.public import ColumnFlag
+from python.generators.trace_processor_table.public import CppDouble
+from python.generators.trace_processor_table.public import CppInt64
+from python.generators.trace_processor_table.public import CppOptional
+from python.generators.trace_processor_table.public import CppString
+from python.generators.trace_processor_table.public import CppTableId
+from python.generators.trace_processor_table.public import CppUint32
+from python.generators.trace_processor_table.public import Table
+
+from src.trace_processor.tables.counter_tables import COUNTER_TABLE
+from src.trace_processor.tables.flow_tables import FLOW_TABLE
+from src.trace_processor.tables.metadata_tables import PROCESS_TABLE
+from src.trace_processor.tables.profiler_tables import STACK_PROFILE_CALLSITE_TABLE
+from src.trace_processor.tables.slice_tables import SLICE_TABLE
+from src.trace_processor.tables.slice_tables import SCHED_SLICE_TABLE
+
+ANCESTOR_SLICE_TABLE = Table(
+ python_module=__file__,
+ class_name="AncestorSliceTable",
+ sql_name="ancestor_slice",
+ columns=[
+ C("start_id", CppTableId(SLICE_TABLE), flags=ColumnFlag.HIDDEN),
+ ],
+ parent=SLICE_TABLE)
+
+ANCESTOR_SLICE_BY_STACK_TABLE = Table(
+ python_module=__file__,
+ class_name="AncestorSliceByStackTable",
+ sql_name="ancestor_slice_by_stack",
+ columns=[
+ C("start_stack_id", CppInt64(), flags=ColumnFlag.HIDDEN),
+ ],
+ parent=SLICE_TABLE)
+
+ANCESTOR_STACK_PROFILE_CALLSITE_TABLE = Table(
+ python_module=__file__,
+ class_name="AncestorStackProfileCallsiteTable",
+ sql_name="experimental_ancestor_stack_profile_callsite",
+ columns=[
+ C("start_id",
+ CppTableId(STACK_PROFILE_CALLSITE_TABLE),
+ flags=ColumnFlag.HIDDEN),
+ ],
+ parent=STACK_PROFILE_CALLSITE_TABLE)
+
+CONNECTED_FLOW_TABLE = Table(
+ python_module=__file__,
+ class_name="ConnectedFlowTable",
+ sql_name="not_exposed_to_sql",
+ columns=[
+ C("start_id", CppTableId(SLICE_TABLE), flags=ColumnFlag.HIDDEN),
+ ],
+ parent=FLOW_TABLE)
+
+DESCENDANT_SLICE_TABLE = Table(
+ python_module=__file__,
+ class_name="DescendantSliceTable",
+ sql_name="descendant_slice",
+ columns=[
+ C("start_id", CppTableId(SLICE_TABLE), flags=ColumnFlag.HIDDEN),
+ ],
+ parent=SLICE_TABLE)
+
+DESCENDANT_SLICE_BY_STACK_TABLE = Table(
+ python_module=__file__,
+ class_name="DescendantSliceByStackTable",
+ sql_name="descendant_slice_by_stack",
+ columns=[
+ C("start_stack_id", CppInt64(), flags=ColumnFlag.HIDDEN),
+ ],
+ parent=SLICE_TABLE)
+
+EXPERIMENTAL_ANNOTATED_CALLSTACK_TABLE = Table(
+ python_module=__file__,
+ class_name="ExperimentalAnnotatedCallstackTable",
+ sql_name="experimental_annotated_callstack",
+ columns=[
+ C("annotation", CppString()),
+ C("start_id",
+ CppTableId(STACK_PROFILE_CALLSITE_TABLE),
+ flags=ColumnFlag.HIDDEN),
+ ],
+ parent=STACK_PROFILE_CALLSITE_TABLE)
+
+EXPERIMENTAL_ANNOTATED_CALLSTACK_TABLE = Table(
+ python_module=__file__,
+ class_name="ExperimentalAnnotatedCallstackTable",
+ sql_name="experimental_annotated_callstack",
+ columns=[
+ C("annotation", CppString()),
+ C("start_id",
+ CppTableId(STACK_PROFILE_CALLSITE_TABLE),
+ flags=ColumnFlag.HIDDEN),
+ ],
+ parent=STACK_PROFILE_CALLSITE_TABLE)
+
+EXPERIMENTAL_ANNOTATED_CALLSTACK_TABLE = Table(
+ python_module=__file__,
+ class_name="ExperimentalAnnotatedCallstackTable",
+ sql_name="experimental_annotated_callstack",
+ columns=[
+ C("annotation", CppString()),
+ C("start_id",
+ CppTableId(STACK_PROFILE_CALLSITE_TABLE),
+ flags=ColumnFlag.HIDDEN),
+ ],
+ parent=STACK_PROFILE_CALLSITE_TABLE)
+
+EXPERIMENTAL_COUNTER_DUR_TABLE = Table(
+ python_module=__file__,
+ class_name="ExperimentalCounterDurTable",
+ sql_name="experimental_counter_dur",
+ columns=[
+ C("dur", CppInt64()),
+ C("delta", CppDouble()),
+ ],
+ parent=COUNTER_TABLE)
+
+EXPERIMENTAL_SCHED_UPID_TABLE = Table(
+ python_module=__file__,
+ class_name="ExperimentalSchedUpidTable",
+ sql_name="experimental_sched_upid",
+ columns=[
+ C("upid", CppOptional(CppTableId(PROCESS_TABLE))),
+ ],
+ parent=SCHED_SLICE_TABLE)
+
+EXPERIMENTAL_SLICE_LAYOUT_TABLE = Table(
+ python_module=__file__,
+ class_name="ExperimentalSliceLayoutTable",
+ sql_name="experimental_slice_layout",
+ columns=[
+ C("layout_depth", CppUint32()),
+ C("filter_track_ids", CppString(), flags=ColumnFlag.HIDDEN),
+ ],
+ parent=SLICE_TABLE)
+
+# Keep this list sorted.
+ALL_TABLES = [
+ ANCESTOR_SLICE_BY_STACK_TABLE,
+ ANCESTOR_SLICE_TABLE,
+ ANCESTOR_STACK_PROFILE_CALLSITE_TABLE,
+ CONNECTED_FLOW_TABLE,
+ DESCENDANT_SLICE_BY_STACK_TABLE,
+ DESCENDANT_SLICE_TABLE,
+ EXPERIMENTAL_ANNOTATED_CALLSTACK_TABLE,
+ EXPERIMENTAL_COUNTER_DUR_TABLE,
+ EXPERIMENTAL_SCHED_UPID_TABLE,
+ EXPERIMENTAL_SLICE_LAYOUT_TABLE,
+]
diff --git a/src/trace_processor/tables/BUILD.gn b/src/trace_processor/tables/BUILD.gn
index 83145a4..ef39e08 100644
--- a/src/trace_processor/tables/BUILD.gn
+++ b/src/trace_processor/tables/BUILD.gn
@@ -32,11 +32,8 @@
source_set("tables") {
sources = [
- "counter_tables.h",
- "flow_tables.h",
"macros.h",
"macros_internal.h",
- "profiler_tables.h",
"slice_tables.h",
"table_destructors.cc",
]
diff --git a/src/trace_processor/tables/android_tables.py b/src/trace_processor/tables/android_tables.py
index b77afcb..03dff07 100644
--- a/src/trace_processor/tables/android_tables.py
+++ b/src/trace_processor/tables/android_tables.py
@@ -28,6 +28,7 @@
from src.trace_processor.tables.metadata_tables import THREAD_TABLE
ANDROID_LOG_TABLE = Table(
+ python_module=__file__,
class_name="AndroidLogTable",
sql_name="android_logs",
columns=[
@@ -54,6 +55,7 @@
}))
ANDROID_GAME_INTERVENTION_LIST_TABLE = Table(
+ python_module=__file__,
class_name='AndroidGameInterventionListTable',
sql_name='android_game_intervention_list',
columns=[
@@ -126,6 +128,7 @@
}))
ANDROID_DUMPSTATE_TABLE = Table(
+ python_module=__file__,
class_name='AndroidDumpstateTable',
sql_name='android_dumpstate',
columns=[
diff --git a/src/trace_processor/tables/counter_tables.h b/src/trace_processor/tables/counter_tables.h
deleted file mode 100644
index 69668b2..0000000
--- a/src/trace_processor/tables/counter_tables.h
+++ /dev/null
@@ -1,41 +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.
- */
-
-#ifndef SRC_TRACE_PROCESSOR_TABLES_COUNTER_TABLES_H_
-#define SRC_TRACE_PROCESSOR_TABLES_COUNTER_TABLES_H_
-
-#include "src/trace_processor/tables/macros.h"
-#include "src/trace_processor/tables/track_tables_py.h"
-
-namespace perfetto {
-namespace trace_processor {
-namespace tables {
-
-// @tablegroup Events
-// @param arg_set_id {@joinable args.arg_set_id}
-#define PERFETTO_TP_COUNTER_TABLE_DEF(NAME, PARENT, C) \
- NAME(CounterTable, "counter") \
- PERFETTO_TP_ROOT_TABLE(PARENT, C) \
- C(int64_t, ts, Column::Flag::kSorted) \
- C(CounterTrackTable::Id, track_id) \
- C(double, value) \
- C(std::optional<uint32_t>, arg_set_id)
-
-} // namespace tables
-} // namespace trace_processor
-} // namespace perfetto
-
-#endif // SRC_TRACE_PROCESSOR_TABLES_COUNTER_TABLES_H_
diff --git a/src/trace_processor/tables/counter_tables.py b/src/trace_processor/tables/counter_tables.py
index 1dd6495..e882452 100644
--- a/src/trace_processor/tables/counter_tables.py
+++ b/src/trace_processor/tables/counter_tables.py
@@ -26,6 +26,7 @@
from src.trace_processor.tables.track_tables import COUNTER_TRACK_TABLE
COUNTER_TABLE = Table(
+ python_module=__file__,
class_name='CounterTable',
sql_name='counter',
columns=[
diff --git a/src/trace_processor/tables/flow_tables.h b/src/trace_processor/tables/flow_tables.h
deleted file mode 100644
index a00ee89..0000000
--- a/src/trace_processor/tables/flow_tables.h
+++ /dev/null
@@ -1,39 +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.
- */
-
-#ifndef SRC_TRACE_PROCESSOR_TABLES_FLOW_TABLES_H_
-#define SRC_TRACE_PROCESSOR_TABLES_FLOW_TABLES_H_
-
-#include "src/trace_processor/tables/macros.h"
-#include "src/trace_processor/tables/slice_tables.h"
-
-namespace perfetto {
-namespace trace_processor {
-namespace tables {
-
-// @param arg_set_id {@joinable args.arg_set_id}
-#define PERFETTO_TP_FLOW_TABLE_DEF(NAME, PARENT, C) \
- NAME(FlowTable, "flow") \
- PERFETTO_TP_ROOT_TABLE(PARENT, C) \
- C(SliceTable::Id, slice_out) \
- C(SliceTable::Id, slice_in) \
- C(uint32_t, arg_set_id)
-
-} // namespace tables
-} // namespace trace_processor
-} // namespace perfetto
-
-#endif // SRC_TRACE_PROCESSOR_TABLES_FLOW_TABLES_H_
diff --git a/src/trace_processor/tables/flow_tables.py b/src/trace_processor/tables/flow_tables.py
index 0491a31..df0ae4c 100644
--- a/src/trace_processor/tables/flow_tables.py
+++ b/src/trace_processor/tables/flow_tables.py
@@ -22,6 +22,7 @@
from src.trace_processor.tables.slice_tables import SLICE_TABLE
FLOW_TABLE = Table(
+ python_module=__file__,
class_name='FlowTable',
sql_name='flow',
columns=[
diff --git a/src/trace_processor/tables/memory_tables.py b/src/trace_processor/tables/memory_tables.py
index 65263f8..f270aa7 100644
--- a/src/trace_processor/tables/memory_tables.py
+++ b/src/trace_processor/tables/memory_tables.py
@@ -26,6 +26,7 @@
from src.trace_processor.tables.track_tables import TRACK_TABLE
MEMORY_SNAPSHOT_TABLE = Table(
+ python_module=__file__,
class_name='MemorySnapshotTable',
sql_name='memory_snapshot',
columns=[
@@ -43,6 +44,7 @@
}))
PROCESS_MEMORY_SNAPSHOT_TABLE = Table(
+ python_module=__file__,
class_name='ProcessMemorySnapshotTable',
sql_name='process_memory_snapshot',
columns=[
@@ -58,6 +60,7 @@
}))
MEMORY_SNAPSHOT_NODE_TABLE = Table(
+ python_module=__file__,
class_name='MemorySnapshotNodeTable',
sql_name='memory_snapshot_node',
columns=[
@@ -81,6 +84,7 @@
}))
MEMORY_SNAPSHOT_EDGE_TABLE = Table(
+ python_module=__file__,
class_name='MemorySnapshotEdgeTable',
sql_name='memory_snapshot_edge',
columns=[
diff --git a/src/trace_processor/tables/metadata_tables.py b/src/trace_processor/tables/metadata_tables.py
index ee9acca..0219aa9 100644
--- a/src/trace_processor/tables/metadata_tables.py
+++ b/src/trace_processor/tables/metadata_tables.py
@@ -29,6 +29,7 @@
from python.generators.trace_processor_table.public import WrappingSqlView
PROCESS_TABLE = Table(
+ python_module=__file__,
class_name='ProcessTable',
sql_name='internal_process',
columns=[
@@ -100,6 +101,7 @@
}))
THREAD_TABLE = Table(
+ python_module=__file__,
class_name='ThreadTable',
sql_name='internal_thread',
columns=[
@@ -159,6 +161,7 @@
}))
RAW_TABLE = Table(
+ python_module=__file__,
class_name='RawTable',
sql_name='raw',
columns=[
@@ -194,6 +197,7 @@
}))
FTRACE_EVENT_TABLE = Table(
+ python_module=__file__,
class_name='FtraceEventTable',
sql_name='ftrace_event',
parent=RAW_TABLE,
@@ -209,6 +213,7 @@
columns={}))
ARG_TABLE = Table(
+ python_module=__file__,
class_name='ArgTable',
sql_name='internal_args',
columns=[
@@ -235,6 +240,7 @@
}))
METADATA_TABLE = Table(
+ python_module=__file__,
class_name='MetadataTable',
sql_name='metadata',
columns=[
@@ -254,6 +260,7 @@
}))
FILEDESCRIPTOR_TABLE = Table(
+ python_module=__file__,
class_name='FiledescriptorTable',
sql_name='filedescriptor',
columns=[
@@ -290,6 +297,7 @@
}))
EXP_MISSING_CHROME_PROC_TABLE = Table(
+ python_module=__file__,
class_name='ExpMissingChromeProcTable',
sql_name='experimental_missing_chrome_processes',
columns=[
@@ -307,6 +315,7 @@
}))
CPU_TABLE = Table(
+ python_module=__file__,
class_name='CpuTable',
sql_name='cpu',
columns=[
@@ -327,6 +336,7 @@
}))
CPU_FREQ_TABLE = Table(
+ python_module=__file__,
class_name='CpuFreqTable',
sql_name='cpu_freq',
columns=[
@@ -340,6 +350,7 @@
}))
CLOCK_SNAPSHOT_TABLE = Table(
+ python_module=__file__,
class_name='ClockSnapshotTable',
sql_name='clock_snapshot',
columns=[
diff --git a/src/trace_processor/tables/profiler_tables.h b/src/trace_processor/tables/profiler_tables.h
deleted file mode 100644
index f0e84b2..0000000
--- a/src/trace_processor/tables/profiler_tables.h
+++ /dev/null
@@ -1,44 +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.
- */
-
-#ifndef SRC_TRACE_PROCESSOR_TABLES_PROFILER_TABLES_H_
-#define SRC_TRACE_PROCESSOR_TABLES_PROFILER_TABLES_H_
-
-#include "src/trace_processor/tables/macros.h"
-#include "src/trace_processor/tables/track_tables_py.h"
-
-namespace perfetto {
-namespace trace_processor {
-namespace tables {
-
-// A callsite. This is a list of frames that were on the stack.
-// This is generated by the stack profilers: heapprofd and traced_perf.
-// @param depth distance from the bottom-most frame of the callstack.
-// @param parent_id parent frame on the callstack. NULL for the bottom-most.
-// @param frame_id frame at this position in the callstack.
-// @tablegroup Callstack profilers
-#define PERFETTO_TP_STACK_PROFILE_CALLSITE_DEF(NAME, PARENT, C) \
- NAME(StackProfileCallsiteTable, "stack_profile_callsite") \
- PERFETTO_TP_ROOT_TABLE(PARENT, C) \
- C(uint32_t, depth) \
- C(std::optional<StackProfileCallsiteTable::Id>, parent_id) \
- C(StackProfileFrameTable::Id, frame_id)
-
-} // namespace tables
-} // namespace trace_processor
-} // namespace perfetto
-
-#endif // SRC_TRACE_PROCESSOR_TABLES_PROFILER_TABLES_H_
diff --git a/src/trace_processor/tables/profiler_tables.py b/src/trace_processor/tables/profiler_tables.py
index d428009..c712adf 100644
--- a/src/trace_processor/tables/profiler_tables.py
+++ b/src/trace_processor/tables/profiler_tables.py
@@ -28,6 +28,7 @@
from src.trace_processor.tables.track_tables import TRACK_TABLE
PROFILER_SMAPS_TABLE = Table(
+ python_module=__file__,
class_name='ProfilerSmapsTable',
sql_name='profiler_smaps',
columns=[
@@ -94,6 +95,7 @@
}))
PACKAGE_LIST_TABLE = Table(
+ python_module=__file__,
class_name='PackageListTable',
sql_name='package_list',
columns=[
@@ -123,6 +125,7 @@
}))
STACK_PROFILE_MAPPING_TABLE = Table(
+ python_module=__file__,
class_name='StackProfileMappingTable',
sql_name='stack_profile_mapping',
columns=[
@@ -151,6 +154,7 @@
}))
STACK_PROFILE_FRAME_TABLE = Table(
+ python_module=__file__,
class_name='StackProfileFrameTable',
sql_name='stack_profile_frame',
columns=[
@@ -181,6 +185,7 @@
}))
STACK_PROFILE_CALLSITE_TABLE = Table(
+ python_module=__file__,
class_name='StackProfileCallsiteTable',
sql_name='stack_profile_callsite',
columns=[
@@ -204,6 +209,7 @@
}))
STACK_SAMPLE_TABLE = Table(
+ python_module=__file__,
class_name='StackSampleTable',
sql_name='stack_sample',
columns=[
@@ -221,6 +227,7 @@
}))
CPU_PROFILE_STACK_SAMPLE_TABLE = Table(
+ python_module=__file__,
class_name='CpuProfileStackSampleTable',
sql_name='cpu_profile_stack_sample',
columns=[
@@ -239,6 +246,7 @@
}))
PERF_SAMPLE_TABLE = Table(
+ python_module=__file__,
class_name='PerfSampleTable',
sql_name='perf_sample',
columns=[
@@ -278,6 +286,7 @@
}))
SYMBOL_TABLE = Table(
+ python_module=__file__,
class_name='SymbolTable',
sql_name='stack_profile_symbol',
columns=[
@@ -323,6 +332,7 @@
}))
HEAP_PROFILE_ALLOCATION_TABLE = Table(
+ python_module=__file__,
class_name='HeapProfileAllocationTable',
sql_name='heap_profile_allocation',
columns=[
@@ -367,6 +377,7 @@
}))
EXPERIMENTAL_FLAMEGRAPH_NODES_TABLE = Table(
+ python_module=__file__,
class_name='ExperimentalFlamegraphNodesTable',
sql_name='experimental_flamegraph_nodes',
columns=[
@@ -421,6 +432,7 @@
}))
HEAP_GRAPH_CLASS_TABLE = Table(
+ python_module=__file__,
class_name='HeapGraphClassTable',
sql_name='heap_graph_class',
columns=[
@@ -455,6 +467,7 @@
}))
HEAP_GRAPH_OBJECT_TABLE = Table(
+ python_module=__file__,
class_name='HeapGraphObjectTable',
sql_name='heap_graph_object',
columns=[
@@ -500,6 +513,7 @@
}))
HEAP_GRAPH_REFERENCE_TABLE = Table(
+ python_module=__file__,
class_name='HeapGraphReferenceTable',
sql_name='heap_graph_reference',
columns=[
@@ -537,6 +551,7 @@
}))
VULKAN_MEMORY_ALLOCATIONS_TABLE = Table(
+ python_module=__file__,
class_name='VulkanMemoryAllocationsTable',
sql_name='vulkan_memory_allocations',
columns=[
@@ -576,6 +591,7 @@
}))
GPU_COUNTER_GROUP_TABLE = Table(
+ python_module=__file__,
class_name='GpuCounterGroupTable',
sql_name='gpu_counter_group',
columns=[
diff --git a/src/trace_processor/tables/py_tables_unittest.cc b/src/trace_processor/tables/py_tables_unittest.cc
index 9c0b72b..c563a40 100644
--- a/src/trace_processor/tables/py_tables_unittest.cc
+++ b/src/trace_processor/tables/py_tables_unittest.cc
@@ -15,6 +15,7 @@
*/
#include "src/trace_processor/db/column.h"
+#include "src/trace_processor/db/column_storage.h"
#include "src/trace_processor/tables/py_tables_unittest_py.h"
#include "test/gtest_and_gmock.h"
@@ -165,6 +166,59 @@
ASSERT_EQ(slice_.dur()[1], 20);
}
+TEST_F(PyTablesUnittest, Extend) {
+ event_.Insert(TestEventTable::Row(50, 0));
+ event_.Insert(TestEventTable::Row(100, 1));
+ event_.Insert(TestEventTable::Row(150, 2));
+
+ ColumnStorage<int64_t> dur;
+ dur.Append(512);
+ dur.Append(1024);
+ dur.Append(2048);
+
+ 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);
+}
+
+TEST_F(PyTablesUnittest, SelectAndExtend) {
+ event_.Insert(TestEventTable::Row(50, 0));
+ event_.Insert(TestEventTable::Row(100, 1));
+ event_.Insert(TestEventTable::Row(150, 2));
+
+ std::vector<TestEventTable::RowNumber> rows;
+ rows.emplace_back(TestEventTable::RowNumber(1));
+ ColumnStorage<int64_t> dur;
+ dur.Append(1024);
+
+ 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);
+}
+
} // namespace
} // namespace tables
} // namespace trace_processor
diff --git a/src/trace_processor/tables/py_tables_unittest.py b/src/trace_processor/tables/py_tables_unittest.py
index ba7b824..99f69dd 100644
--- a/src/trace_processor/tables/py_tables_unittest.py
+++ b/src/trace_processor/tables/py_tables_unittest.py
@@ -21,6 +21,7 @@
from python.generators.trace_processor_table.public import CppUint32
EVENT_TABLE = Table(
+ python_module=__file__,
class_name="TestEventTable",
sql_name="event",
columns=[
@@ -29,12 +30,14 @@
])
EVENT_CHILD_TABLE = Table(
+ python_module=__file__,
class_name="TestEventChildTable",
sql_name="event",
parent=EVENT_TABLE,
columns=[])
SLICE_TABLE = Table(
+ python_module=__file__,
class_name="TestSliceTable",
sql_name="slice",
parent=EVENT_TABLE,
@@ -43,6 +46,7 @@
])
ARGS_TABLE = Table(
+ python_module=__file__,
class_name="TestArgsTable",
sql_name="args",
columns=[
diff --git a/src/trace_processor/tables/slice_tables.h b/src/trace_processor/tables/slice_tables.h
index e33ae19..44f5ba9 100644
--- a/src/trace_processor/tables/slice_tables.h
+++ b/src/trace_processor/tables/slice_tables.h
@@ -42,16 +42,6 @@
C(std::optional<int64_t>, thread_instruction_count) \
C(std::optional<int64_t>, thread_instruction_delta)
-#define PERFETTO_TP_SCHED_SLICE_TABLE_DEF(NAME, PARENT, C) \
- NAME(SchedSliceTable, "sched_slice") \
- PERFETTO_TP_ROOT_TABLE(PARENT, C) \
- C(int64_t, ts, Column::Flag::kSorted) \
- C(int64_t, dur) \
- C(uint32_t, cpu) \
- C(uint32_t, utid) \
- C(StringPool::Id, end_state) \
- C(int32_t, priority)
-
} // namespace tables
} // namespace trace_processor
} // namespace perfetto
diff --git a/src/trace_processor/tables/slice_tables.py b/src/trace_processor/tables/slice_tables.py
index 50b8c3e..22bd9b3 100644
--- a/src/trace_processor/tables/slice_tables.py
+++ b/src/trace_processor/tables/slice_tables.py
@@ -29,6 +29,7 @@
from src.trace_processor.tables.track_tables import TRACK_TABLE
SLICE_TABLE = Table(
+ python_module=__file__,
class_name='SliceTable',
sql_name='internal_slice',
columns=[
@@ -69,6 +70,7 @@
}))
SCHED_SLICE_TABLE = Table(
+ python_module=__file__,
class_name='SchedSliceTable',
sql_name='sched_slice',
columns=[
@@ -108,6 +110,7 @@
}))
THREAD_STATE_TABLE = Table(
+ python_module=__file__,
class_name='ThreadStateTable',
sql_name='thread_state',
columns=[
@@ -135,6 +138,7 @@
}))
GPU_SLICE_TABLE = Table(
+ python_module=__file__,
class_name='GpuSliceTable',
sql_name='gpu_slice',
columns=[
@@ -169,6 +173,7 @@
}))
GRAPHICS_FRAME_SLICE_TABLE = Table(
+ python_module=__file__,
class_name='GraphicsFrameSliceTable',
sql_name='frame_slice',
columns=[
@@ -191,6 +196,7 @@
}))
EXPECTED_FRAME_TIMELINE_SLICE_TABLE = Table(
+ python_module=__file__,
class_name='ExpectedFrameTimelineSliceTable',
sql_name='expected_frame_timeline_slice',
columns=[
@@ -211,6 +217,7 @@
}))
ACTUAL_FRAME_TIMELINE_SLICE_TABLE = Table(
+ python_module=__file__,
class_name='ActualFrameTimelineSliceTable',
sql_name='actual_frame_timeline_slice',
columns=[
@@ -243,6 +250,7 @@
}))
EXPERIMENTAL_FLAT_SLICE_TABLE = Table(
+ python_module=__file__,
class_name='ExperimentalFlatSliceTable',
sql_name='experimental_flat_slice',
columns=[
diff --git a/src/trace_processor/tables/trace_proto_tables.h b/src/trace_processor/tables/trace_proto_tables.h
deleted file mode 100644
index aa57b59..0000000
--- a/src/trace_processor/tables/trace_proto_tables.h
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Copyright (C) 2020 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_TABLES_TRACE_PROTO_TABLES_H_
-#define SRC_TRACE_PROCESSOR_TABLES_TRACE_PROTO_TABLES_H_
-
-#include "src/trace_processor/tables/macros.h"
-
-namespace perfetto {
-namespace trace_processor {
-namespace tables {
-
-// Experimental table, subject to arbitrary breaking changes.
-#define PERFETTO_TP_EXPERIMENTAL_PROTO_PATH_TABLE_DEF(NAME, PARENT, C) \
- NAME(ExperimentalProtoPathTable, "experimental_proto_path") \
- PERFETTO_TP_ROOT_TABLE(PARENT, C) \
- C(std::optional<ExperimentalProtoPathTable::Id>, parent_id) \
- C(StringPool::Id, field_type) \
- C(std::optional<StringPool::Id>, field_name) \
- C(std::optional<uint32_t>, arg_set_id)
-
-PERFETTO_TP_TABLE(PERFETTO_TP_EXPERIMENTAL_PROTO_PATH_TABLE_DEF);
-
-#define PERFETTO_TP_EXPERIMENTAL_PROTO_CONTENT_TABLE_DEF(NAME, PARENT, C) \
- NAME(ExperimentalProtoContentTable, "experimental_proto_content") \
- PERFETTO_TP_ROOT_TABLE(PARENT, C) \
- C(StringPool::Id, path) \
- C(ExperimentalProtoPathTable::Id, path_id) \
- C(int64_t, total_size) \
- C(int64_t, size) \
- C(int64_t, count)
-
-PERFETTO_TP_TABLE(PERFETTO_TP_EXPERIMENTAL_PROTO_CONTENT_TABLE_DEF);
-
-} // namespace tables
-} // namespace trace_processor
-} // namespace perfetto
-
-#endif // SRC_TRACE_PROCESSOR_TABLES_TRACE_PROTO_TABLES_H_
diff --git a/src/trace_processor/tables/trace_proto_tables.py b/src/trace_processor/tables/trace_proto_tables.py
index f6f5f9d..e9c9754 100644
--- a/src/trace_processor/tables/trace_proto_tables.py
+++ b/src/trace_processor/tables/trace_proto_tables.py
@@ -24,6 +24,7 @@
from python.generators.trace_processor_table.public import CppUint32
EXPERIMENTAL_PROTO_PATH_TABLE = Table(
+ python_module=__file__,
class_name='ExperimentalProtoPathTable',
sql_name='experimental_proto_path',
columns=[
@@ -45,6 +46,7 @@
}))
EXPERIMENTAL_PROTO_CONTENT_TABLE = Table(
+ python_module=__file__,
class_name='ExperimentalProtoContentTable',
sql_name='experimental_proto_content',
columns=[
diff --git a/src/trace_processor/tables/track_tables.py b/src/trace_processor/tables/track_tables.py
index bb5a0df..3cbce76 100644
--- a/src/trace_processor/tables/track_tables.py
+++ b/src/trace_processor/tables/track_tables.py
@@ -25,6 +25,7 @@
from python.generators.trace_processor_table.public import CppUint32
TRACK_TABLE = Table(
+ python_module=__file__,
class_name="TrackTable",
sql_name="track",
columns=[
@@ -62,6 +63,7 @@
}))
PROCESS_TRACK_TABLE = Table(
+ python_module=__file__,
class_name="ProcessTrackTable",
sql_name="process_track",
columns=[
@@ -81,6 +83,7 @@
}))
THREAD_TRACK_TABLE = Table(
+ python_module=__file__,
class_name='ThreadTrackTable',
sql_name='thread_track',
columns=[
@@ -101,6 +104,7 @@
}))
CPU_TRACK_TABLE = Table(
+ python_module=__file__,
class_name='CpuTrackTable',
sql_name='cpu_track',
columns=[
@@ -113,6 +117,7 @@
columns={'cpu': 'The CPU associated with this track'}))
GPU_TRACK_TABLE = Table(
+ python_module=__file__,
class_name='GpuTrackTable',
sql_name='gpu_track',
columns=[
@@ -134,6 +139,7 @@
}))
COUNTER_TRACK_TABLE = Table(
+ python_module=__file__,
class_name='CounterTrackTable',
sql_name='counter_track',
columns=[
@@ -156,6 +162,7 @@
}))
THREAD_COUNTER_TRACK_TABLE = Table(
+ python_module=__file__,
class_name='ThreadCounterTrackTable',
sql_name='thread_counter_track',
columns=[
@@ -174,6 +181,7 @@
}))
PROCESS_COUNTER_TRACK_TABLE = Table(
+ python_module=__file__,
class_name='ProcessCounterTrackTable',
sql_name='process_counter_track',
columns=[
@@ -193,6 +201,7 @@
}))
CPU_COUNTER_TRACK_TABLE = Table(
+ python_module=__file__,
class_name='CpuCounterTrackTable',
sql_name='cpu_counter_track',
columns=[
@@ -205,6 +214,7 @@
columns={'cpu': 'The CPU this track is associated with'}))
IRQ_COUNTER_TRACK_TABLE = Table(
+ python_module=__file__,
class_name='IrqCounterTrackTable',
sql_name='irq_counter_track',
columns=[
@@ -217,6 +227,7 @@
columns={'irq': 'The identifier for the hardirq.'}))
SOFTIRQ_COUNTER_TRACK_TABLE = Table(
+ python_module=__file__,
class_name='SoftirqCounterTrackTable',
sql_name='softirq_counter_track',
columns=[
@@ -229,6 +240,7 @@
columns={'softirq': 'The identifier for the softirq.'}))
GPU_COUNTER_TRACK_TABLE = Table(
+ python_module=__file__,
class_name='GpuCounterTrackTable',
sql_name='gpu_counter_track',
columns=[
@@ -241,6 +253,7 @@
columns={'gpu_id': 'The identifier for the GPU.'}))
PERF_COUNTER_TRACK_TABLE = Table(
+ python_module=__file__,
class_name='PerfCounterTrackTable',
sql_name='perf_counter_track',
columns=[
@@ -265,6 +278,7 @@
}))
ENERGY_COUNTER_TRACK_TABLE = Table(
+ python_module=__file__,
class_name='EnergyCounterTrackTable',
sql_name='energy_counter_track',
columns=[
@@ -286,6 +300,7 @@
}))
UID_COUNTER_TRACK_TABLE = Table(
+ python_module=__file__,
class_name='UidCounterTrackTable',
sql_name='uid_counter_track',
columns=[
@@ -298,6 +313,7 @@
columns={'uid': 'uid of process for which breakdowns are emitted'}))
ENERGY_PER_UID_COUNTER_TRACK_TABLE = Table(
+ python_module=__file__,
class_name='EnergyPerUidCounterTrackTable',
sql_name='energy_per_uid_counter_track',
columns=[
diff --git a/tools/gen_android_bp b/tools/gen_android_bp
index d0eb99f..5317914 100755
--- a/tools/gen_android_bp
+++ b/tools/gen_android_bp
@@ -819,10 +819,9 @@
module.cmd = ' '.join([
f'$(location {bp_binary_module_name})',
'--gen-dir=$(genDir)',
+ '--relative-input-dir=external/perfetto',
'--inputs',
'$(in)',
- '--outputs',
- '$(out)',
])
module.out.update(target.outputs)
module.genrule_headers.add(module.name)
diff --git a/tools/gen_bazel b/tools/gen_bazel
index a514fe3..3121aa8 100755
--- a/tools/gen_bazel
+++ b/tools/gen_bazel
@@ -582,6 +582,9 @@
label = BazelLabel(get_bazel_label_name(target.name), 'perfetto_cc_tp_tables')
label.comment = target.name
label.srcs += (gn_utils.label_to_path(x) for x in target.sources)
+ label.deps += sorted(':' + get_bazel_label_name(x.name)
+ for x in target.transitive_deps
+ if x.name not in default_python_targets)
label.outs += target.outputs
return [label]
diff --git a/tools/gen_tp_table_docs.py b/tools/gen_tp_table_docs.py
index 8b8565a..97e183e 100755
--- a/tools/gen_tp_table_docs.py
+++ b/tools/gen_tp_table_docs.py
@@ -59,7 +59,9 @@
raise Exception('Unknown column documentation type '
f'{table.table.class_name}::{col.column.name}')
- parsed_type = table.parse_type(col.column.type)
+ parsed_type = util.parse_type_with_cols(table.table,
+ [c.column for c in table.columns],
+ col.column.type)
docs_type = parsed_type.cpp_type
if docs_type == 'StringPool::Id':
docs_type = 'string'
@@ -88,11 +90,20 @@
parser = argparse.ArgumentParser()
parser.add_argument('--out', required=True)
parser.add_argument('inputs', nargs='*')
+ parser.add_argument('--relative-input-dir')
args = parser.parse_args()
- tables = util.parse_tables_from_files(args.inputs)
+ def get_relin_path(in_path: str):
+ if not args.relative_input_dir:
+ return in_path
+ return os.path.relpath(in_path, args.relative_input_dir)
+
+ modules = [
+ os.path.splitext(get_relin_path(i).replace('/', '.'))[0]
+ for i in args.inputs
+ ]
table_docs = []
- for parsed in tables:
+ for parsed in util.parse_tables_from_modules(modules):
table = parsed.table
doc = table.tabledoc
assert doc
diff --git a/tools/gen_tp_table_headers.py b/tools/gen_tp_table_headers.py
index 1ce0963..d06c637 100755
--- a/tools/gen_tp_table_headers.py
+++ b/tools/gen_tp_table_headers.py
@@ -28,63 +28,71 @@
#pylint: disable=wrong-import-position
from python.generators.trace_processor_table.serialize import serialize_header
+from python.generators.trace_processor_table.util import find_table_deps
from python.generators.trace_processor_table.util import ParsedTable
-from python.generators.trace_processor_table.util import parse_tables_from_files
+from python.generators.trace_processor_table.util import parse_tables_from_modules
#pylint: enable=wrong-import-position
+# Suffix which replaces the .py extension for all input modules.
+OUT_HEADER_SUFFIX = '_py.h'
+
@dataclass
class Header:
"""Represents a Python module which will be converted to a header."""
- out_path: str
- relout_path: str
tables: List[ParsedTable]
def main():
"""Main function."""
parser = argparse.ArgumentParser()
- parser.add_argument('--gen-dir', required=True)
parser.add_argument('--inputs', required=True, nargs='*')
- parser.add_argument('--outputs', required=True, nargs='*')
+ parser.add_argument('--gen-dir', required=True)
parser.add_argument('--header-prefix')
+ parser.add_argument('--relative-input-dir')
args = parser.parse_args()
- if len(args.inputs) != len(args.outputs):
- raise Exception('Number of inputs must match number of outputs')
-
header_prefix = args.header_prefix if args.header_prefix else ''
- in_to_out = dict(zip(args.inputs, args.outputs))
+
+ def get_relin_path(in_path: str):
+ if not args.relative_input_dir:
+ return in_path
+ return os.path.relpath(in_path, args.relative_input_dir)
+
+ def get_relout_path(in_path: str):
+ path = os.path.splitext(in_path)[0]
+ return os.path.join(header_prefix, path + OUT_HEADER_SUFFIX)
+
+ def get_out_path(in_path: str):
+ return os.path.join(args.gen_dir, get_relout_path(in_path))
+
+ modules = [
+ os.path.splitext(get_relin_path(i).replace('/', '.'))[0]
+ for i in args.inputs
+ ]
headers: Dict[str, Header] = {}
- for table in parse_tables_from_files(args.inputs):
- out_path = in_to_out[table.input_path]
- relout_path = os.path.join(header_prefix,
- os.path.relpath(out_path, args.gen_dir))
-
- header = headers.get(table.input_path, Header(out_path, relout_path, []))
+ for table in parse_tables_from_modules(modules):
+ input_path = os.path.relpath(table.table.python_module, ROOT_DIR)
+ header = headers.get(input_path, Header([]))
header.tables.append(table)
- headers[table.input_path] = header
+ headers[input_path] = header
- # Build a mapping from table class name to the output path of the header
- # which will be generated for it. This is used to include one header into
- # another for Id dependencies.
- table_class_name_to_relout: Dict[str, str] = {}
- for header in headers.values():
- for table in header.tables:
- table_class_name_to_relout[table.table.class_name] = header.relout_path
+ for in_path, header in headers.items():
+ out_path = get_out_path(in_path)
+ relout_path = get_relout_path(in_path)
- for header in headers.values():
# Find all headers depended on by this table. These will be #include-ed when
# generating the header file below so ensure we remove ourself.
header_relout_deps: Set[str] = set()
for table in header.tables:
- header_relout_deps = header_relout_deps.union(
- [table_class_name_to_relout[c] for c in table.find_table_deps()])
- header_relout_deps.discard(header.relout_path)
+ header_relout_deps = header_relout_deps.union([
+ get_relout_path(os.path.relpath(c.python_module, ROOT_DIR))
+ for c in find_table_deps(table.table)
+ ])
+ header_relout_deps.discard(relout_path)
- with open(header.out_path, 'w', encoding='utf8') as out:
- ifdef_guard = re.sub(r'[^a-zA-Z0-9_-]', '_',
- header.relout_path).upper() + '_'
+ with open(out_path, 'w', encoding='utf8') as out:
+ ifdef_guard = re.sub(r'[^a-zA-Z0-9_-]', '_', relout_path).upper() + '_'
out.write(
serialize_header(ifdef_guard, header.tables,
sorted(header_relout_deps)))