Merge "[client] Implement thread functions for windows" into main
diff --git a/Android.bp b/Android.bp
index 9f5a62b..f074854 100644
--- a/Android.bp
+++ b/Android.bp
@@ -4638,6 +4638,7 @@
genrule {
name: "perfetto_protos_perfetto_metrics_chrome_descriptor",
srcs: [
+ "protos/perfetto/metrics/android/ad_services_metric.proto",
"protos/perfetto/metrics/android/android_blocking_call.proto",
"protos/perfetto/metrics/android/android_blocking_calls_cuj_metric.proto",
"protos/perfetto/metrics/android/android_boot.proto",
@@ -4719,6 +4720,7 @@
genrule {
name: "perfetto_protos_perfetto_metrics_descriptor",
srcs: [
+ "protos/perfetto/metrics/android/ad_services_metric.proto",
"protos/perfetto/metrics/android/android_blocking_call.proto",
"protos/perfetto/metrics/android/android_blocking_calls_cuj_metric.proto",
"protos/perfetto/metrics/android/android_boot.proto",
@@ -4783,6 +4785,7 @@
genrule {
name: "perfetto_protos_perfetto_metrics_webview_descriptor",
srcs: [
+ "protos/perfetto/metrics/android/ad_services_metric.proto",
"protos/perfetto/metrics/android/android_blocking_call.proto",
"protos/perfetto/metrics/android/android_blocking_calls_cuj_metric.proto",
"protos/perfetto/metrics/android/android_boot.proto",
@@ -10614,6 +10617,7 @@
genrule {
name: "perfetto_src_trace_processor_metrics_sql_gen_amalgamated_sql_metrics",
srcs: [
+ "src/trace_processor/metrics/sql/android/ad_services_metric.sql",
"src/trace_processor/metrics/sql/android/android_anr.sql",
"src/trace_processor/metrics/sql/android/android_batt.sql",
"src/trace_processor/metrics/sql/android/android_binder.sql",
diff --git a/BUILD b/BUILD
index 26d176a..1ba49a5 100644
--- a/BUILD
+++ b/BUILD
@@ -1790,6 +1790,7 @@
perfetto_filegroup(
name = "src_trace_processor_metrics_sql_android_android",
srcs = [
+ "src/trace_processor/metrics/sql/android/ad_services_metric.sql",
"src/trace_processor/metrics/sql/android/android_anr.sql",
"src/trace_processor/metrics/sql/android/android_batt.sql",
"src/trace_processor/metrics/sql/android/android_binder.sql",
@@ -4034,6 +4035,7 @@
perfetto_proto_library(
name = "protos_perfetto_metrics_android_protos",
srcs = [
+ "protos/perfetto/metrics/android/ad_services_metric.proto",
"protos/perfetto/metrics/android/android_blocking_call.proto",
"protos/perfetto/metrics/android/android_blocking_calls_cuj_metric.proto",
"protos/perfetto/metrics/android/android_boot.proto",
diff --git a/docs/analysis/trace-processor.md b/docs/analysis/trace-processor.md
index 3fb44b5..a459566 100644
--- a/docs/analysis/trace-processor.md
+++ b/docs/analysis/trace-processor.md
@@ -600,53 +600,46 @@
every change to trace processor code or builtin metrics.
#### Choosing where to add diff tests
-Choosing a folder with a diff tests often can be confusing
-as a test can fall into more than one category. This section is a guide
-to decide which folder to choose.
+`diff_tests/` folder contains four directories corresponding to different
+areas of trace processor.
+1. __stdlib__: Tests focusing on testing Perfetto Standard Library, both
+ prelude and the regular modules. The subdirectories in this folder
+ should generally correspond to directories in `perfetto_sql/stdlib`.
+2. __parser__: Tests focusing on ensuring that different trace files are
+ parsed correctly and the corresponding built-in tables are populated.
+3. __metrics__: Tests focusing on testing metrics located in
+ `trace_processor/metrics/sql`. This organisation is mostly historical
+ and code (and corresponding tests) is expected to move to `stdlib` over time.
+4. __syntax__: Tests focusing on testing the core syntax of PerfettoSQL
+ (i.e. `CREATE PERFETTO TABLE` or `CREATE PERFETTO FUNCTION`).
-Broadly, there are two categories which all folders fall into:
-1. __"Area" folders__ which encompass a "vertical" area of interest
- e.g. startup/ contains Android app startup related tests or chrome/
- contains all Chrome related tests.
-2. __"Feature" folders__ which encompass a particular feature of
- trace processor e.g. process_tracking/ tests the lifetime tracking of
- processes, span_join/ tests the span join operator.
+__Scenario__: A new stdlib module `foo/bar.sql` is being added.
-"Area" folders should be preferred for adding tests unless the test is
-applicable to more than one "area"; in this case, one of "feature" folders
-can be used instead.
-
-Here are some common scenarios in which new tests may be added and
-answers on where to add the test:
+_Answer_: Add the test to the `stdlib/foo/bar_tests.py` file.
__Scenario__: A new event is being parsed, the focus of the test is to ensure
-the event is being parsed correctly and the event is focused on a single
-vertical "Area".
+the event is being parsed correctly.
-_Answer_: Add the test in one of the "Area" folders.
-
-__Scenario__: A new event is being parsed and the focus of the test is to ensure
-the event is being parsed correctly and the event is applicable to more than one
-vertical "Area".
-
-_Answer_: Add the test to the parsing/ folder.
+_Answer_: Add the test in one of the `parser` subdirectories. Prefer adding a
+test to an existing related directory (i.e. `sched`, `power`) if one exists.
__Scenario__: A new metric is being added and the focus of the test is to
ensure the metric is being correctly computed.
-_Answer_: Add the test in one of the "Area" folders.
+_Answer_: Add the test in one of the `metrics` subdirectories. Prefer adding a
+test to an existing related directory if one exists. Also consider adding the
+code in question to stdlib.
__Scenario__: A new dynamic table is being added and the focus of the test is to
ensure the dynamic table is being correctly computed...
-_Answer_: Add the test to the dynamic/ folder
+_Answer_: Add the test to the `stdlib/dynamic_tables` folder
__Scenario__: The interals of trace processor are being modified and the test
is to ensure the trace processor is correctly filtering/sorting important
built-in tables.
-_Answer_: Add the test to the tables/ folder.
-
+_Answer_: Add the test to the `parser/core_tables` folder.
## Appendix: table inheritance
diff --git a/protos/perfetto/config/interceptor_config.proto b/protos/perfetto/config/interceptor_config.proto
index 7ecc13b..9263bb5 100644
--- a/protos/perfetto/config/interceptor_config.proto
+++ b/protos/perfetto/config/interceptor_config.proto
@@ -27,5 +27,5 @@
// Matches the name given to RegisterInterceptor().
optional string name = 1;
- optional ConsoleConfig console_config = 100 [lazy = true];
+ optional ConsoleConfig console_config = 100;
}
diff --git a/protos/perfetto/config/perfetto_config.proto b/protos/perfetto/config/perfetto_config.proto
index bf19bbb..ade9e6b 100644
--- a/protos/perfetto/config/perfetto_config.proto
+++ b/protos/perfetto/config/perfetto_config.proto
@@ -901,7 +901,7 @@
// Matches the name given to RegisterInterceptor().
optional string name = 1;
- optional ConsoleConfig console_config = 100 [lazy = true];
+ optional ConsoleConfig console_config = 100;
}
// End of protos/perfetto/config/interceptor_config.proto
diff --git a/protos/perfetto/metrics/android/BUILD.gn b/protos/perfetto/metrics/android/BUILD.gn
index a2ae264..2504f4c 100644
--- a/protos/perfetto/metrics/android/BUILD.gn
+++ b/protos/perfetto/metrics/android/BUILD.gn
@@ -20,6 +20,7 @@
"source_set",
]
sources = [
+ "ad_services_metric.proto",
"android_blocking_call.proto",
"android_blocking_calls_cuj_metric.proto",
"android_boot.proto",
diff --git a/protos/perfetto/metrics/android/ad_services_metric.proto b/protos/perfetto/metrics/android/ad_services_metric.proto
new file mode 100644
index 0000000..c2ddcfd
--- /dev/null
+++ b/protos/perfetto/metrics/android/ad_services_metric.proto
@@ -0,0 +1,41 @@
+/*
+ * 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.
+ */
+
+syntax = "proto2";
+
+package perfetto.protos;
+
+// Next: 2
+message AdServicesUiMetric {
+ optional double latency = 1;
+}
+
+// Next: 2
+message AdServicesAdIdMetric {
+ optional double latency = 1;
+}
+
+// Next: 2
+message AdServicesAppSetIdMetric {
+ optional double latency = 1;
+}
+
+// Next: 4
+message AdServicesMetric {
+ repeated AdServicesUiMetric ui_metric = 1;
+ repeated AdServicesAdIdMetric ad_id_metric = 2;
+ repeated AdServicesAppSetIdMetric app_set_id_metric = 3;
+}
\ No newline at end of file
diff --git a/protos/perfetto/metrics/metrics.proto b/protos/perfetto/metrics/metrics.proto
index 95fd3b4..8330a3f 100644
--- a/protos/perfetto/metrics/metrics.proto
+++ b/protos/perfetto/metrics/metrics.proto
@@ -18,6 +18,7 @@
package perfetto.protos;
+import "protos/perfetto/metrics/android/ad_services_metric.proto";
import "protos/perfetto/metrics/android/android_boot.proto";
import "protos/perfetto/metrics/android/android_frame_timeline_metric.proto";
import "protos/perfetto/metrics/android/anr_metric.proto";
@@ -109,7 +110,7 @@
// Root message for all Perfetto-based metrics.
//
-// Next id: 58
+// Next id: 59
message TraceMetrics {
reserved 4, 10, 13, 14, 16, 19;
@@ -261,11 +262,15 @@
// Metrics for App Not Responding (ANR) errors.
optional AndroidAnrMetric android_anr = 55;
+
// Aggregated Android Monitor Contention metrics
optional AndroidMonitorContentionAggMetric android_monitor_contention_agg = 56;
optional AndroidBootMetric android_boot = 57;
+ // Metric for AdServices module.
+ optional AdServicesMetric ad_services_metric = 58;
+
// Demo extensions.
extensions 450 to 499;
diff --git a/protos/perfetto/metrics/perfetto_merged_metrics.proto b/protos/perfetto/metrics/perfetto_merged_metrics.proto
index e940682..3f270f6 100644
--- a/protos/perfetto/metrics/perfetto_merged_metrics.proto
+++ b/protos/perfetto/metrics/perfetto_merged_metrics.proto
@@ -13,6 +13,31 @@
option go_package = "github.com/google/perfetto/perfetto_proto";
+// Begin of protos/perfetto/metrics/android/ad_services_metric.proto
+
+// Next: 2
+message AdServicesUiMetric {
+ optional double latency = 1;
+}
+
+// Next: 2
+message AdServicesAdIdMetric {
+ optional double latency = 1;
+}
+
+// Next: 2
+message AdServicesAppSetIdMetric {
+ optional double latency = 1;
+}
+
+// Next: 4
+message AdServicesMetric {
+ repeated AdServicesUiMetric ui_metric = 1;
+ repeated AdServicesAdIdMetric ad_id_metric = 2;
+ repeated AdServicesAppSetIdMetric app_set_id_metric = 3;
+}
+// End of protos/perfetto/metrics/android/ad_services_metric.proto
+
// Begin of protos/perfetto/metrics/android/android_blocking_call.proto
// Blocking call on the main thread.
@@ -2283,7 +2308,7 @@
// Root message for all Perfetto-based metrics.
//
-// Next id: 58
+// Next id: 59
message TraceMetrics {
reserved 4, 10, 13, 14, 16, 19;
@@ -2435,11 +2460,15 @@
// Metrics for App Not Responding (ANR) errors.
optional AndroidAnrMetric android_anr = 55;
+
// Aggregated Android Monitor Contention metrics
optional AndroidMonitorContentionAggMetric android_monitor_contention_agg = 56;
optional AndroidBootMetric android_boot = 57;
+ // Metric for AdServices module.
+ optional AdServicesMetric ad_services_metric = 58;
+
// Demo extensions.
extensions 450 to 499;
diff --git a/protos/perfetto/trace/perfetto_trace.proto b/protos/perfetto/trace/perfetto_trace.proto
index a2c34a3..6470fdb 100644
--- a/protos/perfetto/trace/perfetto_trace.proto
+++ b/protos/perfetto/trace/perfetto_trace.proto
@@ -901,7 +901,7 @@
// Matches the name given to RegisterInterceptor().
optional string name = 1;
- optional ConsoleConfig console_config = 100 [lazy = true];
+ optional ConsoleConfig console_config = 100;
}
// End of protos/perfetto/config/interceptor_config.proto
@@ -12495,7 +12495,7 @@
optional uint64 user_ns = 2;
// Time spent in user mode (low prio).
- optional uint64 user_ice_ns = 3;
+ optional uint64 user_nice_ns = 3;
// Time spent in system mode.
optional uint64 system_mode_ns = 4;
diff --git a/protos/perfetto/trace/sys_stats/sys_stats.proto b/protos/perfetto/trace/sys_stats/sys_stats.proto
index 2aad34c..4bc538d 100644
--- a/protos/perfetto/trace/sys_stats/sys_stats.proto
+++ b/protos/perfetto/trace/sys_stats/sys_stats.proto
@@ -45,7 +45,7 @@
optional uint64 user_ns = 2;
// Time spent in user mode (low prio).
- optional uint64 user_ice_ns = 3;
+ optional uint64 user_nice_ns = 3;
// Time spent in system mode.
optional uint64 system_mode_ns = 4;
diff --git a/python/generators/diff_tests/testing.py b/python/generators/diff_tests/testing.py
index 89aea8a..9bd6d84 100644
--- a/python/generators/diff_tests/testing.py
+++ b/python/generators/diff_tests/testing.py
@@ -177,7 +177,7 @@
self.name = name
self.blueprint = blueprint
self.index_dir = index_dir
- self.test_dir = os.path.dirname(os.path.dirname(os.path.dirname(index_dir)))
+ self.test_dir = os.path.abspath(os.path.join(__file__, '../../../../test'))
if blueprint.is_metric():
self.type = TestType.METRIC
diff --git a/python/perfetto/trace_processor/metrics.descriptor b/python/perfetto/trace_processor/metrics.descriptor
index 926dee9..7af1fde 100644
--- a/python/perfetto/trace_processor/metrics.descriptor
+++ b/python/perfetto/trace_processor/metrics.descriptor
Binary files differ
diff --git a/src/base/time_unittest.cc b/src/base/time_unittest.cc
index 6536bc8..a5b9d78 100644
--- a/src/base/time_unittest.cc
+++ b/src/base/time_unittest.cc
@@ -73,26 +73,31 @@
EXPECT_LE(elapsed_cputime.count(), 50 * ns_in_ms);
}
+// This test can work only on Posix platforms which respect the TZ env var.
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_LINUX) || \
+ PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID) || \
+ PERFETTO_BUILDFLAG(PERFETTO_OS_APPLE)
TEST(TimeTest, GetTimezoneOffsetMins) {
const char* tz = getenv("TZ");
std::string tz_save(tz ? tz : "");
auto reset_tz_on_exit = OnScopeExit([&] {
if (!tz_save.empty())
- setenv("TZ", tz_save.c_str(), 1);
+ base::SetEnv("TZ", tz_save.c_str());
});
// Note: the sign is reversed in the semantic of the TZ env var.
// UTC+2 means "2 hours to reach UTC", not "2 hours ahead of UTC".
- setenv("TZ", "UTC+2", true);
+ base::SetEnv("TZ", "UTC+2");
EXPECT_EQ(GetTimezoneOffsetMins(), -2 * 60);
- setenv("TZ", "UTC-2", true);
+ base::SetEnv("TZ", "UTC-2");
EXPECT_EQ(GetTimezoneOffsetMins(), 2 * 60);
- setenv("TZ", "UTC-07:45", true);
+ base::SetEnv("TZ", "UTC-07:45");
EXPECT_EQ(GetTimezoneOffsetMins(), 7 * 60 + 45);
}
+#endif
} // namespace
} // namespace base
diff --git a/src/perfetto_cmd/perfetto_cmd.cc b/src/perfetto_cmd/perfetto_cmd.cc
index 2ddbf04..323d7bc 100644
--- a/src/perfetto_cmd/perfetto_cmd.cc
+++ b/src/perfetto_cmd/perfetto_cmd.cc
@@ -236,8 +236,9 @@
(e.g., file.0, file.1, file.2).
--txt : Parse config as pbtxt. Not for production use.
Not a stable API.
- --query : Queries the service state and prints it as
- human-readable text.
+ --query [--long] : Queries the service state and prints it as
+ human-readable text. --long allows the output to
+ extend past 80 chars.
--query-raw : Like --query, but prints raw proto-encoded bytes
of tracing_service_state.proto.
--help -h
@@ -298,6 +299,7 @@
OPT_IS_DETACHED,
OPT_STOP,
OPT_QUERY,
+ OPT_LONG,
OPT_QUERY_RAW,
OPT_VERSION,
};
@@ -326,6 +328,7 @@
{"is_detached", required_argument, nullptr, OPT_IS_DETACHED},
{"stop", no_argument, nullptr, OPT_STOP},
{"query", no_argument, nullptr, OPT_QUERY},
+ {"long", no_argument, nullptr, OPT_LONG},
{"query-raw", no_argument, nullptr, OPT_QUERY_RAW},
{"version", no_argument, nullptr, OPT_VERSION},
{"save-for-bugreport", no_argument, nullptr, OPT_BUGREPORT},
@@ -520,6 +523,11 @@
continue;
}
+ if (option == OPT_LONG) {
+ query_service_long_ = true;
+ continue;
+ }
+
if (option == OPT_QUERY_RAW) {
query_service_ = true;
query_service_output_raw_ = true;
@@ -550,6 +558,11 @@
return 1;
}
+ if (query_service_long_ && !query_service_) {
+ PERFETTO_ELOG("--long can only be used with --query");
+ return 1;
+ }
+
if (is_detach() && is_attach()) {
PERFETTO_ELOG("--attach and --detach are mutually exclusive");
return 1;
@@ -1396,15 +1409,17 @@
}
}
- printf("%-40s %-40s ", ds.ds_descriptor().name().c_str(),
+ printf("%-40s %-28s ", ds.ds_descriptor().name().c_str(),
producer_id_and_name);
// Print the category names for clients using the track event SDK.
+ std::string cats;
if (!ds.ds_descriptor().track_event_descriptor_raw().empty()) {
const std::string& raw = ds.ds_descriptor().track_event_descriptor_raw();
protos::gen::TrackEventDescriptor desc;
if (desc.ParseFromArray(raw.data(), raw.size())) {
for (const auto& cat : desc.available_categories()) {
- printf("%s,", cat.name().c_str());
+ cats.append(cats.empty() ? "" : ",");
+ cats.append(cat.name());
}
}
} else if (!ds.ds_descriptor().ftrace_descriptor_raw().empty()) {
@@ -1412,11 +1427,17 @@
protos::gen::FtraceDescriptor desc;
if (desc.ParseFromArray(raw.data(), raw.size())) {
for (const auto& cat : desc.atrace_categories()) {
- printf("%s,", cat.name().c_str());
+ cats.append(cats.empty() ? "" : ",");
+ cats.append(cat.name());
}
}
}
- printf("\n");
+ const size_t kCatsShortLen = 40;
+ if (!query_service_long_ && cats.length() > kCatsShortLen) {
+ cats = cats.substr(0, kCatsShortLen);
+ cats.append("... (use --long to expand)");
+ }
+ printf("%s\n", cats.c_str());
} // for data_sources()
if (svc_state.supports_tracing_sessions()) {
diff --git a/src/perfetto_cmd/perfetto_cmd.h b/src/perfetto_cmd/perfetto_cmd.h
index b55cbc8..7ac090f 100644
--- a/src/perfetto_cmd/perfetto_cmd.h
+++ b/src/perfetto_cmd/perfetto_cmd.h
@@ -153,6 +153,7 @@
bool redetach_once_attached_ = false;
bool query_service_ = false;
bool query_service_output_raw_ = false;
+ bool query_service_long_ = false;
bool bugreport_ = false;
bool background_ = false;
bool background_wait_ = false;
diff --git a/src/trace_processor/importers/proto/system_probes_parser.cc b/src/trace_processor/importers/proto/system_probes_parser.cc
index 0eefa57..aa46613 100644
--- a/src/trace_processor/importers/proto/system_probes_parser.cc
+++ b/src/trace_processor/importers/proto/system_probes_parser.cc
@@ -312,7 +312,7 @@
track = context_->track_tracker->InternCpuCounterTrack(
cpu_times_user_nice_ns_id_, ct.cpu_id());
context_->event_tracker->PushCounter(
- ts, static_cast<double>(ct.user_ice_ns()), track);
+ ts, static_cast<double>(ct.user_nice_ns()), track);
track = context_->track_tracker->InternCpuCounterTrack(
cpu_times_system_mode_ns_id_, ct.cpu_id());
diff --git a/src/trace_processor/metrics/sql/android/BUILD.gn b/src/trace_processor/metrics/sql/android/BUILD.gn
index 6c31943..a2e64da 100644
--- a/src/trace_processor/metrics/sql/android/BUILD.gn
+++ b/src/trace_processor/metrics/sql/android/BUILD.gn
@@ -20,6 +20,7 @@
perfetto_sql_source_set("android") {
sources = [
"android_anr.sql",
+ "ad_services_metric.sql",
"android_batt.sql",
"android_binder.sql",
"android_blocking_calls_cuj_metric.sql",
diff --git a/src/trace_processor/metrics/sql/android/ad_services_metric.sql b/src/trace_processor/metrics/sql/android/ad_services_metric.sql
new file mode 100644
index 0000000..36885fd
--- /dev/null
+++ b/src/trace_processor/metrics/sql/android/ad_services_metric.sql
@@ -0,0 +1,59 @@
+--
+-- Copyright 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
+--
+-- https://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.
+--
+
+CREATE OR REPLACE PERFETTO FUNCTION GET_EVENT_LATENCY_TABLE(event_name STRING)
+RETURNS TABLE (latency LONG) AS
+SELECT
+ dur / 1e6 as latency
+FROM
+ slices
+WHERE
+ name = $event_name;
+
+DROP VIEW IF EXISTS ad_services_metric_output;
+CREATE VIEW ad_services_metric_output AS
+SELECT
+ AdServicesMetric(
+ 'ui_metric',
+ (
+ SELECT
+ RepeatedField(
+ AdServicesUiMetric('latency', latency)
+ )
+ FROM
+ GET_EVENT_LATENCY_TABLE("NotificationTriggerEvent")
+ ),
+ 'app_set_id_metric',
+ (
+ SELECT
+ RepeatedField(
+ AdServicesAppSetIdMetric(
+ 'latency', latency
+ )
+ )
+ FROM
+ GET_EVENT_LATENCY_TABLE("AdIdCacheEvent")
+ ),
+ 'ad_id_metric',
+ (
+ SELECT
+ RepeatedField(
+ AdServicesAdIdMetric('latency', latency)
+ )
+ FROM
+ GET_EVENT_LATENCY_TABLE("AppSetIdEvent")
+ )
+);
diff --git a/src/trace_processor/metrics/sql/chrome/scroll_jank_cause_queuing_delay.sql b/src/trace_processor/metrics/sql/chrome/scroll_jank_cause_queuing_delay.sql
index 9257d84..6c246e8 100644
--- a/src/trace_processor/metrics/sql/chrome/scroll_jank_cause_queuing_delay.sql
+++ b/src/trace_processor/metrics/sql/chrome/scroll_jank_cause_queuing_delay.sql
@@ -357,6 +357,8 @@
"TabGroupUiToolbarView"
WHEN $name GLOB "*TabGridThumbnailView*" THEN
"TabGridThumbnailView"
+ WHEN $name GLOB "*TabThumbnailView" THEN
+ "TabThumbnailView"
WHEN $name GLOB "*TabGridDialogView*" THEN
"TabGridDialogView"
WHEN $name GLOB "*BottomContainer*" THEN
diff --git a/src/traced/probes/sys_stats/sys_stats_data_source.cc b/src/traced/probes/sys_stats/sys_stats_data_source.cc
index e5c02a9..32cd67f 100644
--- a/src/traced/probes/sys_stats/sys_stats_data_source.cc
+++ b/src/traced/probes/sys_stats/sys_stats_data_source.cc
@@ -438,7 +438,7 @@
auto* cpu_stat = sys_stats->add_cpu_stat();
cpu_stat->set_cpu_id(static_cast<uint32_t>(cpu_id));
cpu_stat->set_user_ns(cpu_times[0] * ns_per_user_hz_);
- cpu_stat->set_user_ice_ns(cpu_times[1] * ns_per_user_hz_);
+ cpu_stat->set_user_nice_ns(cpu_times[1] * ns_per_user_hz_);
cpu_stat->set_system_mode_ns(cpu_times[2] * ns_per_user_hz_);
cpu_stat->set_idle_ns(cpu_times[3] * ns_per_user_hz_);
cpu_stat->set_io_wait_ns(cpu_times[4] * ns_per_user_hz_);
diff --git a/src/tracing/BUILD.gn b/src/tracing/BUILD.gn
index 19b3205..f0a04eb 100644
--- a/src/tracing/BUILD.gn
+++ b/src/tracing/BUILD.gn
@@ -92,7 +92,7 @@
"../../include/perfetto/tracing/core",
"../../protos/perfetto/common:zero",
"../../protos/perfetto/config:cpp",
- "../../protos/perfetto/config/interceptors:zero",
+ "../../protos/perfetto/config/interceptors:cpp",
"../../protos/perfetto/config/track_event:cpp",
"../base",
"core",
diff --git a/src/tracing/console_interceptor.cc b/src/tracing/console_interceptor.cc
index 2c3221f..a594409 100644
--- a/src/tracing/console_interceptor.cc
+++ b/src/tracing/console_interceptor.cc
@@ -33,7 +33,7 @@
#include "protos/perfetto/common/interceptor_descriptor.gen.h"
#include "protos/perfetto/config/data_source_config.gen.h"
#include "protos/perfetto/config/interceptor_config.gen.h"
-#include "protos/perfetto/config/interceptors/console_config.pbzero.h"
+#include "protos/perfetto/config/interceptors/console_config.gen.h"
#include "protos/perfetto/trace/interned_data/interned_data.pbzero.h"
#include "protos/perfetto/trace/trace_packet.pbzero.h"
#include "protos/perfetto/trace/trace_packet_defaults.pbzero.h"
@@ -275,13 +275,13 @@
#else
bool use_colors = false;
#endif
- protos::pbzero::ConsoleConfig::Decoder config(
- args.config.interceptor_config().console_config_raw());
+ const protos::gen::ConsoleConfig& config =
+ args.config.interceptor_config().console_config();
if (config.has_enable_colors())
use_colors = config.enable_colors();
- if (config.output() == protos::pbzero::ConsoleConfig::OUTPUT_STDOUT) {
+ if (config.output() == protos::gen::ConsoleConfig::OUTPUT_STDOUT) {
fd = STDOUT_FILENO;
- } else if (config.output() == protos::pbzero::ConsoleConfig::OUTPUT_STDERR) {
+ } else if (config.output() == protos::gen::ConsoleConfig::OUTPUT_STDERR) {
fd = STDERR_FILENO;
}
fd_ = fd;
diff --git a/test/trace_processor/diff_tests/android/ad_services_metric.py b/test/trace_processor/diff_tests/android/ad_services_metric.py
new file mode 100644
index 0000000..efa827f
--- /dev/null
+++ b/test/trace_processor/diff_tests/android/ad_services_metric.py
@@ -0,0 +1,40 @@
+#!/usr/bin/env python3
+# 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.
+
+from os import sys, path
+
+import synth_common
+
+UI_NOTIFICATION_TRIGGER_EVENT = "NotificationTriggerEvent"
+AD_ID_CACHE_EVENT = "AdIdCacheEvent"
+APP_SET_ID_EVENT = "AppSetIdEvent"
+
+trace = synth_common.create_trace()
+
+trace.add_ftrace_packet(cpu=0)
+
+trace.add_sys_enter(ts=100, tid=42, id=64)
+trace.add_sys_exit(ts=200, tid=42, id=64, ret=0)
+
+trace.add_atrace_begin(ts=350, tid=42, pid=42, buf=UI_NOTIFICATION_TRIGGER_EVENT)
+trace.add_atrace_end(ts=650, tid=42, pid=42)
+
+trace.add_atrace_begin(ts=750, tid=42, pid=42, buf=AD_ID_CACHE_EVENT)
+trace.add_atrace_end(ts=850, tid=42, pid=42)
+
+trace.add_atrace_begin(ts=900, tid=42, pid=42, buf=APP_SET_ID_EVENT)
+trace.add_atrace_end(ts=1200, tid=42, pid=42)
+
+sys.stdout.buffer.write(trace.trace.SerializeToString())
\ No newline at end of file
diff --git a/test/trace_processor/diff_tests/android/tests.py b/test/trace_processor/diff_tests/android/tests.py
index 8bbbeb7..58410ce 100644
--- a/test/trace_processor/diff_tests/android/tests.py
+++ b/test/trace_processor/diff_tests/android/tests.py
@@ -1186,3 +1186,22 @@
}
}
"""))
+
+ def test_ad_services_metric(self):
+ return DiffTestBlueprint(
+ trace=Path('ad_services_metric.py'),
+ query=Metric('ad_services_metric'),
+ out=TextProto(r"""
+ ad_services_metric {
+ ui_metric {
+ latency: 0.0003
+ }
+ app_set_id_metric {
+ latency: 0.0001
+ }
+ ad_id_metric {
+ latency:0.0003
+ }
+ }
+ """)
+ )
diff --git a/test/trace_processor/diff_tests/chrome/tests_scroll_jank.py b/test/trace_processor/diff_tests/chrome/tests_scroll_jank.py
index ef8ec6a..deb365a 100644
--- a/test/trace_processor/diff_tests/chrome/tests_scroll_jank.py
+++ b/test/trace_processor/diff_tests/chrome/tests_scroll_jank.py
@@ -355,7 +355,7 @@
def test_chrome_thread_slice_repeated(self):
return DiffTestBlueprint(
- trace=Path('../track_event/track_event_counters.textproto'),
+ trace=Path('../parser/track_event/track_event_counters.textproto'),
query="""
SELECT RUN_METRIC('chrome/chrome_thread_slice.sql');
diff --git a/test/trace_processor/diff_tests/include_index.py b/test/trace_processor/diff_tests/include_index.py
index b131e43..a0bcb08 100644
--- a/test/trace_processor/diff_tests/include_index.py
+++ b/test/trace_processor/diff_tests/include_index.py
@@ -30,9 +30,6 @@
from diff_tests.android.tests_games import AndroidGames
from diff_tests.android.tests_surfaceflinger_layers import SurfaceFlingerLayers
from diff_tests.android.tests_surfaceflinger_transactions import SurfaceFlingerTransactions
-from diff_tests.atrace.tests import Atrace
-from diff_tests.atrace.tests_error_handling import AtraceErrorHandling
-from diff_tests.camera.tests import Camera
from diff_tests.chrome.tests import Chrome
from diff_tests.chrome.tests_args import ChromeArgs
from diff_tests.chrome.tests_memory_snapshots import ChromeMemorySnapshots
@@ -40,74 +37,151 @@
from diff_tests.chrome.tests_rail_modes import ChromeRailModes
from diff_tests.chrome.tests_scroll_jank import ChromeScrollJank
from diff_tests.chrome.tests_touch_gesture import ChromeTouchGesture
-from diff_tests.codecs.tests import Codecs
-from diff_tests.cros.tests import Cros
-from diff_tests.dynamic.tests import Dynamic
-from diff_tests.fs.tests import Fs
-from diff_tests.fuchsia.tests import Fuchsia
-from diff_tests.functions.tests import Functions
from diff_tests.graphics.tests import Graphics
-from diff_tests.graphics.tests_drm_related_ftrace_events import \
- GraphicsDrmRelatedFtraceEvents
+from diff_tests.graphics.tests_drm_related_ftrace_events import GraphicsDrmRelatedFtraceEvents
from diff_tests.graphics.tests_gpu_trace import GraphicsGpuTrace
-from diff_tests.memory.tests import Memory
-from diff_tests.memory.tests_metrics import MemoryMetrics
-from diff_tests.network.tests import Network
-from diff_tests.parsing.tests import Parsing
-from diff_tests.parsing.tests_debug_annotation import ParsingDebugAnnotation
-from diff_tests.parsing.tests_memory_counters import ParsingMemoryCounters
-from diff_tests.parsing.tests_rss_stats import ParsingRssStats
-from diff_tests.perfetto_sql.tests import PerfettoSql
-from diff_tests.performance.tests import Performance
-from diff_tests.pkvm.tests import Pkvm
+from diff_tests.metrics.camera.tests import Camera
+from diff_tests.metrics.codecs.tests import Codecs
+from diff_tests.metrics.frame_timeline.tests import FrameTimeline
+from diff_tests.metrics.irq.tests import IRQ
+from diff_tests.metrics.memory.tests import MemoryMetrics
+from diff_tests.metrics.network.tests import NetworkMetrics
+from diff_tests.metrics.profiling.tests import ProfilingMetrics
+from diff_tests.metrics.startup.tests import Startup
+from diff_tests.metrics.startup.tests_broadcasts import StartupBroadcasts
+from diff_tests.metrics.startup.tests_lock_contention import StartupLockContention
+from diff_tests.metrics.startup.tests_metrics import StartupMetrics
+from diff_tests.metrics.webview.tests import WebView
+from diff_tests.parser.android_fs.tests import AndroidFs
+from diff_tests.parser.atrace.tests import Atrace
+from diff_tests.parser.atrace.tests_error_handling import AtraceErrorHandling
+from diff_tests.parser.cros.tests import Cros
+from diff_tests.parser.fs.tests import Fs
+from diff_tests.parser.fuchsia.tests import Fuchsia
+from diff_tests.parser.memory.tests import MemoryParser
+from diff_tests.parser.network.tests import NetworkParser
+from diff_tests.parser.parsing.tests import Parsing
+from diff_tests.parser.parsing.tests_debug_annotation import ParsingDebugAnnotation
+from diff_tests.parser.parsing.tests_memory_counters import ParsingMemoryCounters
+from diff_tests.parser.parsing.tests_rss_stats import ParsingRssStats
+from diff_tests.parser.process_tracking.tests import ProcessTracking
+from diff_tests.parser.profiling.tests import Profiling
+from diff_tests.parser.profiling.tests_heap_graph import ProfilingHeapGraph
+from diff_tests.parser.profiling.tests_heap_profiling import ProfilingHeapProfiling
+from diff_tests.parser.profiling.tests_llvm_symbolizer import ProfilingLlvmSymbolizer
+from diff_tests.parser.sched.tests import SchedParser
+from diff_tests.parser.smoke.tests import Smoke
+from diff_tests.parser.smoke.tests_compute_metrics import SmokeComputeMetrics
+from diff_tests.parser.smoke.tests_json import SmokeJson
+from diff_tests.parser.smoke.tests_sched_events import SmokeSchedEvents
+from diff_tests.parser.track_event.tests import TrackEvent
+from diff_tests.parser.translated_args.tests import TranslatedArgs
+from diff_tests.parser.ufs.tests import Ufs
from diff_tests.power.tests import Power
from diff_tests.power.tests_energy_breakdown import PowerEnergyBreakdown
from diff_tests.power.tests_entity_state_residency import EntityStateResidency
from diff_tests.power.tests_linux_sysfs_power import LinuxSysfsPower
from diff_tests.power.tests_power_rails import PowerPowerRails
from diff_tests.power.tests_voltage_and_scaling import PowerVoltageAndScaling
-from diff_tests.process_tracking.tests import ProcessTracking
-from diff_tests.profiling.tests import Profiling
-from diff_tests.profiling.tests_heap_graph import ProfilingHeapGraph
-from diff_tests.profiling.tests_heap_profiling import ProfilingHeapProfiling
-from diff_tests.profiling.tests_llvm_symbolizer import ProfilingLlvmSymbolizer
-from diff_tests.profiling.tests_metrics import ProfilingMetrics
-from diff_tests.scheduler.tests import Scheduler
-from diff_tests.slices.tests import Slices
-from diff_tests.smoke.tests import Smoke
-from diff_tests.smoke.tests_compute_metrics import SmokeComputeMetrics
-from diff_tests.smoke.tests_json import SmokeJson
-from diff_tests.smoke.tests_sched_events import SmokeSchedEvents
-from diff_tests.span_join.tests_left_join import SpanJoinLeftJoin
-from diff_tests.span_join.tests_outer_join import SpanJoinOuterJoin
-from diff_tests.span_join.tests_regression import SpanJoinRegression
-from diff_tests.span_join.tests_smoke import SpanJoinSmoke
-from diff_tests.startup.tests import Startup
-from diff_tests.startup.tests_broadcasts import StartupBroadcasts
-from diff_tests.startup.tests_lock_contention import StartupLockContention
-from diff_tests.startup.tests_metrics import StartupMetrics
+from diff_tests.stdlib.dynamic_tables.tests import DynamicTables
+from diff_tests.stdlib.pkvm.tests import Pkvm
+from diff_tests.stdlib.slices.tests import Slices
+from diff_tests.stdlib.span_join.tests_left_join import SpanJoinLeftJoin
+from diff_tests.stdlib.span_join.tests_outer_join import SpanJoinOuterJoin
+from diff_tests.stdlib.span_join.tests_regression import SpanJoinRegression
+from diff_tests.stdlib.span_join.tests_smoke import SpanJoinSmoke
+from diff_tests.stdlib.timestamps.tests import Timestamps
+from diff_tests.syntax.functions.tests import Functions
+from diff_tests.syntax.perfetto_sql.tests import PerfettoSql
from diff_tests.tables.tests import Tables
from diff_tests.tables.tests_counters import TablesCounters
from diff_tests.tables.tests_sched import TablesSched
-from diff_tests.time.tests import Time
-from diff_tests.track_event.tests import TrackEvent
-from diff_tests.translation.tests import Translation
-from diff_tests.ufs.tests import Ufs
-from diff_tests.webview.tests import WebView
-from diff_tests.android_fs.tests import AndroidFs
sys.path.pop()
def fetch_all_diff_tests(index_path: str) -> List['testing.TestCase']:
- return [
+ parser_tests = [
+ *AndroidFs(index_path, 'parser/android_fs', 'AndroidFs').fetch(),
+ *Atrace(index_path, 'parser/atrace', 'Atrace').fetch(),
+ *AtraceErrorHandling(index_path, 'parser/atrace',
+ 'AtraceErrorHandling').fetch(),
+ *Cros(index_path, 'parser/cros', 'Cros').fetch(),
+ *Fs(index_path, 'parser/fs', 'Fs').fetch(),
+ *Fuchsia(index_path, 'parser/fuchsia', 'Fuchsia').fetch(),
+ *MemoryParser(index_path, 'parser/memory', 'MemoryParser').fetch(),
+ *NetworkParser(index_path, 'parser/network', 'NetworkParser').fetch(),
+ *ProcessTracking(index_path, 'parser/process_tracking',
+ 'ProcessTracking').fetch(),
+ *Profiling(index_path, 'parser/profiling', 'Profiling').fetch(),
+ *ProfilingHeapProfiling(index_path, 'parser/profiling',
+ 'ProfilingHeapProfiling').fetch(),
+ *ProfilingHeapGraph(index_path, 'parser/profiling',
+ 'ProfilingHeapGraph').fetch(),
+ *ProfilingLlvmSymbolizer(index_path, 'parser/profiling',
+ 'ProfilingLlvmSymbolizer').fetch(),
+ *Smoke(index_path, 'parser/smoke', 'Smoke').fetch(),
+ *SchedParser(index_path, 'parser/sched', 'SchedParser').fetch(),
+ *SmokeComputeMetrics(index_path, 'parser/smoke',
+ 'SmokeComputeMetrics').fetch(),
+ *SmokeJson(index_path, 'parser/smoke', 'SmokeJson').fetch(),
+ *SmokeSchedEvents(index_path, 'parser/smoke', 'SmokeSchedEvents').fetch(),
+ *TrackEvent(index_path, 'parser/track_event', 'TrackEvent').fetch(),
+ *TranslatedArgs(index_path, 'parser/translated_args',
+ 'TranslatedArgs').fetch(),
+ *Ufs(index_path, 'parser/ufs', 'Ufs').fetch(),
+ # TODO(altimin, lalitm): "parsing" should be split into more specific directories.
+ *Parsing(index_path, 'parser/parsing', 'Parsing').fetch(),
+ *ParsingDebugAnnotation(index_path, 'parser/parsing',
+ 'ParsingDebugAnnotation').fetch(),
+ *ParsingRssStats(index_path, 'parser/parsing', 'ParsingRssStats').fetch(),
+ *ParsingMemoryCounters(index_path, 'parser/parsing',
+ 'ParsingMemoryCounters').fetch(),
+ ]
+
+ metrics_tests = [
+ *Camera(index_path, 'metrics/camera', 'Camera').fetch(),
+ *Codecs(index_path, 'metrics/codecs', 'Codecs').fetch(),
+ *MemoryMetrics(index_path, 'metrics/memory', 'MemoryMetrics').fetch(),
+ *NetworkMetrics(index_path, 'metrics/network', 'NetworkMetrics').fetch(),
+ *FrameTimeline(index_path, 'metrics/frame_timeline',
+ 'FrameTimeline').fetch(),
+ *IRQ(index_path, 'metrics/irq', 'IRQ').fetch(),
+ *ProfilingMetrics(index_path, 'metrics/profiling',
+ 'ProfilingMetrics').fetch(),
+ *Startup(index_path, 'metrics/startup', 'Startup').fetch(),
+ *StartupBroadcasts(index_path, 'metrics/startup',
+ 'StartupBroadcasts').fetch(),
+ *StartupMetrics(index_path, 'metrics/startup', 'StartupMetrics').fetch(),
+ *StartupLockContention(index_path, 'metrics/startup',
+ 'StartupLockContention').fetch(),
+ *WebView(index_path, 'metrics/webview', 'WebView').fetch(),
+ ]
+
+ stdlib_tests = [
+ *DynamicTables(index_path, 'stdlib/dynamic_tables',
+ 'DynamicTables').fetch(),
+ *Pkvm(index_path, 'stdlib/pkvm', 'Pkvm').fetch(),
+ *Slices(index_path, 'stdlib/slices', 'Slices').fetch(),
+ *SpanJoinLeftJoin(index_path, 'stdlib/span_join',
+ 'SpanJoinLeftJoin').fetch(),
+ *SpanJoinOuterJoin(index_path, 'stdlib/span_join',
+ 'SpanJoinOuterJoin').fetch(),
+ *SpanJoinSmoke(index_path, 'stdlib/span_join', 'SpanJoinSmoke').fetch(),
+ *SpanJoinRegression(index_path, 'stdlib/span_join',
+ 'SpanJoinRegression').fetch(),
+ *Timestamps(index_path, 'stdlib/timestamps', 'Timestamps').fetch(),
+ ]
+
+ syntax_tests = [
+ *Functions(index_path, 'syntax/functions', 'Functions').fetch(),
+ *PerfettoSql(index_path, 'syntax/perfetto_sql', 'PerfettoSql').fetch(),
+ ]
+
+ return parser_tests + metrics_tests + stdlib_tests + syntax_tests + [
*Android(index_path, 'android', 'Android').fetch(),
*AndroidBugreport(index_path, 'android', 'AndroidBugreport').fetch(),
- *AndroidFs(index_path, 'android_fs', 'AndroidFs').fetch(),
*AndroidGames(index_path, 'android', 'AndroidGames').fetch(),
- *Atrace(index_path, 'atrace', 'Atrace').fetch(),
- *AtraceErrorHandling(index_path, 'atrace', 'AtraceErrorHandling').fetch(),
- *Camera(index_path, 'camera', 'Camera').fetch(),
*ChromeScrollJank(index_path, 'chrome', 'ChromeScrollJank').fetch(),
*ChromeTouchGesture(index_path, 'chrome', 'ChromeTouchGesture').fetch(),
*ChromeMemorySnapshots(index_path, 'chrome',
@@ -116,64 +190,19 @@
*ChromeProcesses(index_path, 'chrome', 'ChromeProcesses').fetch(),
*ChromeArgs(index_path, 'chrome', 'ChromeArgs').fetch(),
*Chrome(index_path, 'chrome', 'Chrome').fetch(),
- *Codecs(index_path, 'codecs', 'Codecs').fetch(),
- *Cros(index_path, 'cros', 'Cros').fetch(),
- *Dynamic(index_path, 'dynamic', 'Dynamic').fetch(),
*EntityStateResidency(index_path, 'power',
'EntityStateResidency').fetch(),
- *Fs(index_path, 'fs', 'Fs').fetch(),
- *Fuchsia(index_path, 'fuchsia', 'Fuchsia').fetch(),
- *Functions(index_path, 'functions', 'Functions').fetch(),
*Graphics(index_path, 'graphics', 'Graphics').fetch(),
*GraphicsGpuTrace(index_path, 'graphics', 'GraphicsGpuTrace').fetch(),
*GraphicsDrmRelatedFtraceEvents(index_path, 'graphics',
'GraphicsDrmRelatedFtraceEvents').fetch(),
- *Ufs(index_path, 'ufs', 'Ufs').fetch(),
*LinuxSysfsPower(index_path, 'power', 'LinuxSysfsPower').fetch(),
- *Memory(index_path, 'memory', 'Memory').fetch(),
- *MemoryMetrics(index_path, 'memory', 'MemoryMetrics').fetch(),
- *Network(index_path, 'network', 'Network').fetch(),
- *Parsing(index_path, 'parsing', 'Parsing').fetch(),
- *ParsingDebugAnnotation(index_path, 'parsing',
- 'ParsingDebugAnnotation').fetch(),
- *ParsingRssStats(index_path, 'parsing', 'ParsingRssStats').fetch(),
- *ParsingMemoryCounters(index_path, 'parsing',
- 'ParsingMemoryCounters').fetch(),
- *PerfettoSql(index_path, 'perfetto_sql', 'PerfettoSql').fetch(),
- *Performance(index_path, 'performance', 'Performance').fetch(),
- *Pkvm(index_path, 'pkvm', 'Pkvm').fetch(),
*Power(index_path, 'power', 'Power').fetch(),
*PowerPowerRails(index_path, 'power', 'PowerPowerRails').fetch(),
*PowerVoltageAndScaling(index_path, 'power',
'PowerVoltageAndScaling').fetch(),
*PowerEnergyBreakdown(index_path, 'power',
'PowerEnergyBreakdown').fetch(),
- *ProcessTracking(index_path, 'process_tracking',
- 'ProcessTracking').fetch(),
- *Profiling(index_path, 'profiling', 'Profiling').fetch(),
- *ProfilingHeapProfiling(index_path, 'profiling',
- 'ProfilingHeapProfiling').fetch(),
- *ProfilingHeapGraph(index_path, 'profiling',
- 'ProfilingHeapGraph').fetch(),
- *ProfilingMetrics(index_path, 'profiling', 'ProfilingMetrics').fetch(),
- *ProfilingLlvmSymbolizer(index_path, 'profiling',
- 'ProfilingLlvmSymbolizer').fetch(),
- *Scheduler(index_path, 'scheduler', 'Scheduler').fetch(),
- *Slices(index_path, 'slices', 'Slices').fetch(),
- *Smoke(index_path, 'smoke', 'Smoke').fetch(),
- *SmokeComputeMetrics(index_path, 'smoke', 'SmokeComputeMetrics').fetch(),
- *SmokeJson(index_path, 'smoke', 'SmokeJson').fetch(),
- *SmokeSchedEvents(index_path, 'smoke', 'SmokeSchedEvents').fetch(),
- *SpanJoinLeftJoin(index_path, 'span_join', 'SpanJoinLeftJoin').fetch(),
- *SpanJoinOuterJoin(index_path, 'span_join', 'SpanJoinOuterJoin').fetch(),
- *SpanJoinSmoke(index_path, 'span_join', 'SpanJoinSmoke').fetch(),
- *SpanJoinRegression(index_path, 'span_join',
- 'SpanJoinRegression').fetch(),
- *Startup(index_path, 'startup', 'Startup').fetch(),
- *StartupBroadcasts(index_path, 'startup', 'StartupBroadcasts').fetch(),
- *StartupMetrics(index_path, 'startup', 'StartupMetrics').fetch(),
- *StartupLockContention(index_path, 'startup',
- 'StartupLockContention').fetch(),
*SurfaceFlingerLayers(index_path, 'android',
'SurfaceFlingerLayers').fetch(),
*SurfaceFlingerTransactions(index_path, 'android',
@@ -181,8 +210,4 @@
*Tables(index_path, 'tables', 'Tables').fetch(),
*TablesCounters(index_path, 'tables', 'TablesCounters').fetch(),
*TablesSched(index_path, 'tables', 'TablesSched').fetch(),
- *Time(index_path, 'time', 'Time').fetch(),
- *TrackEvent(index_path, 'track_event', 'TrackEvent').fetch(),
- *Translation(index_path, 'translation', 'Translation').fetch(),
- *WebView(index_path, 'webview', 'WebView').fetch(),
]
diff --git a/test/trace_processor/diff_tests/memory/tests_metrics.py b/test/trace_processor/diff_tests/memory/tests_metrics.py
deleted file mode 100644
index 8a45185..0000000
--- a/test/trace_processor/diff_tests/memory/tests_metrics.py
+++ /dev/null
@@ -1,112 +0,0 @@
-#!/usr/bin/env python3
-# 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 a
-#
-# 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.
-
-from python.generators.diff_tests.testing import Path, DataPath, Metric
-from python.generators.diff_tests.testing import Csv, Json, TextProto
-from python.generators.diff_tests.testing import DiffTestBlueprint
-from python.generators.diff_tests.testing import TestSuite
-
-
-class MemoryMetrics(TestSuite):
-
- def test_android_mem_counters(self):
- return DiffTestBlueprint(
- trace=DataPath('memory_counters.pb'),
- query=Metric('android_mem'),
- out=Path('android_mem_counters.out'))
-
- def test_trace_metadata(self):
- return DiffTestBlueprint(
- trace=DataPath('memory_counters.pb'),
- query=Metric('trace_metadata'),
- out=Path('trace_metadata.out'))
-
- def test_android_mem_by_priority(self):
- return DiffTestBlueprint(
- trace=Path('android_mem_by_priority.py'),
- query=Metric('android_mem'),
- out=Path('android_mem_by_priority.out'))
-
- def test_android_mem_lmk(self):
- return DiffTestBlueprint(
- trace=Path('android_systrace_lmk.py'),
- query=Metric('android_lmk'),
- out=TextProto(r"""
- android_lmk {
- total_count: 1
- by_oom_score {
- oom_score_adj: 900
- count: 1
- }
- oom_victim_count: 0
- }
- """))
-
- def test_android_lmk_oom(self):
- return DiffTestBlueprint(
- trace=TextProto(r"""
- packet {
- process_tree {
- processes {
- pid: 1000
- ppid: 1
- cmdline: "com.google.android.gm"
- }
- threads {
- tid: 1001
- tgid: 1000
- }
- }
- }
- packet {
- ftrace_events {
- cpu: 4
- event {
- timestamp: 1234
- pid: 4321
- mark_victim {
- pid: 1001
- }
- }
- }
- }
- """),
- query=Metric('android_lmk'),
- out=TextProto(r"""
- android_lmk {
- total_count: 0
- oom_victim_count: 1
- }
- """))
-
- def test_android_mem_delta(self):
- return DiffTestBlueprint(
- trace=Path('android_mem_delta.py'),
- query=Metric('android_mem'),
- out=TextProto(r"""
- android_mem {
- process_metrics {
- process_name: "com.my.pkg"
- total_counters {
- file_rss {
- min: 2000.0
- max: 10000.0
- avg: 6666.666666666667
- delta: 7000.0
- }
- }
- }
- }
- """))
diff --git a/test/trace_processor/diff_tests/camera/camera-ion-mem-trace_android_camera_unagg.out b/test/trace_processor/diff_tests/metrics/camera/camera-ion-mem-trace_android_camera_unagg.out
similarity index 100%
rename from test/trace_processor/diff_tests/camera/camera-ion-mem-trace_android_camera_unagg.out
rename to test/trace_processor/diff_tests/metrics/camera/camera-ion-mem-trace_android_camera_unagg.out
diff --git a/test/trace_processor/diff_tests/camera/tests.py b/test/trace_processor/diff_tests/metrics/camera/tests.py
similarity index 100%
rename from test/trace_processor/diff_tests/camera/tests.py
rename to test/trace_processor/diff_tests/metrics/camera/tests.py
diff --git a/test/trace_processor/diff_tests/codecs/codec-framedecoder-trace.out b/test/trace_processor/diff_tests/metrics/codecs/codec-framedecoder-trace.out
similarity index 100%
rename from test/trace_processor/diff_tests/codecs/codec-framedecoder-trace.out
rename to test/trace_processor/diff_tests/metrics/codecs/codec-framedecoder-trace.out
diff --git a/test/trace_processor/diff_tests/codecs/tests.py b/test/trace_processor/diff_tests/metrics/codecs/tests.py
similarity index 100%
rename from test/trace_processor/diff_tests/codecs/tests.py
rename to test/trace_processor/diff_tests/metrics/codecs/tests.py
diff --git a/test/trace_processor/diff_tests/performance/frame_timeline_metric.out b/test/trace_processor/diff_tests/metrics/frame_timeline/frame_timeline_metric.out
similarity index 100%
rename from test/trace_processor/diff_tests/performance/frame_timeline_metric.out
rename to test/trace_processor/diff_tests/metrics/frame_timeline/frame_timeline_metric.out
diff --git a/test/trace_processor/diff_tests/performance/frame_timeline_metric.py b/test/trace_processor/diff_tests/metrics/frame_timeline/frame_timeline_metric.py
similarity index 99%
rename from test/trace_processor/diff_tests/performance/frame_timeline_metric.py
rename to test/trace_processor/diff_tests/metrics/frame_timeline/frame_timeline_metric.py
index 05cfee3..c7c1885 100755
--- a/test/trace_processor/diff_tests/performance/frame_timeline_metric.py
+++ b/test/trace_processor/diff_tests/metrics/frame_timeline/frame_timeline_metric.py
@@ -181,7 +181,6 @@
prediction_type=PredictionType.PREDICTION_VALID)
trace.add_frame_end_event(ts=14000000, cookie=25)
-
trace.add_actual_surface_frame_start_event(
ts=14500000,
cookie=30,
@@ -196,7 +195,6 @@
prediction_type=PredictionType.PREDICTION_VALID)
trace.add_frame_end_event(ts=15000000, cookie=30)
-
trace.add_actual_surface_frame_start_event(
ts=15500000,
cookie=35,
@@ -211,7 +209,6 @@
prediction_type=PredictionType.PREDICTION_VALID)
trace.add_frame_end_event(ts=16000000, cookie=35)
-
trace.add_actual_surface_frame_start_event(
ts=16500000,
cookie=40,
diff --git a/test/trace_processor/diff_tests/metrics/frame_timeline/tests.py b/test/trace_processor/diff_tests/metrics/frame_timeline/tests.py
new file mode 100644
index 0000000..24ef27a
--- /dev/null
+++ b/test/trace_processor/diff_tests/metrics/frame_timeline/tests.py
@@ -0,0 +1,28 @@
+#!/usr/bin/env python3
+# 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 a
+#
+# 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.
+
+from python.generators.diff_tests.testing import Path, DataPath, Metric
+from python.generators.diff_tests.testing import Csv, Json, TextProto
+from python.generators.diff_tests.testing import DiffTestBlueprint
+from python.generators.diff_tests.testing import TestSuite
+
+
+class FrameTimeline(TestSuite):
+ # frame_timeline_metric collects App_Deadline_Missed metrics
+ def test_frame_timeline_metric(self):
+ return DiffTestBlueprint(
+ trace=Path('frame_timeline_metric.py'),
+ query=Metric('android_frame_timeline_metric'),
+ out=Path('frame_timeline_metric.out'))
diff --git a/test/trace_processor/diff_tests/performance/irq_runtime_metric.out b/test/trace_processor/diff_tests/metrics/irq/irq_runtime_metric.out
similarity index 100%
rename from test/trace_processor/diff_tests/performance/irq_runtime_metric.out
rename to test/trace_processor/diff_tests/metrics/irq/irq_runtime_metric.out
diff --git a/test/trace_processor/diff_tests/performance/irq_runtime_metric.textproto b/test/trace_processor/diff_tests/metrics/irq/irq_runtime_metric.textproto
similarity index 100%
rename from test/trace_processor/diff_tests/performance/irq_runtime_metric.textproto
rename to test/trace_processor/diff_tests/metrics/irq/irq_runtime_metric.textproto
diff --git a/test/trace_processor/diff_tests/metrics/irq/tests.py b/test/trace_processor/diff_tests/metrics/irq/tests.py
new file mode 100644
index 0000000..f7b11fd
--- /dev/null
+++ b/test/trace_processor/diff_tests/metrics/irq/tests.py
@@ -0,0 +1,28 @@
+#!/usr/bin/env python3
+# 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 a
+#
+# 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.
+
+from python.generators.diff_tests.testing import Path, DataPath, Metric
+from python.generators.diff_tests.testing import Csv, Json, TextProto
+from python.generators.diff_tests.testing import DiffTestBlueprint
+from python.generators.diff_tests.testing import TestSuite
+
+
+class IRQ(TestSuite):
+ # IRQ max runtime and count over 1ms
+ def test_irq_runtime_metric(self):
+ return DiffTestBlueprint(
+ trace=Path('irq_runtime_metric.textproto'),
+ query=Metric('android_irq_runtime'),
+ out=Path('irq_runtime_metric.out'))
\ No newline at end of file
diff --git a/test/trace_processor/diff_tests/memory/android_ion.py b/test/trace_processor/diff_tests/metrics/memory/android_ion.py
similarity index 100%
rename from test/trace_processor/diff_tests/memory/android_ion.py
rename to test/trace_processor/diff_tests/metrics/memory/android_ion.py
diff --git a/test/trace_processor/diff_tests/memory/android_lmk_reason.out b/test/trace_processor/diff_tests/metrics/memory/android_lmk_reason.out
similarity index 100%
rename from test/trace_processor/diff_tests/memory/android_lmk_reason.out
rename to test/trace_processor/diff_tests/metrics/memory/android_lmk_reason.out
diff --git a/test/trace_processor/diff_tests/memory/android_mem_by_priority.out b/test/trace_processor/diff_tests/metrics/memory/android_mem_by_priority.out
similarity index 100%
rename from test/trace_processor/diff_tests/memory/android_mem_by_priority.out
rename to test/trace_processor/diff_tests/metrics/memory/android_mem_by_priority.out
diff --git a/test/trace_processor/diff_tests/memory/android_mem_by_priority.py b/test/trace_processor/diff_tests/metrics/memory/android_mem_by_priority.py
similarity index 100%
rename from test/trace_processor/diff_tests/memory/android_mem_by_priority.py
rename to test/trace_processor/diff_tests/metrics/memory/android_mem_by_priority.py
diff --git a/test/trace_processor/diff_tests/memory/android_mem_counters.out b/test/trace_processor/diff_tests/metrics/memory/android_mem_counters.out
similarity index 100%
rename from test/trace_processor/diff_tests/memory/android_mem_counters.out
rename to test/trace_processor/diff_tests/metrics/memory/android_mem_counters.out
diff --git a/test/trace_processor/diff_tests/memory/android_mem_delta.py b/test/trace_processor/diff_tests/metrics/memory/android_mem_delta.py
similarity index 100%
rename from test/trace_processor/diff_tests/memory/android_mem_delta.py
rename to test/trace_processor/diff_tests/metrics/memory/android_mem_delta.py
diff --git a/test/trace_processor/diff_tests/memory/android_systrace_lmk.py b/test/trace_processor/diff_tests/metrics/memory/android_systrace_lmk.py
similarity index 100%
rename from test/trace_processor/diff_tests/memory/android_systrace_lmk.py
rename to test/trace_processor/diff_tests/metrics/memory/android_systrace_lmk.py
diff --git a/test/trace_processor/diff_tests/memory/tests.py b/test/trace_processor/diff_tests/metrics/memory/tests.py
similarity index 78%
rename from test/trace_processor/diff_tests/memory/tests.py
rename to test/trace_processor/diff_tests/metrics/memory/tests.py
index aca4edf..7ea5fda 100644
--- a/test/trace_processor/diff_tests/memory/tests.py
+++ b/test/trace_processor/diff_tests/metrics/memory/tests.py
@@ -19,7 +19,7 @@
from python.generators.diff_tests.testing import TestSuite
-class Memory(TestSuite):
+class MemoryMetrics(TestSuite):
# Contains test for Android memory metrics. ION metric
def test_android_ion(self):
return DiffTestBlueprint(
@@ -132,48 +132,6 @@
}
"""))
- def test_android_dma_buffer_tracks(self):
- return DiffTestBlueprint(
- trace=TextProto(r"""
- packet {
- ftrace_events {
- cpu: 0
- event {
- timestamp: 100
- pid: 1
- dma_heap_stat {
- inode: 123
- len: 1024
- total_allocated: 2048
- }
- }
- }
- }
- packet {
- ftrace_events {
- cpu: 0
- event {
- timestamp: 200
- pid: 1
- dma_heap_stat {
- inode: 123
- len: -1024
- total_allocated: 1024
- }
- }
- }
- }
- """),
- query="""
- SELECT track.name, slice.ts, slice.dur, slice.name
- FROM slice JOIN track ON slice.track_id = track.id
- WHERE track.name = 'mem.dma_buffer';
- """,
- out=Csv("""
- "name","ts","dur","name"
- "mem.dma_buffer",100,100,"1 kB"
- """))
-
# fastrpc metric
def test_android_fastrpc_dma_stat(self):
return DiffTestBlueprint(
@@ -220,55 +178,94 @@
}
"""))
- # shrink slab
- def test_shrink_slab(self):
+ def test_android_mem_counters(self):
+ return DiffTestBlueprint(
+ trace=DataPath('memory_counters.pb'),
+ query=Metric('android_mem'),
+ out=Path('android_mem_counters.out'))
+
+ def test_trace_metadata(self):
+ return DiffTestBlueprint(
+ trace=DataPath('memory_counters.pb'),
+ query=Metric('trace_metadata'),
+ out=Path('trace_metadata.out'))
+
+ def test_android_mem_by_priority(self):
+ return DiffTestBlueprint(
+ trace=Path('android_mem_by_priority.py'),
+ query=Metric('android_mem'),
+ out=Path('android_mem_by_priority.out'))
+
+ def test_android_mem_lmk(self):
+ return DiffTestBlueprint(
+ trace=Path('android_systrace_lmk.py'),
+ query=Metric('android_lmk'),
+ out=TextProto(r"""
+ android_lmk {
+ total_count: 1
+ by_oom_score {
+ oom_score_adj: 900
+ count: 1
+ }
+ oom_victim_count: 0
+ }
+ """))
+
+ def test_android_lmk_oom(self):
return DiffTestBlueprint(
trace=TextProto(r"""
packet {
- ftrace_events {
- cpu: 7
- event {
- timestamp: 36448185787847
- pid: 156
- mm_shrink_slab_start {
- cache_items: 1
- delta: 0
- gfp_flags: 3264
- nr_objects_to_shrink: 0
- shr: 18446743882920355600
- shrink: 90
- total_scan: 0
- nid: 0
- priority: 12
- }
+ process_tree {
+ processes {
+ pid: 1000
+ ppid: 1
+ cmdline: "com.google.android.gm"
+ }
+ threads {
+ tid: 1001
+ tgid: 1000
}
}
}
packet {
ftrace_events {
- cpu: 7
+ cpu: 4
event {
- timestamp: 36448185788539
- pid: 156
- mm_shrink_slab_end {
- new_scan: 0
- retval: 0
- shr: 18446743882920355600
- shrink: 90
- total_scan: 0
- unused_scan: 0
- nid: 0
+ timestamp: 1234
+ pid: 4321
+ mark_victim {
+ pid: 1001
}
}
}
}
"""),
- query="""
- SELECT ts, dur, name FROM slice WHERE name = 'mm_vmscan_shrink_slab';
- """,
- out=Csv("""
- "ts","dur","name"
- 36448185787847,692,"mm_vmscan_shrink_slab"
+ query=Metric('android_lmk'),
+ out=TextProto(r"""
+ android_lmk {
+ total_count: 0
+ oom_victim_count: 1
+ }
+ """))
+
+ def test_android_mem_delta(self):
+ return DiffTestBlueprint(
+ trace=Path('android_mem_delta.py'),
+ query=Metric('android_mem'),
+ out=TextProto(r"""
+ android_mem {
+ process_metrics {
+ process_name: "com.my.pkg"
+ total_counters {
+ file_rss {
+ min: 2000.0
+ max: 10000.0
+ avg: 6666.666666666667
+ delta: 7000.0
+ }
+ }
+ }
+ }
"""))
# cma alloc
@@ -321,3 +318,45 @@
"ts","dur","name"
74288080958099,110151652,"mm_cma_alloc"
"""))
+
+ def test_android_dma_buffer_tracks(self):
+ return DiffTestBlueprint(
+ trace=TextProto(r"""
+ packet {
+ ftrace_events {
+ cpu: 0
+ event {
+ timestamp: 100
+ pid: 1
+ dma_heap_stat {
+ inode: 123
+ len: 1024
+ total_allocated: 2048
+ }
+ }
+ }
+ }
+ packet {
+ ftrace_events {
+ cpu: 0
+ event {
+ timestamp: 200
+ pid: 1
+ dma_heap_stat {
+ inode: 123
+ len: -1024
+ total_allocated: 1024
+ }
+ }
+ }
+ }
+ """),
+ query="""
+ SELECT track.name, slice.ts, slice.dur, slice.name
+ FROM slice JOIN track ON slice.track_id = track.id
+ WHERE track.name = 'mem.dma_buffer';
+ """,
+ out=Csv("""
+ "name","ts","dur","name"
+ "mem.dma_buffer",100,100,"1 kB"
+ """))
diff --git a/test/trace_processor/diff_tests/memory/trace_metadata.out b/test/trace_processor/diff_tests/metrics/memory/trace_metadata.out
similarity index 100%
rename from test/trace_processor/diff_tests/memory/trace_metadata.out
rename to test/trace_processor/diff_tests/metrics/memory/trace_metadata.out
diff --git a/test/trace_processor/diff_tests/network/netperf_metric.out b/test/trace_processor/diff_tests/metrics/network/netperf_metric.out
similarity index 100%
rename from test/trace_processor/diff_tests/network/netperf_metric.out
rename to test/trace_processor/diff_tests/metrics/network/netperf_metric.out
diff --git a/test/trace_processor/diff_tests/network/netperf_metric.textproto b/test/trace_processor/diff_tests/metrics/network/netperf_metric.textproto
similarity index 100%
rename from test/trace_processor/diff_tests/network/netperf_metric.textproto
rename to test/trace_processor/diff_tests/metrics/network/netperf_metric.textproto
diff --git a/test/trace_processor/diff_tests/metrics/network/tests.py b/test/trace_processor/diff_tests/metrics/network/tests.py
new file mode 100644
index 0000000..d59879f
--- /dev/null
+++ b/test/trace_processor/diff_tests/metrics/network/tests.py
@@ -0,0 +1,27 @@
+#!/usr/bin/env python3
+# 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 a
+#
+# 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.
+
+from python.generators.diff_tests.testing import Path, Metric
+from python.generators.diff_tests.testing import DiffTestBlueprint
+from python.generators.diff_tests.testing import TestSuite
+
+
+class NetworkMetrics(TestSuite):
+
+ def test_netperf_metric(self):
+ return DiffTestBlueprint(
+ trace=Path('netperf_metric.textproto'),
+ query=Metric('android_netperf'),
+ out=Path('netperf_metric.out'))
diff --git a/test/trace_processor/diff_tests/profiling/heap_graph.textproto b/test/trace_processor/diff_tests/metrics/profiling/heap_graph.textproto
similarity index 100%
rename from test/trace_processor/diff_tests/profiling/heap_graph.textproto
rename to test/trace_processor/diff_tests/metrics/profiling/heap_graph.textproto
diff --git a/test/trace_processor/diff_tests/profiling/heap_graph_closest_proc.textproto b/test/trace_processor/diff_tests/metrics/profiling/heap_graph_closest_proc.textproto
similarity index 100%
rename from test/trace_processor/diff_tests/profiling/heap_graph_closest_proc.textproto
rename to test/trace_processor/diff_tests/metrics/profiling/heap_graph_closest_proc.textproto
diff --git a/test/trace_processor/diff_tests/profiling/heap_profile_no_symbols.textproto b/test/trace_processor/diff_tests/metrics/profiling/heap_profile_no_symbols.textproto
similarity index 100%
rename from test/trace_processor/diff_tests/profiling/heap_profile_no_symbols.textproto
rename to test/trace_processor/diff_tests/metrics/profiling/heap_profile_no_symbols.textproto
diff --git a/test/trace_processor/diff_tests/profiling/heap_stats_closest_proc.out b/test/trace_processor/diff_tests/metrics/profiling/heap_stats_closest_proc.out
similarity index 100%
rename from test/trace_processor/diff_tests/profiling/heap_stats_closest_proc.out
rename to test/trace_processor/diff_tests/metrics/profiling/heap_stats_closest_proc.out
diff --git a/test/trace_processor/diff_tests/profiling/java_heap_histogram.out b/test/trace_processor/diff_tests/metrics/profiling/java_heap_histogram.out
similarity index 100%
rename from test/trace_processor/diff_tests/profiling/java_heap_histogram.out
rename to test/trace_processor/diff_tests/metrics/profiling/java_heap_histogram.out
diff --git a/test/trace_processor/diff_tests/profiling/simpleperf_event.out b/test/trace_processor/diff_tests/metrics/profiling/simpleperf_event.out
similarity index 100%
rename from test/trace_processor/diff_tests/profiling/simpleperf_event.out
rename to test/trace_processor/diff_tests/metrics/profiling/simpleperf_event.out
diff --git a/test/trace_processor/diff_tests/profiling/simpleperf_event.py b/test/trace_processor/diff_tests/metrics/profiling/simpleperf_event.py
similarity index 100%
rename from test/trace_processor/diff_tests/profiling/simpleperf_event.py
rename to test/trace_processor/diff_tests/metrics/profiling/simpleperf_event.py
diff --git a/test/trace_processor/diff_tests/profiling/tests_metrics.py b/test/trace_processor/diff_tests/metrics/profiling/tests.py
similarity index 100%
rename from test/trace_processor/diff_tests/profiling/tests_metrics.py
rename to test/trace_processor/diff_tests/metrics/profiling/tests.py
diff --git a/test/trace_processor/diff_tests/startup/android_startup.out b/test/trace_processor/diff_tests/metrics/startup/android_startup.out
similarity index 100%
rename from test/trace_processor/diff_tests/startup/android_startup.out
rename to test/trace_processor/diff_tests/metrics/startup/android_startup.out
diff --git a/test/trace_processor/diff_tests/startup/android_startup.py b/test/trace_processor/diff_tests/metrics/startup/android_startup.py
similarity index 100%
rename from test/trace_processor/diff_tests/startup/android_startup.py
rename to test/trace_processor/diff_tests/metrics/startup/android_startup.py
diff --git a/test/trace_processor/diff_tests/startup/android_startup_attribution.out b/test/trace_processor/diff_tests/metrics/startup/android_startup_attribution.out
similarity index 100%
rename from test/trace_processor/diff_tests/startup/android_startup_attribution.out
rename to test/trace_processor/diff_tests/metrics/startup/android_startup_attribution.out
diff --git a/test/trace_processor/diff_tests/startup/android_startup_attribution.py b/test/trace_processor/diff_tests/metrics/startup/android_startup_attribution.py
similarity index 98%
rename from test/trace_processor/diff_tests/startup/android_startup_attribution.py
rename to test/trace_processor/diff_tests/metrics/startup/android_startup_attribution.py
index 59301e0..a48edcc 100644
--- a/test/trace_processor/diff_tests/startup/android_startup_attribution.py
+++ b/test/trace_processor/diff_tests/metrics/startup/android_startup_attribution.py
@@ -78,7 +78,7 @@
trace.add_atrace_begin(
ts=170, pid=APP_PID, tid=APP_TID, buf='OpenDexFilesFromOat(something else)')
-trace.add_atrace_end(ts=5*10**8, pid=APP_PID, tid=APP_TID)
+trace.add_atrace_end(ts=5 * 10**8, pid=APP_PID, tid=APP_TID)
# OpenDex slice outside the startup.
trace.add_atrace_begin(
diff --git a/test/trace_processor/diff_tests/startup/android_startup_attribution_slow.out b/test/trace_processor/diff_tests/metrics/startup/android_startup_attribution_slow.out
similarity index 100%
rename from test/trace_processor/diff_tests/startup/android_startup_attribution_slow.out
rename to test/trace_processor/diff_tests/metrics/startup/android_startup_attribution_slow.out
diff --git a/test/trace_processor/diff_tests/startup/android_startup_attribution_slow.py b/test/trace_processor/diff_tests/metrics/startup/android_startup_attribution_slow.py
similarity index 100%
rename from test/trace_processor/diff_tests/startup/android_startup_attribution_slow.py
rename to test/trace_processor/diff_tests/metrics/startup/android_startup_attribution_slow.py
diff --git a/test/trace_processor/diff_tests/startup/android_startup_battery.py b/test/trace_processor/diff_tests/metrics/startup/android_startup_battery.py
similarity index 100%
rename from test/trace_processor/diff_tests/startup/android_startup_battery.py
rename to test/trace_processor/diff_tests/metrics/startup/android_startup_battery.py
diff --git a/test/trace_processor/diff_tests/startup/android_startup_breakdown.out b/test/trace_processor/diff_tests/metrics/startup/android_startup_breakdown.out
similarity index 100%
rename from test/trace_processor/diff_tests/startup/android_startup_breakdown.out
rename to test/trace_processor/diff_tests/metrics/startup/android_startup_breakdown.out
diff --git a/test/trace_processor/diff_tests/startup/android_startup_breakdown.py b/test/trace_processor/diff_tests/metrics/startup/android_startup_breakdown.py
similarity index 100%
rename from test/trace_processor/diff_tests/startup/android_startup_breakdown.py
rename to test/trace_processor/diff_tests/metrics/startup/android_startup_breakdown.py
diff --git a/test/trace_processor/diff_tests/startup/android_startup_breakdown_slow.out b/test/trace_processor/diff_tests/metrics/startup/android_startup_breakdown_slow.out
similarity index 100%
rename from test/trace_processor/diff_tests/startup/android_startup_breakdown_slow.out
rename to test/trace_processor/diff_tests/metrics/startup/android_startup_breakdown_slow.out
diff --git a/test/trace_processor/diff_tests/startup/android_startup_breakdown_slow.py b/test/trace_processor/diff_tests/metrics/startup/android_startup_breakdown_slow.py
similarity index 97%
rename from test/trace_processor/diff_tests/startup/android_startup_breakdown_slow.py
rename to test/trace_processor/diff_tests/metrics/startup/android_startup_breakdown_slow.py
index f4ea962..b8f473f 100644
--- a/test/trace_processor/diff_tests/startup/android_startup_breakdown_slow.py
+++ b/test/trace_processor/diff_tests/metrics/startup/android_startup_breakdown_slow.py
@@ -29,7 +29,10 @@
trace.add_process(3, 1, 'com.google.android.calendar', uid=10001)
trace.add_package_list(
- ts=to_s(100), name='com.google.android.calendar', uid=10001, version_code=123)
+ ts=to_s(100),
+ name='com.google.android.calendar',
+ uid=10001,
+ version_code=123)
trace.add_ftrace_packet(cpu=0)
diff --git a/test/trace_processor/diff_tests/startup/android_startup_broadcast.out b/test/trace_processor/diff_tests/metrics/startup/android_startup_broadcast.out
similarity index 100%
rename from test/trace_processor/diff_tests/startup/android_startup_broadcast.out
rename to test/trace_processor/diff_tests/metrics/startup/android_startup_broadcast.out
diff --git a/test/trace_processor/diff_tests/startup/android_startup_broadcast.py b/test/trace_processor/diff_tests/metrics/startup/android_startup_broadcast.py
similarity index 100%
rename from test/trace_processor/diff_tests/startup/android_startup_broadcast.py
rename to test/trace_processor/diff_tests/metrics/startup/android_startup_broadcast.py
diff --git a/test/trace_processor/diff_tests/startup/android_startup_broadcast_multiple.out b/test/trace_processor/diff_tests/metrics/startup/android_startup_broadcast_multiple.out
similarity index 100%
rename from test/trace_processor/diff_tests/startup/android_startup_broadcast_multiple.out
rename to test/trace_processor/diff_tests/metrics/startup/android_startup_broadcast_multiple.out
diff --git a/test/trace_processor/diff_tests/startup/android_startup_broadcast_multiple.py b/test/trace_processor/diff_tests/metrics/startup/android_startup_broadcast_multiple.py
similarity index 100%
rename from test/trace_processor/diff_tests/startup/android_startup_broadcast_multiple.py
rename to test/trace_processor/diff_tests/metrics/startup/android_startup_broadcast_multiple.py
diff --git a/test/trace_processor/diff_tests/startup/android_startup_cpu.out b/test/trace_processor/diff_tests/metrics/startup/android_startup_cpu.out
similarity index 100%
rename from test/trace_processor/diff_tests/startup/android_startup_cpu.out
rename to test/trace_processor/diff_tests/metrics/startup/android_startup_cpu.out
diff --git a/test/trace_processor/diff_tests/startup/android_startup_cpu.py b/test/trace_processor/diff_tests/metrics/startup/android_startup_cpu.py
similarity index 100%
rename from test/trace_processor/diff_tests/startup/android_startup_cpu.py
rename to test/trace_processor/diff_tests/metrics/startup/android_startup_cpu.py
diff --git a/test/trace_processor/diff_tests/startup/android_startup_installd_dex2oat.out b/test/trace_processor/diff_tests/metrics/startup/android_startup_installd_dex2oat.out
similarity index 100%
rename from test/trace_processor/diff_tests/startup/android_startup_installd_dex2oat.out
rename to test/trace_processor/diff_tests/metrics/startup/android_startup_installd_dex2oat.out
diff --git a/test/trace_processor/diff_tests/startup/android_startup_installd_dex2oat.py b/test/trace_processor/diff_tests/metrics/startup/android_startup_installd_dex2oat.py
similarity index 100%
rename from test/trace_processor/diff_tests/startup/android_startup_installd_dex2oat.py
rename to test/trace_processor/diff_tests/metrics/startup/android_startup_installd_dex2oat.py
diff --git a/test/trace_processor/diff_tests/startup/android_startup_installd_dex2oat_slow.out b/test/trace_processor/diff_tests/metrics/startup/android_startup_installd_dex2oat_slow.out
similarity index 100%
rename from test/trace_processor/diff_tests/startup/android_startup_installd_dex2oat_slow.out
rename to test/trace_processor/diff_tests/metrics/startup/android_startup_installd_dex2oat_slow.out
diff --git a/test/trace_processor/diff_tests/startup/android_startup_installd_dex2oat_slow.py b/test/trace_processor/diff_tests/metrics/startup/android_startup_installd_dex2oat_slow.py
similarity index 100%
rename from test/trace_processor/diff_tests/startup/android_startup_installd_dex2oat_slow.py
rename to test/trace_processor/diff_tests/metrics/startup/android_startup_installd_dex2oat_slow.py
diff --git a/test/trace_processor/diff_tests/startup/android_startup_lock_contention.out b/test/trace_processor/diff_tests/metrics/startup/android_startup_lock_contention.out
similarity index 100%
rename from test/trace_processor/diff_tests/startup/android_startup_lock_contention.out
rename to test/trace_processor/diff_tests/metrics/startup/android_startup_lock_contention.out
diff --git a/test/trace_processor/diff_tests/startup/android_startup_lock_contention.py b/test/trace_processor/diff_tests/metrics/startup/android_startup_lock_contention.py
similarity index 100%
rename from test/trace_processor/diff_tests/startup/android_startup_lock_contention.py
rename to test/trace_processor/diff_tests/metrics/startup/android_startup_lock_contention.py
diff --git a/test/trace_processor/diff_tests/startup/android_startup_lock_contention_slow.out b/test/trace_processor/diff_tests/metrics/startup/android_startup_lock_contention_slow.out
similarity index 100%
rename from test/trace_processor/diff_tests/startup/android_startup_lock_contention_slow.out
rename to test/trace_processor/diff_tests/metrics/startup/android_startup_lock_contention_slow.out
diff --git a/test/trace_processor/diff_tests/startup/android_startup_lock_contention_slow.py b/test/trace_processor/diff_tests/metrics/startup/android_startup_lock_contention_slow.py
similarity index 100%
rename from test/trace_processor/diff_tests/startup/android_startup_lock_contention_slow.py
rename to test/trace_processor/diff_tests/metrics/startup/android_startup_lock_contention_slow.py
diff --git a/test/trace_processor/diff_tests/startup/android_startup_minsdk33.out b/test/trace_processor/diff_tests/metrics/startup/android_startup_minsdk33.out
similarity index 100%
rename from test/trace_processor/diff_tests/startup/android_startup_minsdk33.out
rename to test/trace_processor/diff_tests/metrics/startup/android_startup_minsdk33.out
diff --git a/test/trace_processor/diff_tests/startup/android_startup_minsdk33.py b/test/trace_processor/diff_tests/metrics/startup/android_startup_minsdk33.py
similarity index 100%
rename from test/trace_processor/diff_tests/startup/android_startup_minsdk33.py
rename to test/trace_processor/diff_tests/metrics/startup/android_startup_minsdk33.py
diff --git a/test/trace_processor/diff_tests/startup/android_startup_powrails.out b/test/trace_processor/diff_tests/metrics/startup/android_startup_powrails.out
similarity index 100%
rename from test/trace_processor/diff_tests/startup/android_startup_powrails.out
rename to test/trace_processor/diff_tests/metrics/startup/android_startup_powrails.out
diff --git a/test/trace_processor/diff_tests/startup/android_startup_powrails.py b/test/trace_processor/diff_tests/metrics/startup/android_startup_powrails.py
similarity index 100%
rename from test/trace_processor/diff_tests/startup/android_startup_powrails.py
rename to test/trace_processor/diff_tests/metrics/startup/android_startup_powrails.py
diff --git a/test/trace_processor/diff_tests/startup/android_startup_process_track.out b/test/trace_processor/diff_tests/metrics/startup/android_startup_process_track.out
similarity index 100%
rename from test/trace_processor/diff_tests/startup/android_startup_process_track.out
rename to test/trace_processor/diff_tests/metrics/startup/android_startup_process_track.out
diff --git a/test/trace_processor/diff_tests/startup/android_startup_process_track.py b/test/trace_processor/diff_tests/metrics/startup/android_startup_process_track.py
similarity index 100%
rename from test/trace_processor/diff_tests/startup/android_startup_process_track.py
rename to test/trace_processor/diff_tests/metrics/startup/android_startup_process_track.py
diff --git a/test/trace_processor/diff_tests/startup/android_startup_slow.out b/test/trace_processor/diff_tests/metrics/startup/android_startup_slow.out
similarity index 100%
rename from test/trace_processor/diff_tests/startup/android_startup_slow.out
rename to test/trace_processor/diff_tests/metrics/startup/android_startup_slow.out
diff --git a/test/trace_processor/diff_tests/startup/android_startup_slow.py b/test/trace_processor/diff_tests/metrics/startup/android_startup_slow.py
similarity index 100%
rename from test/trace_processor/diff_tests/startup/android_startup_slow.py
rename to test/trace_processor/diff_tests/metrics/startup/android_startup_slow.py
diff --git a/test/trace_processor/diff_tests/startup/android_startup_unlock.out b/test/trace_processor/diff_tests/metrics/startup/android_startup_unlock.out
similarity index 100%
rename from test/trace_processor/diff_tests/startup/android_startup_unlock.out
rename to test/trace_processor/diff_tests/metrics/startup/android_startup_unlock.out
diff --git a/test/trace_processor/diff_tests/startup/android_startup_unlock.py b/test/trace_processor/diff_tests/metrics/startup/android_startup_unlock.py
similarity index 100%
rename from test/trace_processor/diff_tests/startup/android_startup_unlock.py
rename to test/trace_processor/diff_tests/metrics/startup/android_startup_unlock.py
diff --git a/test/trace_processor/diff_tests/startup/tests.py b/test/trace_processor/diff_tests/metrics/startup/tests.py
similarity index 100%
rename from test/trace_processor/diff_tests/startup/tests.py
rename to test/trace_processor/diff_tests/metrics/startup/tests.py
diff --git a/test/trace_processor/diff_tests/startup/tests_broadcasts.py b/test/trace_processor/diff_tests/metrics/startup/tests_broadcasts.py
similarity index 100%
rename from test/trace_processor/diff_tests/startup/tests_broadcasts.py
rename to test/trace_processor/diff_tests/metrics/startup/tests_broadcasts.py
diff --git a/test/trace_processor/diff_tests/startup/tests_lock_contention.py b/test/trace_processor/diff_tests/metrics/startup/tests_lock_contention.py
similarity index 100%
rename from test/trace_processor/diff_tests/startup/tests_lock_contention.py
rename to test/trace_processor/diff_tests/metrics/startup/tests_lock_contention.py
diff --git a/test/trace_processor/diff_tests/startup/tests_metrics.py b/test/trace_processor/diff_tests/metrics/startup/tests_metrics.py
similarity index 100%
rename from test/trace_processor/diff_tests/startup/tests_metrics.py
rename to test/trace_processor/diff_tests/metrics/startup/tests_metrics.py
diff --git a/test/trace_processor/diff_tests/webview/tests.py b/test/trace_processor/diff_tests/metrics/webview/tests.py
similarity index 100%
rename from test/trace_processor/diff_tests/webview/tests.py
rename to test/trace_processor/diff_tests/metrics/webview/tests.py
diff --git a/test/trace_processor/diff_tests/android_fs/tests.py b/test/trace_processor/diff_tests/parser/android_fs/tests.py
similarity index 100%
rename from test/trace_processor/diff_tests/android_fs/tests.py
rename to test/trace_processor/diff_tests/parser/android_fs/tests.py
diff --git a/test/trace_processor/diff_tests/atrace/android_b2b_async_begin.textproto b/test/trace_processor/diff_tests/parser/atrace/android_b2b_async_begin.textproto
similarity index 100%
rename from test/trace_processor/diff_tests/atrace/android_b2b_async_begin.textproto
rename to test/trace_processor/diff_tests/parser/atrace/android_b2b_async_begin.textproto
diff --git a/test/trace_processor/diff_tests/atrace/async_track_atrace.py b/test/trace_processor/diff_tests/parser/atrace/async_track_atrace.py
similarity index 100%
rename from test/trace_processor/diff_tests/atrace/async_track_atrace.py
rename to test/trace_processor/diff_tests/parser/atrace/async_track_atrace.py
diff --git a/test/trace_processor/diff_tests/atrace/bad_print.systrace b/test/trace_processor/diff_tests/parser/atrace/bad_print.systrace
similarity index 100%
rename from test/trace_processor/diff_tests/atrace/bad_print.systrace
rename to test/trace_processor/diff_tests/parser/atrace/bad_print.systrace
diff --git a/test/trace_processor/diff_tests/atrace/bad_print.textproto b/test/trace_processor/diff_tests/parser/atrace/bad_print.textproto
similarity index 100%
rename from test/trace_processor/diff_tests/atrace/bad_print.textproto
rename to test/trace_processor/diff_tests/parser/atrace/bad_print.textproto
diff --git a/test/trace_processor/diff_tests/atrace/instant_async_atrace.py b/test/trace_processor/diff_tests/parser/atrace/instant_async_atrace.py
similarity index 100%
rename from test/trace_processor/diff_tests/atrace/instant_async_atrace.py
rename to test/trace_processor/diff_tests/parser/atrace/instant_async_atrace.py
diff --git a/test/trace_processor/diff_tests/atrace/instant_atrace.py b/test/trace_processor/diff_tests/parser/atrace/instant_atrace.py
similarity index 100%
rename from test/trace_processor/diff_tests/atrace/instant_atrace.py
rename to test/trace_processor/diff_tests/parser/atrace/instant_atrace.py
diff --git a/test/trace_processor/diff_tests/atrace/process_track_slices_android_async_slice.out b/test/trace_processor/diff_tests/parser/atrace/process_track_slices_android_async_slice.out
similarity index 100%
rename from test/trace_processor/diff_tests/atrace/process_track_slices_android_async_slice.out
rename to test/trace_processor/diff_tests/parser/atrace/process_track_slices_android_async_slice.out
diff --git a/test/trace_processor/diff_tests/atrace/sys_write_and_atrace.py b/test/trace_processor/diff_tests/parser/atrace/sys_write_and_atrace.py
similarity index 100%
rename from test/trace_processor/diff_tests/atrace/sys_write_and_atrace.py
rename to test/trace_processor/diff_tests/parser/atrace/sys_write_and_atrace.py
diff --git a/test/trace_processor/diff_tests/atrace/tests.py b/test/trace_processor/diff_tests/parser/atrace/tests.py
similarity index 100%
rename from test/trace_processor/diff_tests/atrace/tests.py
rename to test/trace_processor/diff_tests/parser/atrace/tests.py
diff --git a/test/trace_processor/diff_tests/atrace/tests_error_handling.py b/test/trace_processor/diff_tests/parser/atrace/tests_error_handling.py
similarity index 100%
rename from test/trace_processor/diff_tests/atrace/tests_error_handling.py
rename to test/trace_processor/diff_tests/parser/atrace/tests_error_handling.py
diff --git a/test/trace_processor/diff_tests/cros/cros_ec_sensorhub_data.out b/test/trace_processor/diff_tests/parser/cros/cros_ec_sensorhub_data.out
similarity index 100%
rename from test/trace_processor/diff_tests/cros/cros_ec_sensorhub_data.out
rename to test/trace_processor/diff_tests/parser/cros/cros_ec_sensorhub_data.out
diff --git a/test/trace_processor/diff_tests/cros/tests.py b/test/trace_processor/diff_tests/parser/cros/tests.py
similarity index 100%
rename from test/trace_processor/diff_tests/cros/tests.py
rename to test/trace_processor/diff_tests/parser/cros/tests.py
diff --git a/test/trace_processor/diff_tests/fs/f2fs_iostat.out b/test/trace_processor/diff_tests/parser/fs/f2fs_iostat.out
similarity index 100%
rename from test/trace_processor/diff_tests/fs/f2fs_iostat.out
rename to test/trace_processor/diff_tests/parser/fs/f2fs_iostat.out
diff --git a/test/trace_processor/diff_tests/fs/f2fs_iostat.textproto b/test/trace_processor/diff_tests/parser/fs/f2fs_iostat.textproto
similarity index 100%
rename from test/trace_processor/diff_tests/fs/f2fs_iostat.textproto
rename to test/trace_processor/diff_tests/parser/fs/f2fs_iostat.textproto
diff --git a/test/trace_processor/diff_tests/fs/f2fs_iostat_latency.out b/test/trace_processor/diff_tests/parser/fs/f2fs_iostat_latency.out
similarity index 100%
rename from test/trace_processor/diff_tests/fs/f2fs_iostat_latency.out
rename to test/trace_processor/diff_tests/parser/fs/f2fs_iostat_latency.out
diff --git a/test/trace_processor/diff_tests/fs/f2fs_iostat_latency.textproto b/test/trace_processor/diff_tests/parser/fs/f2fs_iostat_latency.textproto
similarity index 100%
rename from test/trace_processor/diff_tests/fs/f2fs_iostat_latency.textproto
rename to test/trace_processor/diff_tests/parser/fs/f2fs_iostat_latency.textproto
diff --git a/test/trace_processor/diff_tests/fs/tests.py b/test/trace_processor/diff_tests/parser/fs/tests.py
similarity index 100%
rename from test/trace_processor/diff_tests/fs/tests.py
rename to test/trace_processor/diff_tests/parser/fs/tests.py
diff --git a/test/trace_processor/diff_tests/fuchsia/fuchsia_workstation_smoke_slices.out b/test/trace_processor/diff_tests/parser/fuchsia/fuchsia_workstation_smoke_slices.out
similarity index 100%
rename from test/trace_processor/diff_tests/fuchsia/fuchsia_workstation_smoke_slices.out
rename to test/trace_processor/diff_tests/parser/fuchsia/fuchsia_workstation_smoke_slices.out
diff --git a/test/trace_processor/diff_tests/fuchsia/tests.py b/test/trace_processor/diff_tests/parser/fuchsia/tests.py
similarity index 100%
rename from test/trace_processor/diff_tests/fuchsia/tests.py
rename to test/trace_processor/diff_tests/parser/fuchsia/tests.py
diff --git a/test/trace_processor/diff_tests/parser/memory/tests.py b/test/trace_processor/diff_tests/parser/memory/tests.py
new file mode 100644
index 0000000..f7bdf1c
--- /dev/null
+++ b/test/trace_processor/diff_tests/parser/memory/tests.py
@@ -0,0 +1,113 @@
+#!/usr/bin/env python3
+# 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 a
+#
+# 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.
+
+from python.generators.diff_tests.testing import Csv, TextProto
+from python.generators.diff_tests.testing import DiffTestBlueprint
+from python.generators.diff_tests.testing import TestSuite
+
+
+class MemoryParser(TestSuite):
+ # cma alloc
+ def test_cma(self):
+ return DiffTestBlueprint(
+ trace=TextProto(r"""
+ packet {
+ system_info {
+ utsname {
+ sysname: "Linux"
+ release: "5.10.0"
+ }
+ }
+ }
+ packet {
+ ftrace_events {
+ cpu: 4
+ event {
+ timestamp: 74288080958099
+ pid: 537
+ cma_alloc_start {
+ align: 4
+ count: 6592
+ name: "farawimg"
+ }
+ }
+ event {
+ timestamp: 74288191109751
+ pid: 537
+ cma_alloc_info {
+ align: 4
+ count: 6592
+ err_iso: 0
+ err_mig: 0
+ err_test: 0
+ name: "farawimg"
+ nr_mapped: 832596
+ nr_migrated: 6365
+ nr_reclaimed: 7
+ pfn: 10365824
+ }
+ }
+ }
+ }
+ """),
+ query="""
+ SELECT ts, dur, name FROM slice WHERE name = 'mm_cma_alloc';
+ """,
+ out=Csv("""
+ "ts","dur","name"
+ 74288080958099,110151652,"mm_cma_alloc"
+ """))
+
+ def test_android_dma_buffer_tracks(self):
+ return DiffTestBlueprint(
+ trace=TextProto(r"""
+ packet {
+ ftrace_events {
+ cpu: 0
+ event {
+ timestamp: 100
+ pid: 1
+ dma_heap_stat {
+ inode: 123
+ len: 1024
+ total_allocated: 2048
+ }
+ }
+ }
+ }
+ packet {
+ ftrace_events {
+ cpu: 0
+ event {
+ timestamp: 200
+ pid: 1
+ dma_heap_stat {
+ inode: 123
+ len: -1024
+ total_allocated: 1024
+ }
+ }
+ }
+ }
+ """),
+ query="""
+ SELECT track.name, slice.ts, slice.dur, slice.name
+ FROM slice JOIN track ON slice.track_id = track.id
+ WHERE track.name = 'mem.dma_buffer';
+ """,
+ out=Csv("""
+ "name","ts","dur","name"
+ "mem.dma_buffer",100,100,"1 kB"
+ """))
diff --git a/test/trace_processor/diff_tests/network/inet_sock_set_state.textproto b/test/trace_processor/diff_tests/parser/network/inet_sock_set_state.textproto
similarity index 100%
rename from test/trace_processor/diff_tests/network/inet_sock_set_state.textproto
rename to test/trace_processor/diff_tests/parser/network/inet_sock_set_state.textproto
diff --git a/test/trace_processor/diff_tests/network/napi_gro_receive.textproto b/test/trace_processor/diff_tests/parser/network/napi_gro_receive.textproto
similarity index 100%
rename from test/trace_processor/diff_tests/network/napi_gro_receive.textproto
rename to test/trace_processor/diff_tests/parser/network/napi_gro_receive.textproto
diff --git a/test/trace_processor/diff_tests/network/net_dev_xmit.textproto b/test/trace_processor/diff_tests/parser/network/net_dev_xmit.textproto
similarity index 100%
rename from test/trace_processor/diff_tests/network/net_dev_xmit.textproto
rename to test/trace_processor/diff_tests/parser/network/net_dev_xmit.textproto
diff --git a/test/trace_processor/diff_tests/network/netif_receive_skb.textproto b/test/trace_processor/diff_tests/parser/network/netif_receive_skb.textproto
similarity index 100%
rename from test/trace_processor/diff_tests/network/netif_receive_skb.textproto
rename to test/trace_processor/diff_tests/parser/network/netif_receive_skb.textproto
diff --git a/test/trace_processor/diff_tests/network/tests.py b/test/trace_processor/diff_tests/parser/network/tests.py
similarity index 94%
rename from test/trace_processor/diff_tests/network/tests.py
rename to test/trace_processor/diff_tests/parser/network/tests.py
index a8bdd72..76f2446 100644
--- a/test/trace_processor/diff_tests/network/tests.py
+++ b/test/trace_processor/diff_tests/parser/network/tests.py
@@ -13,13 +13,13 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-from python.generators.diff_tests.testing import Path, DataPath, Metric
-from python.generators.diff_tests.testing import Csv, Json, TextProto
+from python.generators.diff_tests.testing import Path, Metric
+from python.generators.diff_tests.testing import Csv, TextProto
from python.generators.diff_tests.testing import DiffTestBlueprint
from python.generators.diff_tests.testing import TestSuite
-class Network(TestSuite):
+class NetworkParser(TestSuite):
# Network performance
def test_netif_receive_skb(self):
return DiffTestBlueprint(
@@ -74,12 +74,6 @@
12000,"wlan0",4,1300
"""))
- def test_netperf_metric(self):
- return DiffTestBlueprint(
- trace=Path('netperf_metric.textproto'),
- query=Metric('android_netperf'),
- out=Path('netperf_metric.out'))
-
def test_inet_sock_set_state(self):
return DiffTestBlueprint(
trace=Path('inet_sock_set_state.textproto'),
diff --git a/test/trace_processor/diff_tests/parsing/all_atoms_test.sql b/test/trace_processor/diff_tests/parser/parsing/all_atoms_test.sql
similarity index 100%
rename from test/trace_processor/diff_tests/parsing/all_atoms_test.sql
rename to test/trace_processor/diff_tests/parser/parsing/all_atoms_test.sql
diff --git a/test/trace_processor/diff_tests/parsing/android_binder.py b/test/trace_processor/diff_tests/parser/parsing/android_binder.py
similarity index 100%
rename from test/trace_processor/diff_tests/parsing/android_binder.py
rename to test/trace_processor/diff_tests/parser/parsing/android_binder.py
diff --git a/test/trace_processor/diff_tests/parsing/android_log_counts_test.sql b/test/trace_processor/diff_tests/parser/parsing/android_log_counts_test.sql
similarity index 100%
rename from test/trace_processor/diff_tests/parsing/android_log_counts_test.sql
rename to test/trace_processor/diff_tests/parser/parsing/android_log_counts_test.sql
diff --git a/test/trace_processor/diff_tests/parsing/android_log_msgs.out b/test/trace_processor/diff_tests/parser/parsing/android_log_msgs.out
similarity index 100%
rename from test/trace_processor/diff_tests/parsing/android_log_msgs.out
rename to test/trace_processor/diff_tests/parser/parsing/android_log_msgs.out
diff --git a/test/trace_processor/diff_tests/parsing/android_log_msgs_test.sql b/test/trace_processor/diff_tests/parser/parsing/android_log_msgs_test.sql
similarity index 100%
rename from test/trace_processor/diff_tests/parsing/android_log_msgs_test.sql
rename to test/trace_processor/diff_tests/parser/parsing/android_log_msgs_test.sql
diff --git a/test/trace_processor/diff_tests/parsing/android_multiuser_switch.textproto b/test/trace_processor/diff_tests/parser/parsing/android_multiuser_switch.textproto
similarity index 100%
rename from test/trace_processor/diff_tests/parsing/android_multiuser_switch.textproto
rename to test/trace_processor/diff_tests/parser/parsing/android_multiuser_switch.textproto
diff --git a/test/trace_processor/diff_tests/parsing/android_package_list.py b/test/trace_processor/diff_tests/parser/parsing/android_package_list.py
similarity index 100%
rename from test/trace_processor/diff_tests/parsing/android_package_list.py
rename to test/trace_processor/diff_tests/parser/parsing/android_package_list.py
diff --git a/test/trace_processor/diff_tests/parsing/android_sched_and_ps_stats.out b/test/trace_processor/diff_tests/parser/parsing/android_sched_and_ps_stats.out
similarity index 100%
rename from test/trace_processor/diff_tests/parsing/android_sched_and_ps_stats.out
rename to test/trace_processor/diff_tests/parser/parsing/android_sched_and_ps_stats.out
diff --git a/test/trace_processor/diff_tests/parsing/args_string_filter_null_test.sql b/test/trace_processor/diff_tests/parser/parsing/args_string_filter_null_test.sql
similarity index 100%
rename from test/trace_processor/diff_tests/parsing/args_string_filter_null_test.sql
rename to test/trace_processor/diff_tests/parser/parsing/args_string_filter_null_test.sql
diff --git a/test/trace_processor/diff_tests/parsing/b120487929_test.sql b/test/trace_processor/diff_tests/parser/parsing/b120487929_test.sql
similarity index 100%
rename from test/trace_processor/diff_tests/parsing/b120487929_test.sql
rename to test/trace_processor/diff_tests/parser/parsing/b120487929_test.sql
diff --git a/test/trace_processor/diff_tests/parsing/cgroup_attach_task_post_s_print_systrace.out b/test/trace_processor/diff_tests/parser/parsing/cgroup_attach_task_post_s_print_systrace.out
similarity index 100%
rename from test/trace_processor/diff_tests/parsing/cgroup_attach_task_post_s_print_systrace.out
rename to test/trace_processor/diff_tests/parser/parsing/cgroup_attach_task_post_s_print_systrace.out
diff --git a/test/trace_processor/diff_tests/parsing/cgroup_attach_task_pre_s_print_systrace.out b/test/trace_processor/diff_tests/parser/parsing/cgroup_attach_task_pre_s_print_systrace.out
similarity index 100%
rename from test/trace_processor/diff_tests/parsing/cgroup_attach_task_pre_s_print_systrace.out
rename to test/trace_processor/diff_tests/parser/parsing/cgroup_attach_task_pre_s_print_systrace.out
diff --git a/test/trace_processor/diff_tests/parsing/chrome_metadata.out b/test/trace_processor/diff_tests/parser/parsing/chrome_metadata.out
similarity index 100%
rename from test/trace_processor/diff_tests/parsing/chrome_metadata.out
rename to test/trace_processor/diff_tests/parser/parsing/chrome_metadata.out
diff --git a/test/trace_processor/diff_tests/parsing/cpu_counters_b120487929.out b/test/trace_processor/diff_tests/parser/parsing/cpu_counters_b120487929.out
similarity index 100%
rename from test/trace_processor/diff_tests/parsing/cpu_counters_b120487929.out
rename to test/trace_processor/diff_tests/parser/parsing/cpu_counters_b120487929.out
diff --git a/test/trace_processor/diff_tests/parsing/cpu_freq.out b/test/trace_processor/diff_tests/parser/parsing/cpu_freq.out
similarity index 100%
rename from test/trace_processor/diff_tests/parsing/cpu_freq.out
rename to test/trace_processor/diff_tests/parser/parsing/cpu_freq.out
diff --git a/test/trace_processor/diff_tests/parsing/cpu_info.textproto b/test/trace_processor/diff_tests/parser/parsing/cpu_info.textproto
similarity index 100%
rename from test/trace_processor/diff_tests/parsing/cpu_info.textproto
rename to test/trace_processor/diff_tests/parser/parsing/cpu_info.textproto
diff --git a/test/trace_processor/diff_tests/parsing/flow_events_json_v1.json b/test/trace_processor/diff_tests/parser/parsing/flow_events_json_v1.json
similarity index 100%
rename from test/trace_processor/diff_tests/parsing/flow_events_json_v1.json
rename to test/trace_processor/diff_tests/parser/parsing/flow_events_json_v1.json
diff --git a/test/trace_processor/diff_tests/parsing/flow_events_json_v2.json b/test/trace_processor/diff_tests/parser/parsing/flow_events_json_v2.json
similarity index 100%
rename from test/trace_processor/diff_tests/parsing/flow_events_json_v2.json
rename to test/trace_processor/diff_tests/parser/parsing/flow_events_json_v2.json
diff --git a/test/trace_processor/diff_tests/parsing/ftrace_with_tracing_start.py b/test/trace_processor/diff_tests/parser/parsing/ftrace_with_tracing_start.py
similarity index 100%
rename from test/trace_processor/diff_tests/parsing/ftrace_with_tracing_start.py
rename to test/trace_processor/diff_tests/parser/parsing/ftrace_with_tracing_start.py
diff --git a/test/trace_processor/diff_tests/parsing/funcgraph_trace.textproto b/test/trace_processor/diff_tests/parser/parsing/funcgraph_trace.textproto
similarity index 100%
rename from test/trace_processor/diff_tests/parsing/funcgraph_trace.textproto
rename to test/trace_processor/diff_tests/parser/parsing/funcgraph_trace.textproto
diff --git a/test/trace_processor/diff_tests/parsing/kernel_dpu_tmw_counter_thread_counter_and_track.out b/test/trace_processor/diff_tests/parser/parsing/kernel_dpu_tmw_counter_thread_counter_and_track.out
similarity index 100%
rename from test/trace_processor/diff_tests/parsing/kernel_dpu_tmw_counter_thread_counter_and_track.out
rename to test/trace_processor/diff_tests/parser/parsing/kernel_dpu_tmw_counter_thread_counter_and_track.out
diff --git a/test/trace_processor/diff_tests/parsing/kernel_tmw_counter.textproto b/test/trace_processor/diff_tests/parser/parsing/kernel_tmw_counter.textproto
similarity index 100%
rename from test/trace_processor/diff_tests/parsing/kernel_tmw_counter.textproto
rename to test/trace_processor/diff_tests/parser/parsing/kernel_tmw_counter.textproto
diff --git a/test/trace_processor/diff_tests/parsing/kernel_tmw_counter_thread_counter_and_track.out b/test/trace_processor/diff_tests/parser/parsing/kernel_tmw_counter_thread_counter_and_track.out
similarity index 100%
rename from test/trace_processor/diff_tests/parsing/kernel_tmw_counter_thread_counter_and_track.out
rename to test/trace_processor/diff_tests/parser/parsing/kernel_tmw_counter_thread_counter_and_track.out
diff --git a/test/trace_processor/diff_tests/parsing/mm_event.out b/test/trace_processor/diff_tests/parser/parsing/mm_event.out
similarity index 100%
rename from test/trace_processor/diff_tests/parsing/mm_event.out
rename to test/trace_processor/diff_tests/parser/parsing/mm_event.out
diff --git a/test/trace_processor/diff_tests/parsing/oom_query_test.sql b/test/trace_processor/diff_tests/parser/parsing/oom_query_test.sql
similarity index 100%
rename from test/trace_processor/diff_tests/parsing/oom_query_test.sql
rename to test/trace_processor/diff_tests/parser/parsing/oom_query_test.sql
diff --git a/test/trace_processor/diff_tests/parsing/otheruuids.textproto b/test/trace_processor/diff_tests/parser/parsing/otheruuids.textproto
similarity index 100%
rename from test/trace_processor/diff_tests/parsing/otheruuids.textproto
rename to test/trace_processor/diff_tests/parser/parsing/otheruuids.textproto
diff --git a/test/trace_processor/diff_tests/parsing/print_systrace_lmk_userspace.out b/test/trace_processor/diff_tests/parser/parsing/print_systrace_lmk_userspace.out
similarity index 100%
rename from test/trace_processor/diff_tests/parsing/print_systrace_lmk_userspace.out
rename to test/trace_processor/diff_tests/parser/parsing/print_systrace_lmk_userspace.out
diff --git a/test/trace_processor/diff_tests/parsing/print_systrace_unsigned.out b/test/trace_processor/diff_tests/parser/parsing/print_systrace_unsigned.out
similarity index 100%
rename from test/trace_processor/diff_tests/parsing/print_systrace_unsigned.out
rename to test/trace_processor/diff_tests/parser/parsing/print_systrace_unsigned.out
diff --git a/test/trace_processor/diff_tests/parsing/print_systrace_unsigned.py b/test/trace_processor/diff_tests/parser/parsing/print_systrace_unsigned.py
similarity index 100%
rename from test/trace_processor/diff_tests/parsing/print_systrace_unsigned.py
rename to test/trace_processor/diff_tests/parser/parsing/print_systrace_unsigned.py
diff --git a/test/trace_processor/diff_tests/parsing/process_stats_poll_oom_score.out b/test/trace_processor/diff_tests/parser/parsing/process_stats_poll_oom_score.out
similarity index 100%
rename from test/trace_processor/diff_tests/parsing/process_stats_poll_oom_score.out
rename to test/trace_processor/diff_tests/parser/parsing/process_stats_poll_oom_score.out
diff --git a/test/trace_processor/diff_tests/parsing/rss_stat_after_free.py b/test/trace_processor/diff_tests/parser/parsing/rss_stat_after_free.py
similarity index 100%
rename from test/trace_processor/diff_tests/parsing/rss_stat_after_free.py
rename to test/trace_processor/diff_tests/parser/parsing/rss_stat_after_free.py
diff --git a/test/trace_processor/diff_tests/parsing/rss_stat_legacy.py b/test/trace_processor/diff_tests/parser/parsing/rss_stat_legacy.py
similarity index 100%
rename from test/trace_processor/diff_tests/parsing/rss_stat_legacy.py
rename to test/trace_processor/diff_tests/parser/parsing/rss_stat_legacy.py
diff --git a/test/trace_processor/diff_tests/parsing/rss_stat_mm_id.py b/test/trace_processor/diff_tests/parser/parsing/rss_stat_mm_id.py
similarity index 100%
rename from test/trace_processor/diff_tests/parsing/rss_stat_mm_id.py
rename to test/trace_processor/diff_tests/parser/parsing/rss_stat_mm_id.py
diff --git a/test/trace_processor/diff_tests/parsing/rss_stat_mm_id_clone.py b/test/trace_processor/diff_tests/parser/parsing/rss_stat_mm_id_clone.py
similarity index 100%
rename from test/trace_processor/diff_tests/parsing/rss_stat_mm_id_clone.py
rename to test/trace_processor/diff_tests/parser/parsing/rss_stat_mm_id_clone.py
diff --git a/test/trace_processor/diff_tests/parsing/rss_stat_mm_id_reuse.py b/test/trace_processor/diff_tests/parser/parsing/rss_stat_mm_id_reuse.py
similarity index 100%
rename from test/trace_processor/diff_tests/parsing/rss_stat_mm_id_reuse.py
rename to test/trace_processor/diff_tests/parser/parsing/rss_stat_mm_id_reuse.py
diff --git a/test/trace_processor/diff_tests/parsing/sched_blocked_proto.py b/test/trace_processor/diff_tests/parser/parsing/sched_blocked_proto.py
similarity index 100%
rename from test/trace_processor/diff_tests/parsing/sched_blocked_proto.py
rename to test/trace_processor/diff_tests/parser/parsing/sched_blocked_proto.py
diff --git a/test/trace_processor/diff_tests/parsing/sched_blocked_reason_symbolized.textproto b/test/trace_processor/diff_tests/parser/parsing/sched_blocked_reason_symbolized.textproto
similarity index 100%
rename from test/trace_processor/diff_tests/parsing/sched_blocked_reason_symbolized.textproto
rename to test/trace_processor/diff_tests/parser/parsing/sched_blocked_reason_symbolized.textproto
diff --git a/test/trace_processor/diff_tests/parsing/sched_blocked_reason_symbolized_to_systrace.out b/test/trace_processor/diff_tests/parser/parsing/sched_blocked_reason_symbolized_to_systrace.out
similarity index 100%
rename from test/trace_processor/diff_tests/parsing/sched_blocked_reason_symbolized_to_systrace.out
rename to test/trace_processor/diff_tests/parser/parsing/sched_blocked_reason_symbolized_to_systrace.out
diff --git a/test/trace_processor/diff_tests/parsing/sched_blocked_systrace.systrace b/test/trace_processor/diff_tests/parser/parsing/sched_blocked_systrace.systrace
similarity index 100%
rename from test/trace_processor/diff_tests/parsing/sched_blocked_systrace.systrace
rename to test/trace_processor/diff_tests/parser/parsing/sched_blocked_systrace.systrace
diff --git a/test/trace_processor/diff_tests/parsing/sched_slices_sched_switch_compact.out b/test/trace_processor/diff_tests/parser/parsing/sched_slices_sched_switch_compact.out
similarity index 100%
rename from test/trace_processor/diff_tests/parsing/sched_slices_sched_switch_compact.out
rename to test/trace_processor/diff_tests/parser/parsing/sched_slices_sched_switch_compact.out
diff --git a/test/trace_processor/diff_tests/parsing/sched_slices_sched_switch_original.out b/test/trace_processor/diff_tests/parser/parsing/sched_slices_sched_switch_original.out
similarity index 100%
rename from test/trace_processor/diff_tests/parsing/sched_slices_sched_switch_original.out
rename to test/trace_processor/diff_tests/parser/parsing/sched_slices_sched_switch_original.out
diff --git a/test/trace_processor/diff_tests/parsing/sched_waking_instants_compact_sched.out b/test/trace_processor/diff_tests/parser/parsing/sched_waking_instants_compact_sched.out
similarity index 100%
rename from test/trace_processor/diff_tests/parsing/sched_waking_instants_compact_sched.out
rename to test/trace_processor/diff_tests/parser/parsing/sched_waking_instants_compact_sched.out
diff --git a/test/trace_processor/diff_tests/parsing/sched_waking_raw_compact_sched.out b/test/trace_processor/diff_tests/parser/parsing/sched_waking_raw_compact_sched.out
similarity index 100%
rename from test/trace_processor/diff_tests/parsing/sched_waking_raw_compact_sched.out
rename to test/trace_processor/diff_tests/parser/parsing/sched_waking_raw_compact_sched.out
diff --git a/test/trace_processor/diff_tests/parsing/sched_waking_raw_test.sql b/test/trace_processor/diff_tests/parser/parsing/sched_waking_raw_test.sql
similarity index 100%
rename from test/trace_processor/diff_tests/parsing/sched_waking_raw_test.sql
rename to test/trace_processor/diff_tests/parser/parsing/sched_waking_raw_test.sql
diff --git a/test/trace_processor/diff_tests/parsing/statsd_atoms_all_atoms.out b/test/trace_processor/diff_tests/parser/parsing/statsd_atoms_all_atoms.out
similarity index 100%
rename from test/trace_processor/diff_tests/parsing/statsd_atoms_all_atoms.out
rename to test/trace_processor/diff_tests/parser/parsing/statsd_atoms_all_atoms.out
diff --git a/test/trace_processor/diff_tests/parsing/synth_oom.py b/test/trace_processor/diff_tests/parser/parsing/synth_oom.py
similarity index 100%
rename from test/trace_processor/diff_tests/parsing/synth_oom.py
rename to test/trace_processor/diff_tests/parser/parsing/synth_oom.py
diff --git a/test/trace_processor/diff_tests/parsing/synth_oom_oom_query.out b/test/trace_processor/diff_tests/parser/parsing/synth_oom_oom_query.out
similarity index 100%
rename from test/trace_processor/diff_tests/parsing/synth_oom_oom_query.out
rename to test/trace_processor/diff_tests/parser/parsing/synth_oom_oom_query.out
diff --git a/test/trace_processor/diff_tests/parsing/syscall.py b/test/trace_processor/diff_tests/parser/parsing/syscall.py
similarity index 100%
rename from test/trace_processor/diff_tests/parsing/syscall.py
rename to test/trace_processor/diff_tests/parser/parsing/syscall.py
diff --git a/test/trace_processor/diff_tests/parsing/systrace_html.out b/test/trace_processor/diff_tests/parser/parsing/systrace_html.out
similarity index 100%
rename from test/trace_processor/diff_tests/parsing/systrace_html.out
rename to test/trace_processor/diff_tests/parser/parsing/systrace_html.out
diff --git a/test/trace_processor/diff_tests/parsing/tests.py b/test/trace_processor/diff_tests/parser/parsing/tests.py
similarity index 100%
rename from test/trace_processor/diff_tests/parsing/tests.py
rename to test/trace_processor/diff_tests/parser/parsing/tests.py
diff --git a/test/trace_processor/diff_tests/parsing/tests_debug_annotation.py b/test/trace_processor/diff_tests/parser/parsing/tests_debug_annotation.py
similarity index 100%
rename from test/trace_processor/diff_tests/parsing/tests_debug_annotation.py
rename to test/trace_processor/diff_tests/parser/parsing/tests_debug_annotation.py
diff --git a/test/trace_processor/diff_tests/parsing/tests_memory_counters.py b/test/trace_processor/diff_tests/parser/parsing/tests_memory_counters.py
similarity index 100%
rename from test/trace_processor/diff_tests/parsing/tests_memory_counters.py
rename to test/trace_processor/diff_tests/parser/parsing/tests_memory_counters.py
diff --git a/test/trace_processor/diff_tests/parsing/tests_rss_stats.py b/test/trace_processor/diff_tests/parser/parsing/tests_rss_stats.py
similarity index 100%
rename from test/trace_processor/diff_tests/parsing/tests_rss_stats.py
rename to test/trace_processor/diff_tests/parser/parsing/tests_rss_stats.py
diff --git a/test/trace_processor/diff_tests/parsing/thread_counter_and_track_test.sql b/test/trace_processor/diff_tests/parser/parsing/thread_counter_and_track_test.sql
similarity index 100%
rename from test/trace_processor/diff_tests/parsing/thread_counter_and_track_test.sql
rename to test/trace_processor/diff_tests/parser/parsing/thread_counter_and_track_test.sql
diff --git a/test/trace_processor/diff_tests/parsing/thread_time_in_state.out b/test/trace_processor/diff_tests/parser/parsing/thread_time_in_state.out
similarity index 100%
rename from test/trace_processor/diff_tests/parsing/thread_time_in_state.out
rename to test/trace_processor/diff_tests/parser/parsing/thread_time_in_state.out
diff --git a/test/trace_processor/diff_tests/parsing/thread_time_in_state_event.out b/test/trace_processor/diff_tests/parser/parsing/thread_time_in_state_event.out
similarity index 100%
rename from test/trace_processor/diff_tests/parsing/thread_time_in_state_event.out
rename to test/trace_processor/diff_tests/parser/parsing/thread_time_in_state_event.out
diff --git a/test/trace_processor/diff_tests/parsing/thread_time_in_state_event.py b/test/trace_processor/diff_tests/parser/parsing/thread_time_in_state_event.py
similarity index 100%
rename from test/trace_processor/diff_tests/parsing/thread_time_in_state_event.py
rename to test/trace_processor/diff_tests/parser/parsing/thread_time_in_state_event.py
diff --git a/test/trace_processor/diff_tests/parsing/triggers_packets_test.sql b/test/trace_processor/diff_tests/parser/parsing/triggers_packets_test.sql
similarity index 100%
rename from test/trace_processor/diff_tests/parsing/triggers_packets_test.sql
rename to test/trace_processor/diff_tests/parser/parsing/triggers_packets_test.sql
diff --git a/test/trace_processor/diff_tests/parsing/very_long_sched.py b/test/trace_processor/diff_tests/parser/parsing/very_long_sched.py
similarity index 100%
rename from test/trace_processor/diff_tests/parsing/very_long_sched.py
rename to test/trace_processor/diff_tests/parser/parsing/very_long_sched.py
diff --git a/test/trace_processor/diff_tests/process_tracking/process_parent_pid_tracking_1.py b/test/trace_processor/diff_tests/parser/process_tracking/process_parent_pid_tracking_1.py
similarity index 100%
rename from test/trace_processor/diff_tests/process_tracking/process_parent_pid_tracking_1.py
rename to test/trace_processor/diff_tests/parser/process_tracking/process_parent_pid_tracking_1.py
diff --git a/test/trace_processor/diff_tests/process_tracking/process_parent_pid_tracking_2.py b/test/trace_processor/diff_tests/parser/process_tracking/process_parent_pid_tracking_2.py
similarity index 100%
rename from test/trace_processor/diff_tests/process_tracking/process_parent_pid_tracking_2.py
rename to test/trace_processor/diff_tests/parser/process_tracking/process_parent_pid_tracking_2.py
diff --git a/test/trace_processor/diff_tests/process_tracking/process_tracking_exec.py b/test/trace_processor/diff_tests/parser/process_tracking/process_tracking_exec.py
similarity index 100%
rename from test/trace_processor/diff_tests/process_tracking/process_tracking_exec.py
rename to test/trace_processor/diff_tests/parser/process_tracking/process_tracking_exec.py
diff --git a/test/trace_processor/diff_tests/process_tracking/process_tracking_short_lived_1.py b/test/trace_processor/diff_tests/parser/process_tracking/process_tracking_short_lived_1.py
similarity index 100%
rename from test/trace_processor/diff_tests/process_tracking/process_tracking_short_lived_1.py
rename to test/trace_processor/diff_tests/parser/process_tracking/process_tracking_short_lived_1.py
diff --git a/test/trace_processor/diff_tests/process_tracking/process_tracking_short_lived_2.py b/test/trace_processor/diff_tests/parser/process_tracking/process_tracking_short_lived_2.py
similarity index 100%
rename from test/trace_processor/diff_tests/process_tracking/process_tracking_short_lived_2.py
rename to test/trace_processor/diff_tests/parser/process_tracking/process_tracking_short_lived_2.py
diff --git a/test/trace_processor/diff_tests/process_tracking/reused_thread_print.py b/test/trace_processor/diff_tests/parser/process_tracking/reused_thread_print.py
similarity index 100%
rename from test/trace_processor/diff_tests/process_tracking/reused_thread_print.py
rename to test/trace_processor/diff_tests/parser/process_tracking/reused_thread_print.py
diff --git a/test/trace_processor/diff_tests/process_tracking/synth_process_tracking.py b/test/trace_processor/diff_tests/parser/process_tracking/synth_process_tracking.py
similarity index 100%
rename from test/trace_processor/diff_tests/process_tracking/synth_process_tracking.py
rename to test/trace_processor/diff_tests/parser/process_tracking/synth_process_tracking.py
diff --git a/test/trace_processor/diff_tests/process_tracking/tests.py b/test/trace_processor/diff_tests/parser/process_tracking/tests.py
similarity index 100%
rename from test/trace_processor/diff_tests/process_tracking/tests.py
rename to test/trace_processor/diff_tests/parser/process_tracking/tests.py
diff --git a/test/trace_processor/diff_tests/process_tracking/unknown_thread_name.systrace b/test/trace_processor/diff_tests/parser/process_tracking/unknown_thread_name.systrace
similarity index 100%
rename from test/trace_processor/diff_tests/process_tracking/unknown_thread_name.systrace
rename to test/trace_processor/diff_tests/parser/process_tracking/unknown_thread_name.systrace
diff --git a/test/trace_processor/diff_tests/profiling/callstack_sampling_flamegraph.out b/test/trace_processor/diff_tests/parser/profiling/callstack_sampling_flamegraph.out
similarity index 100%
rename from test/trace_processor/diff_tests/profiling/callstack_sampling_flamegraph.out
rename to test/trace_processor/diff_tests/parser/profiling/callstack_sampling_flamegraph.out
diff --git a/test/trace_processor/diff_tests/profiling/heap_graph.textproto b/test/trace_processor/diff_tests/parser/profiling/heap_graph.textproto
similarity index 100%
copy from test/trace_processor/diff_tests/profiling/heap_graph.textproto
copy to test/trace_processor/diff_tests/parser/profiling/heap_graph.textproto
diff --git a/test/trace_processor/diff_tests/profiling/heap_graph_baseapk.textproto b/test/trace_processor/diff_tests/parser/profiling/heap_graph_baseapk.textproto
similarity index 100%
rename from test/trace_processor/diff_tests/profiling/heap_graph_baseapk.textproto
rename to test/trace_processor/diff_tests/parser/profiling/heap_graph_baseapk.textproto
diff --git a/test/trace_processor/diff_tests/profiling/heap_graph_branching.textproto b/test/trace_processor/diff_tests/parser/profiling/heap_graph_branching.textproto
similarity index 100%
rename from test/trace_processor/diff_tests/profiling/heap_graph_branching.textproto
rename to test/trace_processor/diff_tests/parser/profiling/heap_graph_branching.textproto
diff --git a/test/trace_processor/diff_tests/profiling/heap_graph_deobfuscate_pkg.textproto b/test/trace_processor/diff_tests/parser/profiling/heap_graph_deobfuscate_pkg.textproto
similarity index 100%
rename from test/trace_processor/diff_tests/profiling/heap_graph_deobfuscate_pkg.textproto
rename to test/trace_processor/diff_tests/parser/profiling/heap_graph_deobfuscate_pkg.textproto
diff --git a/test/trace_processor/diff_tests/profiling/heap_graph_duplicate_flamegraph.out b/test/trace_processor/diff_tests/parser/profiling/heap_graph_duplicate_flamegraph.out
similarity index 100%
rename from test/trace_processor/diff_tests/profiling/heap_graph_duplicate_flamegraph.out
rename to test/trace_processor/diff_tests/parser/profiling/heap_graph_duplicate_flamegraph.out
diff --git a/test/trace_processor/diff_tests/profiling/heap_graph_flamegraph.out b/test/trace_processor/diff_tests/parser/profiling/heap_graph_flamegraph.out
similarity index 100%
rename from test/trace_processor/diff_tests/profiling/heap_graph_flamegraph.out
rename to test/trace_processor/diff_tests/parser/profiling/heap_graph_flamegraph.out
diff --git a/test/trace_processor/diff_tests/profiling/heap_graph_flamegraph_focused.out b/test/trace_processor/diff_tests/parser/profiling/heap_graph_flamegraph_focused.out
similarity index 100%
rename from test/trace_processor/diff_tests/profiling/heap_graph_flamegraph_focused.out
rename to test/trace_processor/diff_tests/parser/profiling/heap_graph_flamegraph_focused.out
diff --git a/test/trace_processor/diff_tests/profiling/heap_graph_flamegraph_system-server-heap-graph.out b/test/trace_processor/diff_tests/parser/profiling/heap_graph_flamegraph_system-server-heap-graph.out
similarity index 100%
rename from test/trace_processor/diff_tests/profiling/heap_graph_flamegraph_system-server-heap-graph.out
rename to test/trace_processor/diff_tests/parser/profiling/heap_graph_flamegraph_system-server-heap-graph.out
diff --git a/test/trace_processor/diff_tests/profiling/heap_graph_huge_size.textproto b/test/trace_processor/diff_tests/parser/profiling/heap_graph_huge_size.textproto
similarity index 100%
rename from test/trace_processor/diff_tests/profiling/heap_graph_huge_size.textproto
rename to test/trace_processor/diff_tests/parser/profiling/heap_graph_huge_size.textproto
diff --git a/test/trace_processor/diff_tests/profiling/heap_graph_interleaved.textproto b/test/trace_processor/diff_tests/parser/profiling/heap_graph_interleaved.textproto
similarity index 100%
rename from test/trace_processor/diff_tests/profiling/heap_graph_interleaved.textproto
rename to test/trace_processor/diff_tests/parser/profiling/heap_graph_interleaved.textproto
diff --git a/test/trace_processor/diff_tests/profiling/heap_graph_interleaved_object.out b/test/trace_processor/diff_tests/parser/profiling/heap_graph_interleaved_object.out
similarity index 100%
rename from test/trace_processor/diff_tests/profiling/heap_graph_interleaved_object.out
rename to test/trace_processor/diff_tests/parser/profiling/heap_graph_interleaved_object.out
diff --git a/test/trace_processor/diff_tests/profiling/heap_graph_interleaved_reference.out b/test/trace_processor/diff_tests/parser/profiling/heap_graph_interleaved_reference.out
similarity index 100%
rename from test/trace_processor/diff_tests/profiling/heap_graph_interleaved_reference.out
rename to test/trace_processor/diff_tests/parser/profiling/heap_graph_interleaved_reference.out
diff --git a/test/trace_processor/diff_tests/profiling/heap_graph_legacy.textproto b/test/trace_processor/diff_tests/parser/profiling/heap_graph_legacy.textproto
similarity index 100%
rename from test/trace_processor/diff_tests/profiling/heap_graph_legacy.textproto
rename to test/trace_processor/diff_tests/parser/profiling/heap_graph_legacy.textproto
diff --git a/test/trace_processor/diff_tests/profiling/heap_graph_native_size.textproto b/test/trace_processor/diff_tests/parser/profiling/heap_graph_native_size.textproto
similarity index 100%
rename from test/trace_processor/diff_tests/profiling/heap_graph_native_size.textproto
rename to test/trace_processor/diff_tests/parser/profiling/heap_graph_native_size.textproto
diff --git a/test/trace_processor/diff_tests/profiling/heap_graph_object.out b/test/trace_processor/diff_tests/parser/profiling/heap_graph_object.out
similarity index 100%
rename from test/trace_processor/diff_tests/profiling/heap_graph_object.out
rename to test/trace_processor/diff_tests/parser/profiling/heap_graph_object.out
diff --git a/test/trace_processor/diff_tests/profiling/heap_graph_reference.out b/test/trace_processor/diff_tests/parser/profiling/heap_graph_reference.out
similarity index 100%
rename from test/trace_processor/diff_tests/profiling/heap_graph_reference.out
rename to test/trace_processor/diff_tests/parser/profiling/heap_graph_reference.out
diff --git a/test/trace_processor/diff_tests/profiling/heap_graph_superclass.textproto b/test/trace_processor/diff_tests/parser/profiling/heap_graph_superclass.textproto
similarity index 100%
rename from test/trace_processor/diff_tests/profiling/heap_graph_superclass.textproto
rename to test/trace_processor/diff_tests/parser/profiling/heap_graph_superclass.textproto
diff --git a/test/trace_processor/diff_tests/profiling/heap_graph_two_locations.out b/test/trace_processor/diff_tests/parser/profiling/heap_graph_two_locations.out
similarity index 100%
rename from test/trace_processor/diff_tests/profiling/heap_graph_two_locations.out
rename to test/trace_processor/diff_tests/parser/profiling/heap_graph_two_locations.out
diff --git a/test/trace_processor/diff_tests/profiling/heap_graph_two_locations.textproto b/test/trace_processor/diff_tests/parser/profiling/heap_graph_two_locations.textproto
similarity index 100%
rename from test/trace_processor/diff_tests/profiling/heap_graph_two_locations.textproto
rename to test/trace_processor/diff_tests/parser/profiling/heap_graph_two_locations.textproto
diff --git a/test/trace_processor/diff_tests/profiling/heap_profile.textproto b/test/trace_processor/diff_tests/parser/profiling/heap_profile.textproto
similarity index 100%
rename from test/trace_processor/diff_tests/profiling/heap_profile.textproto
rename to test/trace_processor/diff_tests/parser/profiling/heap_profile.textproto
diff --git a/test/trace_processor/diff_tests/profiling/heap_profile_data_local_tmp.textproto b/test/trace_processor/diff_tests/parser/profiling/heap_profile_data_local_tmp.textproto
similarity index 100%
rename from test/trace_processor/diff_tests/profiling/heap_profile_data_local_tmp.textproto
rename to test/trace_processor/diff_tests/parser/profiling/heap_profile_data_local_tmp.textproto
diff --git a/test/trace_processor/diff_tests/profiling/heap_profile_deobfuscate.textproto b/test/trace_processor/diff_tests/parser/profiling/heap_profile_deobfuscate.textproto
similarity index 100%
rename from test/trace_processor/diff_tests/profiling/heap_profile_deobfuscate.textproto
rename to test/trace_processor/diff_tests/parser/profiling/heap_profile_deobfuscate.textproto
diff --git a/test/trace_processor/diff_tests/profiling/heap_profile_deobfuscate_memfd.textproto b/test/trace_processor/diff_tests/parser/profiling/heap_profile_deobfuscate_memfd.textproto
similarity index 100%
rename from test/trace_processor/diff_tests/profiling/heap_profile_deobfuscate_memfd.textproto
rename to test/trace_processor/diff_tests/parser/profiling/heap_profile_deobfuscate_memfd.textproto
diff --git a/test/trace_processor/diff_tests/profiling/heap_profile_deobfuscate_test.sql b/test/trace_processor/diff_tests/parser/profiling/heap_profile_deobfuscate_test.sql
similarity index 100%
rename from test/trace_processor/diff_tests/profiling/heap_profile_deobfuscate_test.sql
rename to test/trace_processor/diff_tests/parser/profiling/heap_profile_deobfuscate_test.sql
diff --git a/test/trace_processor/diff_tests/profiling/heap_profile_dump_max.textproto b/test/trace_processor/diff_tests/parser/profiling/heap_profile_dump_max.textproto
similarity index 100%
rename from test/trace_processor/diff_tests/profiling/heap_profile_dump_max.textproto
rename to test/trace_processor/diff_tests/parser/profiling/heap_profile_dump_max.textproto
diff --git a/test/trace_processor/diff_tests/profiling/heap_profile_dump_max_legacy.textproto b/test/trace_processor/diff_tests/parser/profiling/heap_profile_dump_max_legacy.textproto
similarity index 100%
rename from test/trace_processor/diff_tests/profiling/heap_profile_dump_max_legacy.textproto
rename to test/trace_processor/diff_tests/parser/profiling/heap_profile_dump_max_legacy.textproto
diff --git a/test/trace_processor/diff_tests/profiling/heap_profile_flamegraph_system-server-native-profile.out b/test/trace_processor/diff_tests/parser/profiling/heap_profile_flamegraph_system-server-native-profile.out
similarity index 100%
rename from test/trace_processor/diff_tests/profiling/heap_profile_flamegraph_system-server-native-profile.out
rename to test/trace_processor/diff_tests/parser/profiling/heap_profile_flamegraph_system-server-native-profile.out
diff --git a/test/trace_processor/diff_tests/profiling/heap_profile_jit.textproto b/test/trace_processor/diff_tests/parser/profiling/heap_profile_jit.textproto
similarity index 100%
rename from test/trace_processor/diff_tests/profiling/heap_profile_jit.textproto
rename to test/trace_processor/diff_tests/parser/profiling/heap_profile_jit.textproto
diff --git a/test/trace_processor/diff_tests/profiling/heap_profile_tracker_new_stack.textproto b/test/trace_processor/diff_tests/parser/profiling/heap_profile_tracker_new_stack.textproto
similarity index 100%
rename from test/trace_processor/diff_tests/profiling/heap_profile_tracker_new_stack.textproto
rename to test/trace_processor/diff_tests/parser/profiling/heap_profile_tracker_new_stack.textproto
diff --git a/test/trace_processor/diff_tests/profiling/heap_profile_tracker_twoheaps.textproto b/test/trace_processor/diff_tests/parser/profiling/heap_profile_tracker_twoheaps.textproto
similarity index 100%
rename from test/trace_processor/diff_tests/profiling/heap_profile_tracker_twoheaps.textproto
rename to test/trace_processor/diff_tests/parser/profiling/heap_profile_tracker_twoheaps.textproto
diff --git a/test/trace_processor/diff_tests/profiling/perf_sample_rvc.out b/test/trace_processor/diff_tests/parser/profiling/perf_sample_rvc.out
similarity index 100%
rename from test/trace_processor/diff_tests/profiling/perf_sample_rvc.out
rename to test/trace_processor/diff_tests/parser/profiling/perf_sample_rvc.out
diff --git a/test/trace_processor/diff_tests/profiling/perf_sample_sc.out b/test/trace_processor/diff_tests/parser/profiling/perf_sample_sc.out
similarity index 100%
rename from test/trace_processor/diff_tests/profiling/perf_sample_sc.out
rename to test/trace_processor/diff_tests/parser/profiling/perf_sample_sc.out
diff --git a/test/trace_processor/diff_tests/profiling/perf_sample_switch_interp.textproto b/test/trace_processor/diff_tests/parser/profiling/perf_sample_switch_interp.textproto
similarity index 100%
rename from test/trace_processor/diff_tests/profiling/perf_sample_switch_interp.textproto
rename to test/trace_processor/diff_tests/parser/profiling/perf_sample_switch_interp.textproto
diff --git a/test/trace_processor/diff_tests/profiling/stack_profile_symbols.out b/test/trace_processor/diff_tests/parser/profiling/stack_profile_symbols.out
similarity index 100%
rename from test/trace_processor/diff_tests/profiling/stack_profile_symbols.out
rename to test/trace_processor/diff_tests/parser/profiling/stack_profile_symbols.out
diff --git a/test/trace_processor/diff_tests/profiling/tests.py b/test/trace_processor/diff_tests/parser/profiling/tests.py
similarity index 100%
rename from test/trace_processor/diff_tests/profiling/tests.py
rename to test/trace_processor/diff_tests/parser/profiling/tests.py
diff --git a/test/trace_processor/diff_tests/profiling/tests_heap_graph.py b/test/trace_processor/diff_tests/parser/profiling/tests_heap_graph.py
similarity index 100%
rename from test/trace_processor/diff_tests/profiling/tests_heap_graph.py
rename to test/trace_processor/diff_tests/parser/profiling/tests_heap_graph.py
diff --git a/test/trace_processor/diff_tests/profiling/tests_heap_profiling.py b/test/trace_processor/diff_tests/parser/profiling/tests_heap_profiling.py
similarity index 100%
rename from test/trace_processor/diff_tests/profiling/tests_heap_profiling.py
rename to test/trace_processor/diff_tests/parser/profiling/tests_heap_profiling.py
diff --git a/test/trace_processor/diff_tests/profiling/tests_llvm_symbolizer.py b/test/trace_processor/diff_tests/parser/profiling/tests_llvm_symbolizer.py
similarity index 100%
rename from test/trace_processor/diff_tests/profiling/tests_llvm_symbolizer.py
rename to test/trace_processor/diff_tests/parser/profiling/tests_llvm_symbolizer.py
diff --git a/test/trace_processor/diff_tests/performance/cpu_frequency_limits.textproto b/test/trace_processor/diff_tests/parser/sched/cpu_frequency_limits.textproto
similarity index 100%
rename from test/trace_processor/diff_tests/performance/cpu_frequency_limits.textproto
rename to test/trace_processor/diff_tests/parser/sched/cpu_frequency_limits.textproto
diff --git a/test/trace_processor/diff_tests/scheduler/sched_cpu_util_cfs.textproto b/test/trace_processor/diff_tests/parser/sched/sched_cpu_util_cfs.textproto
similarity index 100%
rename from test/trace_processor/diff_tests/scheduler/sched_cpu_util_cfs.textproto
rename to test/trace_processor/diff_tests/parser/sched/sched_cpu_util_cfs.textproto
diff --git a/test/trace_processor/diff_tests/scheduler/sched_cpu_util_cfs_test.sql b/test/trace_processor/diff_tests/parser/sched/sched_cpu_util_cfs_test.sql
similarity index 100%
rename from test/trace_processor/diff_tests/scheduler/sched_cpu_util_cfs_test.sql
rename to test/trace_processor/diff_tests/parser/sched/sched_cpu_util_cfs_test.sql
diff --git a/test/trace_processor/diff_tests/performance/tests.py b/test/trace_processor/diff_tests/parser/sched/tests.py
similarity index 74%
rename from test/trace_processor/diff_tests/performance/tests.py
rename to test/trace_processor/diff_tests/parser/sched/tests.py
index 7358373..ea04126 100644
--- a/test/trace_processor/diff_tests/performance/tests.py
+++ b/test/trace_processor/diff_tests/parser/sched/tests.py
@@ -19,14 +19,7 @@
from python.generators.diff_tests.testing import TestSuite
-class Performance(TestSuite):
- # IRQ max runtime and count over 1ms
- def test_irq_runtime_metric(self):
- return DiffTestBlueprint(
- trace=Path('irq_runtime_metric.textproto'),
- query=Metric('android_irq_runtime'),
- out=Path('irq_runtime_metric.out'))
-
+class SchedParser(TestSuite):
# CPU frequency maximum & minimum limits change
def test_cpu_frequency_limits(self):
return DiffTestBlueprint(
@@ -61,9 +54,22 @@
130000000,800000.000000,"Cpu 4 Min"
"""))
- # frame_timeline_metric collects App_Deadline_Missed metrics
- def test_frame_timeline_metric(self):
+ def test_sched_cpu_util_cfs(self):
return DiffTestBlueprint(
- trace=Path('frame_timeline_metric.py'),
- query=Metric('android_frame_timeline_metric'),
- out=Path('frame_timeline_metric.out'))
+ trace=Path('sched_cpu_util_cfs.textproto'),
+ query=Path('sched_cpu_util_cfs_test.sql'),
+ out=Csv("""
+ "name","ts","value"
+ "Cpu 6 Util",10000,1.000000
+ "Cpu 6 Cap",10000,1004.000000
+ "Cpu 6 Nr Running",10000,0.000000
+ "Cpu 7 Util",11000,1.000000
+ "Cpu 7 Cap",11000,1007.000000
+ "Cpu 7 Nr Running",11000,0.000000
+ "Cpu 4 Util",12000,43.000000
+ "Cpu 4 Cap",12000,760.000000
+ "Cpu 4 Nr Running",12000,0.000000
+ "Cpu 5 Util",13000,125.000000
+ "Cpu 5 Cap",13000,757.000000
+ "Cpu 5 Nr Running",13000,1.000000
+ """))
\ No newline at end of file
diff --git a/test/trace_processor/diff_tests/smoke/proxy_power.out b/test/trace_processor/diff_tests/parser/smoke/proxy_power.out
similarity index 100%
rename from test/trace_processor/diff_tests/smoke/proxy_power.out
rename to test/trace_processor/diff_tests/parser/smoke/proxy_power.out
diff --git a/test/trace_processor/diff_tests/smoke/tests.py b/test/trace_processor/diff_tests/parser/smoke/tests.py
similarity index 100%
rename from test/trace_processor/diff_tests/smoke/tests.py
rename to test/trace_processor/diff_tests/parser/smoke/tests.py
diff --git a/test/trace_processor/diff_tests/smoke/tests_compute_metrics.py b/test/trace_processor/diff_tests/parser/smoke/tests_compute_metrics.py
similarity index 100%
rename from test/trace_processor/diff_tests/smoke/tests_compute_metrics.py
rename to test/trace_processor/diff_tests/parser/smoke/tests_compute_metrics.py
diff --git a/test/trace_processor/diff_tests/smoke/tests_json.py b/test/trace_processor/diff_tests/parser/smoke/tests_json.py
similarity index 100%
rename from test/trace_processor/diff_tests/smoke/tests_json.py
rename to test/trace_processor/diff_tests/parser/smoke/tests_json.py
diff --git a/test/trace_processor/diff_tests/smoke/tests_sched_events.py b/test/trace_processor/diff_tests/parser/smoke/tests_sched_events.py
similarity index 97%
rename from test/trace_processor/diff_tests/smoke/tests_sched_events.py
rename to test/trace_processor/diff_tests/parser/smoke/tests_sched_events.py
index 86e39fd..fec730f 100644
--- a/test/trace_processor/diff_tests/smoke/tests_sched_events.py
+++ b/test/trace_processor/diff_tests/parser/smoke/tests_sched_events.py
@@ -56,7 +56,7 @@
# Sched events from sythetic trace
def test_synth_1_smoke(self):
return DiffTestBlueprint(
- trace=Path('../common/synth_1.py'),
+ trace=Path('../../common/synth_1.py'),
query="""
SELECT
ts,
diff --git a/test/trace_processor/diff_tests/smoke/thread_cpu_time_example_android_trace_30s.out b/test/trace_processor/diff_tests/parser/smoke/thread_cpu_time_example_android_trace_30s.out
similarity index 100%
rename from test/trace_processor/diff_tests/smoke/thread_cpu_time_example_android_trace_30s.out
rename to test/trace_processor/diff_tests/parser/smoke/thread_cpu_time_example_android_trace_30s.out
diff --git a/test/trace_processor/diff_tests/track_event/experimental_slice_layout_depth.py b/test/trace_processor/diff_tests/parser/track_event/experimental_slice_layout_depth.py
similarity index 99%
rename from test/trace_processor/diff_tests/track_event/experimental_slice_layout_depth.py
rename to test/trace_processor/diff_tests/parser/track_event/experimental_slice_layout_depth.py
index 3baf368..25b7668 100644
--- a/test/trace_processor/diff_tests/track_event/experimental_slice_layout_depth.py
+++ b/test/trace_processor/diff_tests/parser/track_event/experimental_slice_layout_depth.py
@@ -21,6 +21,7 @@
import synth_common
from synth_common import ms_to_ns
+
trace = synth_common.create_trace()
track1 = 1234
diff --git a/test/trace_processor/diff_tests/track_event/flow_events_proto_v1.textproto b/test/trace_processor/diff_tests/parser/track_event/flow_events_proto_v1.textproto
similarity index 100%
rename from test/trace_processor/diff_tests/track_event/flow_events_proto_v1.textproto
rename to test/trace_processor/diff_tests/parser/track_event/flow_events_proto_v1.textproto
diff --git a/test/trace_processor/diff_tests/track_event/flow_events_proto_v2.textproto b/test/trace_processor/diff_tests/parser/track_event/flow_events_proto_v2.textproto
similarity index 100%
rename from test/trace_processor/diff_tests/track_event/flow_events_proto_v2.textproto
rename to test/trace_processor/diff_tests/parser/track_event/flow_events_proto_v2.textproto
diff --git a/test/trace_processor/diff_tests/track_event/flow_events_track_event.textproto b/test/trace_processor/diff_tests/parser/track_event/flow_events_track_event.textproto
similarity index 100%
rename from test/trace_processor/diff_tests/track_event/flow_events_track_event.textproto
rename to test/trace_processor/diff_tests/parser/track_event/flow_events_track_event.textproto
diff --git a/test/trace_processor/diff_tests/track_event/legacy_async_event.out b/test/trace_processor/diff_tests/parser/track_event/legacy_async_event.out
similarity index 100%
rename from test/trace_processor/diff_tests/track_event/legacy_async_event.out
rename to test/trace_processor/diff_tests/parser/track_event/legacy_async_event.out
diff --git a/test/trace_processor/diff_tests/track_event/legacy_async_event.textproto b/test/trace_processor/diff_tests/parser/track_event/legacy_async_event.textproto
similarity index 100%
rename from test/trace_processor/diff_tests/track_event/legacy_async_event.textproto
rename to test/trace_processor/diff_tests/parser/track_event/legacy_async_event.textproto
diff --git a/test/trace_processor/diff_tests/track_event/range_of_interest.textproto b/test/trace_processor/diff_tests/parser/track_event/range_of_interest.textproto
similarity index 100%
rename from test/trace_processor/diff_tests/track_event/range_of_interest.textproto
rename to test/trace_processor/diff_tests/parser/track_event/range_of_interest.textproto
diff --git a/test/trace_processor/diff_tests/track_event/tests.py b/test/trace_processor/diff_tests/parser/track_event/tests.py
similarity index 100%
rename from test/trace_processor/diff_tests/track_event/tests.py
rename to test/trace_processor/diff_tests/parser/track_event/tests.py
diff --git a/test/trace_processor/diff_tests/track_event/track_event_args_test.sql b/test/trace_processor/diff_tests/parser/track_event/track_event_args_test.sql
similarity index 100%
rename from test/trace_processor/diff_tests/track_event/track_event_args_test.sql
rename to test/trace_processor/diff_tests/parser/track_event/track_event_args_test.sql
diff --git a/test/trace_processor/diff_tests/track_event/track_event_chrome_histogram_sample.textproto b/test/trace_processor/diff_tests/parser/track_event/track_event_chrome_histogram_sample.textproto
similarity index 100%
rename from test/trace_processor/diff_tests/track_event/track_event_chrome_histogram_sample.textproto
rename to test/trace_processor/diff_tests/parser/track_event/track_event_chrome_histogram_sample.textproto
diff --git a/test/trace_processor/diff_tests/track_event/track_event_chrome_histogram_sample_args.out b/test/trace_processor/diff_tests/parser/track_event/track_event_chrome_histogram_sample_args.out
similarity index 100%
rename from test/trace_processor/diff_tests/track_event/track_event_chrome_histogram_sample_args.out
rename to test/trace_processor/diff_tests/parser/track_event/track_event_chrome_histogram_sample_args.out
diff --git a/test/trace_processor/diff_tests/track_event/track_event_counters.textproto b/test/trace_processor/diff_tests/parser/track_event/track_event_counters.textproto
similarity index 100%
rename from test/trace_processor/diff_tests/track_event/track_event_counters.textproto
rename to test/trace_processor/diff_tests/parser/track_event/track_event_counters.textproto
diff --git a/test/trace_processor/diff_tests/track_event/track_event_counters_counters.out b/test/trace_processor/diff_tests/parser/track_event/track_event_counters_counters.out
similarity index 100%
rename from test/trace_processor/diff_tests/track_event/track_event_counters_counters.out
rename to test/trace_processor/diff_tests/parser/track_event/track_event_counters_counters.out
diff --git a/test/trace_processor/diff_tests/track_event/track_event_merged_debug_annotations.textproto b/test/trace_processor/diff_tests/parser/track_event/track_event_merged_debug_annotations.textproto
similarity index 100%
rename from test/trace_processor/diff_tests/track_event/track_event_merged_debug_annotations.textproto
rename to test/trace_processor/diff_tests/parser/track_event/track_event_merged_debug_annotations.textproto
diff --git a/test/trace_processor/diff_tests/track_event/track_event_merged_debug_annotations_args.out b/test/trace_processor/diff_tests/parser/track_event/track_event_merged_debug_annotations_args.out
similarity index 100%
rename from test/trace_processor/diff_tests/track_event/track_event_merged_debug_annotations_args.out
rename to test/trace_processor/diff_tests/parser/track_event/track_event_merged_debug_annotations_args.out
diff --git a/test/trace_processor/diff_tests/track_event/track_event_tracks.textproto b/test/trace_processor/diff_tests/parser/track_event/track_event_tracks.textproto
similarity index 100%
rename from test/trace_processor/diff_tests/track_event/track_event_tracks.textproto
rename to test/trace_processor/diff_tests/parser/track_event/track_event_tracks.textproto
diff --git a/test/trace_processor/diff_tests/track_event/track_event_tracks_slices.out b/test/trace_processor/diff_tests/parser/track_event/track_event_tracks_slices.out
similarity index 100%
rename from test/trace_processor/diff_tests/track_event/track_event_tracks_slices.out
rename to test/trace_processor/diff_tests/parser/track_event/track_event_tracks_slices.out
diff --git a/test/trace_processor/diff_tests/track_event/track_event_typed_args.textproto b/test/trace_processor/diff_tests/parser/track_event/track_event_typed_args.textproto
similarity index 100%
rename from test/trace_processor/diff_tests/track_event/track_event_typed_args.textproto
rename to test/trace_processor/diff_tests/parser/track_event/track_event_typed_args.textproto
diff --git a/test/trace_processor/diff_tests/track_event/track_event_typed_args_args.out b/test/trace_processor/diff_tests/parser/track_event/track_event_typed_args_args.out
similarity index 100%
rename from test/trace_processor/diff_tests/track_event/track_event_typed_args_args.out
rename to test/trace_processor/diff_tests/parser/track_event/track_event_typed_args_args.out
diff --git a/test/trace_processor/diff_tests/track_event/track_event_with_atrace.textproto b/test/trace_processor/diff_tests/parser/track_event/track_event_with_atrace.textproto
similarity index 100%
rename from test/trace_processor/diff_tests/track_event/track_event_with_atrace.textproto
rename to test/trace_processor/diff_tests/parser/track_event/track_event_with_atrace.textproto
diff --git a/test/trace_processor/diff_tests/track_event/track_event_with_atrace_separate_tracks.textproto b/test/trace_processor/diff_tests/parser/track_event/track_event_with_atrace_separate_tracks.textproto
similarity index 100%
rename from test/trace_processor/diff_tests/track_event/track_event_with_atrace_separate_tracks.textproto
rename to test/trace_processor/diff_tests/parser/track_event/track_event_with_atrace_separate_tracks.textproto
diff --git a/test/trace_processor/diff_tests/translation/chrome_args_test.sql b/test/trace_processor/diff_tests/parser/translated_args/chrome_args_test.sql
similarity index 100%
rename from test/trace_processor/diff_tests/translation/chrome_args_test.sql
rename to test/trace_processor/diff_tests/parser/translated_args/chrome_args_test.sql
diff --git a/test/trace_processor/diff_tests/translation/chrome_histogram.out b/test/trace_processor/diff_tests/parser/translated_args/chrome_histogram.out
similarity index 100%
rename from test/trace_processor/diff_tests/translation/chrome_histogram.out
rename to test/trace_processor/diff_tests/parser/translated_args/chrome_histogram.out
diff --git a/test/trace_processor/diff_tests/translation/chrome_histogram.textproto b/test/trace_processor/diff_tests/parser/translated_args/chrome_histogram.textproto
similarity index 100%
rename from test/trace_processor/diff_tests/translation/chrome_histogram.textproto
rename to test/trace_processor/diff_tests/parser/translated_args/chrome_histogram.textproto
diff --git a/test/trace_processor/diff_tests/translation/chrome_performance_mark.out b/test/trace_processor/diff_tests/parser/translated_args/chrome_performance_mark.out
similarity index 100%
rename from test/trace_processor/diff_tests/translation/chrome_performance_mark.out
rename to test/trace_processor/diff_tests/parser/translated_args/chrome_performance_mark.out
diff --git a/test/trace_processor/diff_tests/translation/chrome_user_event.out b/test/trace_processor/diff_tests/parser/translated_args/chrome_user_event.out
similarity index 100%
rename from test/trace_processor/diff_tests/translation/chrome_user_event.out
rename to test/trace_processor/diff_tests/parser/translated_args/chrome_user_event.out
diff --git a/test/trace_processor/diff_tests/translation/chrome_user_event.textproto b/test/trace_processor/diff_tests/parser/translated_args/chrome_user_event.textproto
similarity index 100%
rename from test/trace_processor/diff_tests/translation/chrome_user_event.textproto
rename to test/trace_processor/diff_tests/parser/translated_args/chrome_user_event.textproto
diff --git a/test/trace_processor/diff_tests/translation/java_class_name_arg.out b/test/trace_processor/diff_tests/parser/translated_args/java_class_name_arg.out
similarity index 100%
rename from test/trace_processor/diff_tests/translation/java_class_name_arg.out
rename to test/trace_processor/diff_tests/parser/translated_args/java_class_name_arg.out
diff --git a/test/trace_processor/diff_tests/translation/java_class_name_arg.textproto b/test/trace_processor/diff_tests/parser/translated_args/java_class_name_arg.textproto
similarity index 100%
rename from test/trace_processor/diff_tests/translation/java_class_name_arg.textproto
rename to test/trace_processor/diff_tests/parser/translated_args/java_class_name_arg.textproto
diff --git a/test/trace_processor/diff_tests/translation/native_symbol_arg.out b/test/trace_processor/diff_tests/parser/translated_args/native_symbol_arg.out
similarity index 100%
rename from test/trace_processor/diff_tests/translation/native_symbol_arg.out
rename to test/trace_processor/diff_tests/parser/translated_args/native_symbol_arg.out
diff --git a/test/trace_processor/diff_tests/translation/native_symbol_arg.textproto b/test/trace_processor/diff_tests/parser/translated_args/native_symbol_arg.textproto
similarity index 100%
rename from test/trace_processor/diff_tests/translation/native_symbol_arg.textproto
rename to test/trace_processor/diff_tests/parser/translated_args/native_symbol_arg.textproto
diff --git a/test/trace_processor/diff_tests/translation/native_symbol_arg_incomplete.textproto b/test/trace_processor/diff_tests/parser/translated_args/native_symbol_arg_incomplete.textproto
similarity index 100%
rename from test/trace_processor/diff_tests/translation/native_symbol_arg_incomplete.textproto
rename to test/trace_processor/diff_tests/parser/translated_args/native_symbol_arg_incomplete.textproto
diff --git a/test/trace_processor/diff_tests/translation/slice_name.textproto b/test/trace_processor/diff_tests/parser/translated_args/slice_name.textproto
similarity index 100%
rename from test/trace_processor/diff_tests/translation/slice_name.textproto
rename to test/trace_processor/diff_tests/parser/translated_args/slice_name.textproto
diff --git a/test/trace_processor/diff_tests/translation/slice_name_negative_timestamp.textproto b/test/trace_processor/diff_tests/parser/translated_args/slice_name_negative_timestamp.textproto
similarity index 100%
rename from test/trace_processor/diff_tests/translation/slice_name_negative_timestamp.textproto
rename to test/trace_processor/diff_tests/parser/translated_args/slice_name_negative_timestamp.textproto
diff --git a/test/trace_processor/diff_tests/translation/tests.py b/test/trace_processor/diff_tests/parser/translated_args/tests.py
similarity index 98%
rename from test/trace_processor/diff_tests/translation/tests.py
rename to test/trace_processor/diff_tests/parser/translated_args/tests.py
index 9856205..7e28f38 100644
--- a/test/trace_processor/diff_tests/translation/tests.py
+++ b/test/trace_processor/diff_tests/parser/translated_args/tests.py
@@ -19,7 +19,7 @@
from python.generators.diff_tests.testing import TestSuite
-class Translation(TestSuite):
+class TranslatedArgs(TestSuite):
def test_java_class_name_arg(self):
return DiffTestBlueprint(
diff --git a/test/trace_processor/diff_tests/ufs/tests.py b/test/trace_processor/diff_tests/parser/ufs/tests.py
similarity index 100%
rename from test/trace_processor/diff_tests/ufs/tests.py
rename to test/trace_processor/diff_tests/parser/ufs/tests.py
diff --git a/test/trace_processor/diff_tests/ufs/ufshcd_command.textproto b/test/trace_processor/diff_tests/parser/ufs/ufshcd_command.textproto
similarity index 100%
rename from test/trace_processor/diff_tests/ufs/ufshcd_command.textproto
rename to test/trace_processor/diff_tests/parser/ufs/ufshcd_command.textproto
diff --git a/test/trace_processor/diff_tests/ufs/ufshcd_command_tag.textproto b/test/trace_processor/diff_tests/parser/ufs/ufshcd_command_tag.textproto
similarity index 100%
rename from test/trace_processor/diff_tests/ufs/ufshcd_command_tag.textproto
rename to test/trace_processor/diff_tests/parser/ufs/ufshcd_command_tag.textproto
diff --git a/test/trace_processor/diff_tests/scheduler/tests.py b/test/trace_processor/diff_tests/scheduler/tests.py
deleted file mode 100644
index b935c6a..0000000
--- a/test/trace_processor/diff_tests/scheduler/tests.py
+++ /dev/null
@@ -1,42 +0,0 @@
-#!/usr/bin/env python3
-# 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 a
-#
-# 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.
-
-from python.generators.diff_tests.testing import Path, DataPath, Metric
-from python.generators.diff_tests.testing import Csv, Json, TextProto
-from python.generators.diff_tests.testing import DiffTestBlueprint
-from python.generators.diff_tests.testing import TestSuite
-
-
-class Scheduler(TestSuite):
- # Scheduler
- def test_sched_cpu_util_cfs(self):
- return DiffTestBlueprint(
- trace=Path('sched_cpu_util_cfs.textproto'),
- query=Path('sched_cpu_util_cfs_test.sql'),
- out=Csv("""
- "name","ts","value"
- "Cpu 6 Util",10000,1.000000
- "Cpu 6 Cap",10000,1004.000000
- "Cpu 6 Nr Running",10000,0.000000
- "Cpu 7 Util",11000,1.000000
- "Cpu 7 Cap",11000,1007.000000
- "Cpu 7 Nr Running",11000,0.000000
- "Cpu 4 Util",12000,43.000000
- "Cpu 4 Cap",12000,760.000000
- "Cpu 4 Nr Running",12000,0.000000
- "Cpu 5 Util",13000,125.000000
- "Cpu 5 Cap",13000,757.000000
- "Cpu 5 Nr Running",13000,1.000000
- """))
diff --git a/test/trace_processor/diff_tests/dynamic/ancestor_slice.out b/test/trace_processor/diff_tests/stdlib/dynamic_tables/ancestor_slice.out
similarity index 100%
rename from test/trace_processor/diff_tests/dynamic/ancestor_slice.out
rename to test/trace_processor/diff_tests/stdlib/dynamic_tables/ancestor_slice.out
diff --git a/test/trace_processor/diff_tests/dynamic/connected_flow.out b/test/trace_processor/diff_tests/stdlib/dynamic_tables/connected_flow.out
similarity index 100%
rename from test/trace_processor/diff_tests/dynamic/connected_flow.out
rename to test/trace_processor/diff_tests/stdlib/dynamic_tables/connected_flow.out
diff --git a/test/trace_processor/diff_tests/dynamic/connected_flow_data.json b/test/trace_processor/diff_tests/stdlib/dynamic_tables/connected_flow_data.json
similarity index 100%
rename from test/trace_processor/diff_tests/dynamic/connected_flow_data.json
rename to test/trace_processor/diff_tests/stdlib/dynamic_tables/connected_flow_data.json
diff --git a/test/trace_processor/diff_tests/dynamic/connected_flow_test.sql b/test/trace_processor/diff_tests/stdlib/dynamic_tables/connected_flow_test.sql
similarity index 100%
rename from test/trace_processor/diff_tests/dynamic/connected_flow_test.sql
rename to test/trace_processor/diff_tests/stdlib/dynamic_tables/connected_flow_test.sql
diff --git a/test/trace_processor/diff_tests/dynamic/descendant_slice.out b/test/trace_processor/diff_tests/stdlib/dynamic_tables/descendant_slice.out
similarity index 100%
rename from test/trace_processor/diff_tests/dynamic/descendant_slice.out
rename to test/trace_processor/diff_tests/stdlib/dynamic_tables/descendant_slice.out
diff --git a/test/trace_processor/diff_tests/dynamic/perf_sample_sc_annotated_callstack.out b/test/trace_processor/diff_tests/stdlib/dynamic_tables/perf_sample_sc_annotated_callstack.out
similarity index 100%
rename from test/trace_processor/diff_tests/dynamic/perf_sample_sc_annotated_callstack.out
rename to test/trace_processor/diff_tests/stdlib/dynamic_tables/perf_sample_sc_annotated_callstack.out
diff --git a/test/trace_processor/diff_tests/dynamic/relationship_tables.textproto b/test/trace_processor/diff_tests/stdlib/dynamic_tables/relationship_tables.textproto
similarity index 100%
rename from test/trace_processor/diff_tests/dynamic/relationship_tables.textproto
rename to test/trace_processor/diff_tests/stdlib/dynamic_tables/relationship_tables.textproto
diff --git a/test/trace_processor/diff_tests/dynamic/slice_stacks.textproto b/test/trace_processor/diff_tests/stdlib/dynamic_tables/slice_stacks.textproto
similarity index 100%
rename from test/trace_processor/diff_tests/dynamic/slice_stacks.textproto
rename to test/trace_processor/diff_tests/stdlib/dynamic_tables/slice_stacks.textproto
diff --git a/test/trace_processor/diff_tests/dynamic/tests.py b/test/trace_processor/diff_tests/stdlib/dynamic_tables/tests.py
similarity index 99%
rename from test/trace_processor/diff_tests/dynamic/tests.py
rename to test/trace_processor/diff_tests/stdlib/dynamic_tables/tests.py
index 3c79262..60b170c 100644
--- a/test/trace_processor/diff_tests/dynamic/tests.py
+++ b/test/trace_processor/diff_tests/stdlib/dynamic_tables/tests.py
@@ -19,7 +19,7 @@
from python.generators.diff_tests.testing import TestSuite
-class Dynamic(TestSuite):
+class DynamicTables(TestSuite):
# Tests for custom dynamic tables. Ancestor slice table.
def test_ancestor_slice(self):
return DiffTestBlueprint(
diff --git a/test/trace_processor/diff_tests/dynamic/various_clocks.textproto b/test/trace_processor/diff_tests/stdlib/dynamic_tables/various_clocks.textproto
similarity index 100%
rename from test/trace_processor/diff_tests/dynamic/various_clocks.textproto
rename to test/trace_processor/diff_tests/stdlib/dynamic_tables/various_clocks.textproto
diff --git a/test/trace_processor/diff_tests/pkvm/pkvm_hypervisor_events.textproto b/test/trace_processor/diff_tests/stdlib/pkvm/pkvm_hypervisor_events.textproto
similarity index 100%
rename from test/trace_processor/diff_tests/pkvm/pkvm_hypervisor_events.textproto
rename to test/trace_processor/diff_tests/stdlib/pkvm/pkvm_hypervisor_events.textproto
diff --git a/test/trace_processor/diff_tests/pkvm/tests.py b/test/trace_processor/diff_tests/stdlib/pkvm/tests.py
similarity index 100%
rename from test/trace_processor/diff_tests/pkvm/tests.py
rename to test/trace_processor/diff_tests/stdlib/pkvm/tests.py
diff --git a/test/trace_processor/diff_tests/slices/tests.py b/test/trace_processor/diff_tests/stdlib/slices/tests.py
similarity index 100%
rename from test/trace_processor/diff_tests/slices/tests.py
rename to test/trace_processor/diff_tests/stdlib/slices/tests.py
diff --git a/test/trace_processor/diff_tests/slices/trace.py b/test/trace_processor/diff_tests/stdlib/slices/trace.py
similarity index 100%
rename from test/trace_processor/diff_tests/slices/trace.py
rename to test/trace_processor/diff_tests/stdlib/slices/trace.py
diff --git a/test/trace_processor/diff_tests/span_join/android_sched_and_ps_slice_span_join_b118665515.out b/test/trace_processor/diff_tests/stdlib/span_join/android_sched_and_ps_slice_span_join_b118665515.out
similarity index 100%
rename from test/trace_processor/diff_tests/span_join/android_sched_and_ps_slice_span_join_b118665515.out
rename to test/trace_processor/diff_tests/stdlib/span_join/android_sched_and_ps_slice_span_join_b118665515.out
diff --git a/test/trace_processor/diff_tests/span_join/slice_span_join_b118665515_test.sql b/test/trace_processor/diff_tests/stdlib/span_join/slice_span_join_b118665515_test.sql
similarity index 100%
rename from test/trace_processor/diff_tests/span_join/slice_span_join_b118665515_test.sql
rename to test/trace_processor/diff_tests/stdlib/span_join/slice_span_join_b118665515_test.sql
diff --git a/test/trace_processor/diff_tests/span_join/span_join_unordered_cols_reverse_test.sql b/test/trace_processor/diff_tests/stdlib/span_join/span_join_unordered_cols_reverse_test.sql
similarity index 100%
rename from test/trace_processor/diff_tests/span_join/span_join_unordered_cols_reverse_test.sql
rename to test/trace_processor/diff_tests/stdlib/span_join/span_join_unordered_cols_reverse_test.sql
diff --git a/test/trace_processor/diff_tests/span_join/span_join_unordered_cols_test.sql b/test/trace_processor/diff_tests/stdlib/span_join/span_join_unordered_cols_test.sql
similarity index 100%
rename from test/trace_processor/diff_tests/span_join/span_join_unordered_cols_test.sql
rename to test/trace_processor/diff_tests/stdlib/span_join/span_join_unordered_cols_test.sql
diff --git a/test/trace_processor/diff_tests/span_join/span_join_zero_negative_dur_test.sql b/test/trace_processor/diff_tests/stdlib/span_join/span_join_zero_negative_dur_test.sql
similarity index 100%
rename from test/trace_processor/diff_tests/span_join/span_join_zero_negative_dur_test.sql
rename to test/trace_processor/diff_tests/stdlib/span_join/span_join_zero_negative_dur_test.sql
diff --git a/test/trace_processor/diff_tests/span_join/span_left_join.out b/test/trace_processor/diff_tests/stdlib/span_join/span_left_join.out
similarity index 100%
rename from test/trace_processor/diff_tests/span_join/span_left_join.out
rename to test/trace_processor/diff_tests/stdlib/span_join/span_left_join.out
diff --git a/test/trace_processor/diff_tests/span_join/span_left_join_left_partitioned.out b/test/trace_processor/diff_tests/stdlib/span_join/span_left_join_left_partitioned.out
similarity index 100%
rename from test/trace_processor/diff_tests/span_join/span_left_join_left_partitioned.out
rename to test/trace_processor/diff_tests/stdlib/span_join/span_left_join_left_partitioned.out
diff --git a/test/trace_processor/diff_tests/span_join/span_left_join_left_partitioned_test.sql b/test/trace_processor/diff_tests/stdlib/span_join/span_left_join_left_partitioned_test.sql
similarity index 100%
rename from test/trace_processor/diff_tests/span_join/span_left_join_left_partitioned_test.sql
rename to test/trace_processor/diff_tests/stdlib/span_join/span_left_join_left_partitioned_test.sql
diff --git a/test/trace_processor/diff_tests/span_join/span_left_join_left_unpartitioned.out b/test/trace_processor/diff_tests/stdlib/span_join/span_left_join_left_unpartitioned.out
similarity index 100%
rename from test/trace_processor/diff_tests/span_join/span_left_join_left_unpartitioned.out
rename to test/trace_processor/diff_tests/stdlib/span_join/span_left_join_left_unpartitioned.out
diff --git a/test/trace_processor/diff_tests/span_join/span_left_join_left_unpartitioned_test.sql b/test/trace_processor/diff_tests/stdlib/span_join/span_left_join_left_unpartitioned_test.sql
similarity index 100%
rename from test/trace_processor/diff_tests/span_join/span_left_join_left_unpartitioned_test.sql
rename to test/trace_processor/diff_tests/stdlib/span_join/span_left_join_left_unpartitioned_test.sql
diff --git a/test/trace_processor/diff_tests/span_join/span_left_join_test.sql b/test/trace_processor/diff_tests/stdlib/span_join/span_left_join_test.sql
similarity index 100%
rename from test/trace_processor/diff_tests/span_join/span_left_join_test.sql
rename to test/trace_processor/diff_tests/stdlib/span_join/span_left_join_test.sql
diff --git a/test/trace_processor/diff_tests/span_join/span_left_join_unpartitioned.out b/test/trace_processor/diff_tests/stdlib/span_join/span_left_join_unpartitioned.out
similarity index 100%
rename from test/trace_processor/diff_tests/span_join/span_left_join_unpartitioned.out
rename to test/trace_processor/diff_tests/stdlib/span_join/span_left_join_unpartitioned.out
diff --git a/test/trace_processor/diff_tests/span_join/span_left_join_unpartitioned_test.sql b/test/trace_processor/diff_tests/stdlib/span_join/span_left_join_unpartitioned_test.sql
similarity index 100%
rename from test/trace_processor/diff_tests/span_join/span_left_join_unpartitioned_test.sql
rename to test/trace_processor/diff_tests/stdlib/span_join/span_left_join_unpartitioned_test.sql
diff --git a/test/trace_processor/diff_tests/span_join/span_outer_join.out b/test/trace_processor/diff_tests/stdlib/span_join/span_outer_join.out
similarity index 100%
rename from test/trace_processor/diff_tests/span_join/span_outer_join.out
rename to test/trace_processor/diff_tests/stdlib/span_join/span_outer_join.out
diff --git a/test/trace_processor/diff_tests/span_join/span_outer_join_mixed.out b/test/trace_processor/diff_tests/stdlib/span_join/span_outer_join_mixed.out
similarity index 100%
rename from test/trace_processor/diff_tests/span_join/span_outer_join_mixed.out
rename to test/trace_processor/diff_tests/stdlib/span_join/span_outer_join_mixed.out
diff --git a/test/trace_processor/diff_tests/span_join/span_outer_join_mixed_test.sql b/test/trace_processor/diff_tests/stdlib/span_join/span_outer_join_mixed_test.sql
similarity index 100%
rename from test/trace_processor/diff_tests/span_join/span_outer_join_mixed_test.sql
rename to test/trace_processor/diff_tests/stdlib/span_join/span_outer_join_mixed_test.sql
diff --git a/test/trace_processor/diff_tests/span_join/span_outer_join_test.sql b/test/trace_processor/diff_tests/stdlib/span_join/span_outer_join_test.sql
similarity index 100%
rename from test/trace_processor/diff_tests/span_join/span_outer_join_test.sql
rename to test/trace_processor/diff_tests/stdlib/span_join/span_outer_join_test.sql
diff --git a/test/trace_processor/diff_tests/span_join/span_outer_join_unpartitioned.out b/test/trace_processor/diff_tests/stdlib/span_join/span_outer_join_unpartitioned.out
similarity index 100%
rename from test/trace_processor/diff_tests/span_join/span_outer_join_unpartitioned.out
rename to test/trace_processor/diff_tests/stdlib/span_join/span_outer_join_unpartitioned.out
diff --git a/test/trace_processor/diff_tests/span_join/span_outer_join_unpartitioned_test.sql b/test/trace_processor/diff_tests/stdlib/span_join/span_outer_join_unpartitioned_test.sql
similarity index 100%
rename from test/trace_processor/diff_tests/span_join/span_outer_join_unpartitioned_test.sql
rename to test/trace_processor/diff_tests/stdlib/span_join/span_outer_join_unpartitioned_test.sql
diff --git a/test/trace_processor/diff_tests/span_join/tests_left_join.py b/test/trace_processor/diff_tests/stdlib/span_join/tests_left_join.py
similarity index 91%
rename from test/trace_processor/diff_tests/span_join/tests_left_join.py
rename to test/trace_processor/diff_tests/stdlib/span_join/tests_left_join.py
index 2bd2e58..30fd6ce 100644
--- a/test/trace_processor/diff_tests/span_join/tests_left_join.py
+++ b/test/trace_processor/diff_tests/stdlib/span_join/tests_left_join.py
@@ -23,31 +23,31 @@
def test_span_left_join(self):
return DiffTestBlueprint(
- trace=Path('../common/synth_1.py'),
+ trace=Path('../../common/synth_1.py'),
query=Path('span_left_join_test.sql'),
out=Path('span_left_join.out'))
def test_span_left_join_unpartitioned(self):
return DiffTestBlueprint(
- trace=Path('../common/synth_1.py'),
+ trace=Path('../../common/synth_1.py'),
query=Path('span_left_join_unpartitioned_test.sql'),
out=Path('span_left_join_unpartitioned.out'))
def test_span_left_join_left_unpartitioned(self):
return DiffTestBlueprint(
- trace=Path('../common/synth_1.py'),
+ trace=Path('../../common/synth_1.py'),
query=Path('span_left_join_left_unpartitioned_test.sql'),
out=Path('span_left_join_left_unpartitioned.out'))
def test_span_left_join_left_partitioned(self):
return DiffTestBlueprint(
- trace=Path('../common/synth_1.py'),
+ trace=Path('../../common/synth_1.py'),
query=Path('span_left_join_left_partitioned_test.sql'),
out=Path('span_left_join_left_partitioned.out'))
def test_span_left_join_empty_right(self):
return DiffTestBlueprint(
- trace=Path('../common/synth_1.py'),
+ trace=Path('../../common/synth_1.py'),
query="""
CREATE TABLE t1(
ts BIGINT,
@@ -79,7 +79,7 @@
def test_span_left_join_unordered_android_sched_and_ps(self):
return DiffTestBlueprint(
- trace=Path('../common/synth_1.py'),
+ trace=Path('../../common/synth_1.py'),
query="""
CREATE TABLE t1(
ts BIGINT,
diff --git a/test/trace_processor/diff_tests/span_join/tests_outer_join.py b/test/trace_processor/diff_tests/stdlib/span_join/tests_outer_join.py
similarity index 92%
rename from test/trace_processor/diff_tests/span_join/tests_outer_join.py
rename to test/trace_processor/diff_tests/stdlib/span_join/tests_outer_join.py
index c2ac4f5..d0354ca 100644
--- a/test/trace_processor/diff_tests/span_join/tests_outer_join.py
+++ b/test/trace_processor/diff_tests/stdlib/span_join/tests_outer_join.py
@@ -23,13 +23,13 @@
def test_span_outer_join(self):
return DiffTestBlueprint(
- trace=Path('../common/synth_1.py'),
+ trace=Path('../../common/synth_1.py'),
query=Path('span_outer_join_test.sql'),
out=Path('span_outer_join.out'))
def test_span_outer_join_empty(self):
return DiffTestBlueprint(
- trace=Path('../common/synth_1.py'),
+ trace=Path('../../common/synth_1.py'),
query="""
CREATE TABLE t1(
ts BIGINT,
@@ -61,7 +61,7 @@
def test_span_outer_join_unpartitioned_empty(self):
return DiffTestBlueprint(
- trace=Path('../common/synth_1.py'),
+ trace=Path('../../common/synth_1.py'),
query="""
CREATE TABLE t1(
ts BIGINT,
@@ -86,7 +86,7 @@
def test_span_outer_join_unpartitioned_left_empty(self):
return DiffTestBlueprint(
- trace=Path('../common/synth_1.py'),
+ trace=Path('../../common/synth_1.py'),
query="""
CREATE TABLE t1(
ts BIGINT,
@@ -119,7 +119,7 @@
def test_span_outer_join_unpartitioned_right_empty(self):
return DiffTestBlueprint(
- trace=Path('../common/synth_1.py'),
+ trace=Path('../../common/synth_1.py'),
query="""
CREATE TABLE t1(
ts BIGINT,
@@ -152,13 +152,13 @@
def test_span_outer_join_mixed(self):
return DiffTestBlueprint(
- trace=Path('../common/synth_1.py'),
+ trace=Path('../../common/synth_1.py'),
query=Path('span_outer_join_mixed_test.sql'),
out=Path('span_outer_join_mixed.out'))
def test_span_outer_join_mixed_empty(self):
return DiffTestBlueprint(
- trace=Path('../common/synth_1.py'),
+ trace=Path('../../common/synth_1.py'),
query="""
CREATE TABLE t1(
ts BIGINT,
@@ -184,7 +184,7 @@
def test_span_outer_join_mixed_left_empty(self):
return DiffTestBlueprint(
- trace=Path('../common/synth_1.py'),
+ trace=Path('../../common/synth_1.py'),
query="""
CREATE TABLE t1(
ts BIGINT,
@@ -215,7 +215,7 @@
def test_span_outer_join_mixed_left_empty_rev(self):
return DiffTestBlueprint(
- trace=Path('../common/synth_1.py'),
+ trace=Path('../../common/synth_1.py'),
query="""
CREATE TABLE t1(
ts BIGINT,
@@ -249,7 +249,7 @@
def test_span_outer_join_mixed_right_empty(self):
return DiffTestBlueprint(
- trace=Path('../common/synth_1.py'),
+ trace=Path('../../common/synth_1.py'),
query="""
CREATE TABLE t1(
ts BIGINT,
@@ -284,7 +284,7 @@
def test_span_outer_join_mixed_right_empty_rev(self):
return DiffTestBlueprint(
- trace=Path('../common/synth_1.py'),
+ trace=Path('../../common/synth_1.py'),
query="""
CREATE TABLE t1(
ts BIGINT,
@@ -316,6 +316,6 @@
def test_span_outer_join_mixed_2(self):
return DiffTestBlueprint(
- trace=Path('../common/synth_1.py'),
+ trace=Path('../../common/synth_1.py'),
query=Path('span_outer_join_mixed_test.sql'),
out=Path('span_outer_join_mixed.out'))
diff --git a/test/trace_processor/diff_tests/span_join/tests_regression.py b/test/trace_processor/diff_tests/stdlib/span_join/tests_regression.py
similarity index 100%
rename from test/trace_processor/diff_tests/span_join/tests_regression.py
rename to test/trace_processor/diff_tests/stdlib/span_join/tests_regression.py
diff --git a/test/trace_processor/diff_tests/span_join/tests_smoke.py b/test/trace_processor/diff_tests/stdlib/span_join/tests_smoke.py
similarity index 95%
rename from test/trace_processor/diff_tests/span_join/tests_smoke.py
rename to test/trace_processor/diff_tests/stdlib/span_join/tests_smoke.py
index e94a6c8..bacaa9a 100644
--- a/test/trace_processor/diff_tests/span_join/tests_smoke.py
+++ b/test/trace_processor/diff_tests/stdlib/span_join/tests_smoke.py
@@ -23,7 +23,7 @@
def test_span_join_unordered_cols_synth_1(self):
return DiffTestBlueprint(
- trace=Path('../common/synth_1.py'),
+ trace=Path('../../common/synth_1.py'),
query=Path('span_join_unordered_cols_test.sql'),
out=Csv("""
"ts","dur","part","b1","b2","b3","a1","a2","a3"
@@ -38,7 +38,7 @@
def test_span_join_unordered_cols_synth_1_2(self):
return DiffTestBlueprint(
- trace=Path('../common/synth_1.py'),
+ trace=Path('../../common/synth_1.py'),
query=Path('span_join_unordered_cols_reverse_test.sql'),
out=Csv("""
"ts","dur","part","b1","b2","b3","a1","a2","a3"
diff --git a/test/trace_processor/diff_tests/time/tests.py b/test/trace_processor/diff_tests/stdlib/timestamps/tests.py
similarity index 98%
rename from test/trace_processor/diff_tests/time/tests.py
rename to test/trace_processor/diff_tests/stdlib/timestamps/tests.py
index ee8771d..a029ce5 100644
--- a/test/trace_processor/diff_tests/time/tests.py
+++ b/test/trace_processor/diff_tests/stdlib/timestamps/tests.py
@@ -20,7 +20,7 @@
from google.protobuf import text_format
-class Time(TestSuite):
+class Timestamps(TestSuite):
def test_ns(self):
return DiffTestBlueprint(
diff --git a/test/trace_processor/diff_tests/functions/tests.py b/test/trace_processor/diff_tests/syntax/functions/tests.py
similarity index 99%
rename from test/trace_processor/diff_tests/functions/tests.py
rename to test/trace_processor/diff_tests/syntax/functions/tests.py
index 966e87d..f613fb5 100644
--- a/test/trace_processor/diff_tests/functions/tests.py
+++ b/test/trace_processor/diff_tests/syntax/functions/tests.py
@@ -20,6 +20,7 @@
from python.generators.diff_tests.testing import PrintProfileProto
from google.protobuf import text_format
+
class Functions(TestSuite):
def test_create_function(self):
diff --git a/test/trace_processor/diff_tests/perfetto_sql/tests.py b/test/trace_processor/diff_tests/syntax/perfetto_sql/tests.py
similarity index 100%
rename from test/trace_processor/diff_tests/perfetto_sql/tests.py
rename to test/trace_processor/diff_tests/syntax/perfetto_sql/tests.py
diff --git a/ui/src/common/actions.ts b/ui/src/common/actions.ts
index 646c8f8..992bc7b 100644
--- a/ui/src/common/actions.ts
+++ b/ui/src/common/actions.ts
@@ -30,9 +30,7 @@
tableColumnEquals,
toggleEnabled,
} from '../frontend/pivot_table_types';
-import {PrimaryTrackSortKey, TrackTags} from '../public/index';
-import {CounterDebugTrackConfig} from '../tracks/debug/counter_track';
-import {DebugTrackV2Config} from '../tracks/debug/slice_track';
+import {PrimaryTrackSortKey} from '../public/index';
import {randomColor} from './colorizer';
import {
@@ -85,15 +83,12 @@
export interface AddTrackArgs {
id?: string;
- engineId: string;
- kind: string;
+ uri: string;
name: string;
labels?: string[];
trackSortKey: TrackSortKey;
trackGroup?: string;
- config: {};
- tags?: TrackTags;
- uri?: string; // Only used for new PLUGIN_TRACK tracks
+ initialState?: unknown;
}
export interface PostedTrace {
@@ -215,9 +210,6 @@
fillUiTrackIdByTraceTrackId(
state: StateDraft, trackState: TrackState, uiTrackId: string) {
- const namespace = (trackState.config as {namespace?: string}).namespace;
- if (namespace !== undefined) return;
-
const setUiTrackId = (trackId: number, uiTrackId: string) => {
if (state.uiTrackIdByTraceTrackId[trackId] !== undefined &&
state.uiTrackIdByTraceTrackId[trackId] !== uiTrackId) {
@@ -228,7 +220,7 @@
state.uiTrackIdByTraceTrackId[trackId] = uiTrackId;
};
- const {uri, config} = trackState;
+ const {uri} = trackState;
if (exists(uri)) {
// If track is a new "plugin" type track (i.e. it has a uri), resolve the
// track ids from through the pluginManager.
@@ -238,16 +230,6 @@
setUiTrackId(trackId, uiTrackId);
}
}
- } else {
- // Traditional track - resolve track ids through the config.
- const {trackId, trackIds} = config;
- if (exists(trackId)) {
- setUiTrackId(trackId, uiTrackId);
- } else if (exists(trackIds)) {
- for (const trackId of trackIds) {
- setUiTrackId(trackId, uiTrackId);
- }
- }
}
},
@@ -255,18 +237,14 @@
args.tracks.forEach((track) => {
const id = track.id === undefined ? generateNextId(state) : track.id;
const name = track.name;
- const tags = track.tags ?? {name};
state.tracks[id] = {
id,
- engineId: track.engineId,
- kind: track.kind,
name,
trackSortKey: track.trackSortKey,
trackGroup: track.trackGroup,
- tags,
- config: track.config,
labels: track.labels,
uri: track.uri,
+ state: track.initialState,
};
this.fillUiTrackIdByTraceTrackId(state, track as TrackState, id);
if (track.trackGroup === SCROLLING_TRACK_GROUP) {
@@ -280,6 +258,19 @@
});
},
+ // Note: While this action has traditionally been omitted, with more and more
+ // dynamic tracks being added and existing ones being moved to plugins, it
+ // makes sense to have a generic "removeTracks" action which is un-opinionated
+ // about what type of tracks we are removing.
+ // E.g. Once debug tracks have been moved to a plugin, it makes no sense to
+ // keep the "removeDebugTrack()" action, as the core should have no concept of
+ // what debug tracks are.
+ removeTracks(state: StateDraft, args: {trackInstanceIds: string[]}) {
+ for (const trackInstanceId of args.trackInstanceIds) {
+ removeTrack(state, trackInstanceId);
+ }
+ },
+
setUtidToTrackSortKey(
state: StateDraft, args: {threadOrderingMetadata: UtidToTrackSortKey}) {
state.utidToThreadSortKey = args.threadOrderingMetadata;
@@ -294,12 +285,10 @@
// Define ID in action so a track group can be referred to without running
// the reducer.
args: {
- engineId: string; name: string; id: string; summaryTrackId: string;
- collapsed: boolean;
+ name: string; id: string; summaryTrackId: string; collapsed: boolean;
fixedOrdering?: boolean;
}): void {
state.trackGroups[args.id] = {
- engineId: args.engineId,
name: args.name,
id: args.id,
collapsed: args.collapsed,
@@ -308,66 +297,6 @@
};
},
- addDebugSliceTrack(
- state: StateDraft,
- args: {engineId: string, name: string, config: DebugTrackV2Config}):
- void {
- const trackId = generateNextId(state);
- this.addTrack(state, {
- id: trackId,
- engineId: args.engineId,
- name: args.name,
- trackSortKey: PrimaryTrackSortKey.DEBUG_TRACK,
- trackGroup: SCROLLING_TRACK_GROUP,
- kind: DEBUG_SLICE_TRACK_KIND,
- config: args.config,
- });
- this.toggleTrackPinned(state, {trackId});
- },
-
- addDebugCounterTrack(state: StateDraft, args: {
- engineId: string,
- name: string,
- config: CounterDebugTrackConfig,
- }): void {
- const trackId = generateNextId(state);
- this.addTrack(state, {
- id: trackId,
- engineId: args.engineId,
- name: args.name,
- trackSortKey: PrimaryTrackSortKey.DEBUG_TRACK,
- trackGroup: SCROLLING_TRACK_GROUP,
- kind: DEBUG_COUNTER_TRACK_KIND,
- config: args.config,
- });
- this.toggleTrackPinned(state, {trackId});
- },
-
-
- removeDebugTrack(state: StateDraft, args: {trackId: string}): void {
- const track = state.tracks[args.trackId];
- if (track !== undefined) {
- assertTrue(
- track.kind === DEBUG_SLICE_TRACK_KIND ||
- track.kind === DEBUG_COUNTER_TRACK_KIND);
- removeTrack(state, args.trackId);
- }
- },
-
- removeVisualisedArgTracks(state: StateDraft, args: {trackIds: string[]}) {
- for (const trackId of args.trackIds) {
- const track = state.tracks[trackId];
-
- const namespace = (track.config as {namespace?: string}).namespace;
- if (namespace === undefined) {
- throw new Error(
- 'All visualised arg tracks should have non-empty namespace');
- }
-
- removeTrack(state, trackId);
- }
- },
-
maybeExpandOnlyTrackGroup(state: StateDraft, _: {}): void {
const trackGroups = Object.values(state.trackGroups);
if (trackGroups.length === 1) {
@@ -827,7 +756,7 @@
selectChromeSlice(
state: StateDraft,
- args: {id: number, trackId: string, table: string, scroll?: boolean}):
+ args: {id: number, trackId: string, table?: string, scroll?: boolean}):
void {
state.currentSelection = {
kind: 'CHROME_SLICE',
@@ -1164,17 +1093,6 @@
}));
},
- addVisualisedArg(state: StateDraft, args: {argName: string}) {
- if (!state.visualisedArgs.includes(args.argName)) {
- state.visualisedArgs.push(args.argName);
- }
- },
-
- removeVisualisedArg(state: StateDraft, args: {argName: string}) {
- state.visualisedArgs =
- state.visualisedArgs.filter((val) => val !== args.argName);
- },
-
setPivotTableArgumentNames(
state: StateDraft, args: {argumentNames: string[]}) {
state.nonSerializableState.pivotTable.argumentNames = args.argumentNames;
diff --git a/ui/src/common/actions_unittest.ts b/ui/src/common/actions_unittest.ts
index 8713c17..40c6949 100644
--- a/ui/src/common/actions_unittest.ts
+++ b/ui/src/common/actions_unittest.ts
@@ -37,7 +37,7 @@
function fakeTrack(state: State, args: {
id: string,
- kind?: string,
+ uri?: string,
trackGroup?: string,
trackSortKey?: TrackSortKey,
name?: string,
@@ -45,15 +45,13 @@
}): State {
return produce(state, (draft) => {
StateActions.addTrack(draft, {
+ uri: args.uri || 'sometrack',
id: args.id,
- engineId: '0',
- kind: args.kind || 'SOME_TRACK_KIND',
name: args.name || 'A track',
trackSortKey: args.trackSortKey === undefined ?
PrimaryTrackSortKey.ORDINARY_TRACK :
args.trackSortKey,
trackGroup: args.trackGroup || SCROLLING_TRACK_GROUP,
- config: {tid: args.tid || '0'},
});
});
}
@@ -64,7 +62,6 @@
StateActions.addTrackGroup(draft, {
name: 'A group',
id: args.id,
- engineId: '0',
collapsed: false,
summaryTrackId: args.summaryTrackId,
});
@@ -89,22 +86,18 @@
test('add scrolling tracks', () => {
const once = produce(createEmptyState(), (draft) => {
StateActions.addTrack(draft, {
- engineId: '1',
- kind: 'cpu',
+ uri: 'cpu',
name: 'Cpu 1',
trackSortKey: PrimaryTrackSortKey.ORDINARY_TRACK,
trackGroup: SCROLLING_TRACK_GROUP,
- config: {},
});
});
const twice = produce(once, (draft) => {
StateActions.addTrack(draft, {
- engineId: '2',
- kind: 'cpu',
+ uri: 'cpu',
name: 'Cpu 2',
trackSortKey: PrimaryTrackSortKey.ORDINARY_TRACK,
trackGroup: SCROLLING_TRACK_GROUP,
- config: {},
});
});
@@ -118,7 +111,6 @@
const afterGroup = produce(state, (draft) => {
StateActions.addTrackGroup(draft, {
- engineId: '1',
name: 'A track group',
id: '123-123-123',
summaryTrackId: 's',
@@ -129,12 +121,10 @@
const afterTrackAdd = produce(afterGroup, (draft) => {
StateActions.addTrack(draft, {
id: '1',
- engineId: '1',
- kind: 'slices',
+ uri: 'slices',
name: 'renderer 1',
trackSortKey: PrimaryTrackSortKey.ORDINARY_TRACK,
trackGroup: '123-123-123',
- config: {},
});
});
@@ -145,18 +135,14 @@
test('reorder tracks', () => {
const once = produce(createEmptyState(), (draft) => {
StateActions.addTrack(draft, {
- engineId: '1',
- kind: 'cpu',
+ uri: 'cpu',
name: 'Cpu 1',
trackSortKey: PrimaryTrackSortKey.ORDINARY_TRACK,
- config: {},
});
StateActions.addTrack(draft, {
- engineId: '2',
- kind: 'cpu',
+ uri: 'cpu',
name: 'Cpu 2',
trackSortKey: PrimaryTrackSortKey.ORDINARY_TRACK,
- config: {},
});
});
@@ -285,11 +271,9 @@
const twice = produce(once, (draft) => {
StateActions.addTrack(draft, {
- engineId: '1',
- kind: 'cpu',
+ uri: 'cpu',
name: 'Cpu 1',
trackSortKey: PrimaryTrackSortKey.ORDINARY_TRACK,
- config: {},
});
});
@@ -332,13 +316,13 @@
state = fakeTrackGroup(state, {id: 'g', summaryTrackId: 'b'});
state = fakeTrack(state, {
id: 'b',
- kind: HEAP_PROFILE_TRACK_KIND,
+ uri: HEAP_PROFILE_TRACK_KIND,
trackSortKey: PrimaryTrackSortKey.HEAP_PROFILE_TRACK,
trackGroup: 'g',
});
state = fakeTrack(state, {
id: 'a',
- kind: PROCESS_SCHEDULING_TRACK_KIND,
+ uri: PROCESS_SCHEDULING_TRACK_KIND,
trackSortKey: PrimaryTrackSortKey.PROCESS_SCHEDULING_TRACK,
trackGroup: 'g',
});
@@ -357,34 +341,34 @@
state = fakeTrackGroup(state, {id: 'g', summaryTrackId: 'b'});
state = fakeTrack(state, {
id: 'a',
- kind: PROCESS_SCHEDULING_TRACK_KIND,
+ uri: PROCESS_SCHEDULING_TRACK_KIND,
trackSortKey: PrimaryTrackSortKey.PROCESS_SCHEDULING_TRACK,
trackGroup: 'g',
});
state = fakeTrack(state, {
id: 'b',
- kind: SLICE_TRACK_KIND,
+ uri: SLICE_TRACK_KIND,
trackGroup: 'g',
trackSortKey: PrimaryTrackSortKey.MAIN_THREAD,
});
state = fakeTrack(state, {
id: 'c',
- kind: SLICE_TRACK_KIND,
+ uri: SLICE_TRACK_KIND,
trackGroup: 'g',
trackSortKey: PrimaryTrackSortKey.RENDER_THREAD,
});
state = fakeTrack(state, {
id: 'd',
- kind: SLICE_TRACK_KIND,
+ uri: SLICE_TRACK_KIND,
trackGroup: 'g',
trackSortKey: PrimaryTrackSortKey.GPU_COMPLETION_THREAD,
});
state = fakeTrack(
- state, {id: 'e', kind: HEAP_PROFILE_TRACK_KIND, trackGroup: 'g'});
+ state, {id: 'e', uri: HEAP_PROFILE_TRACK_KIND, trackGroup: 'g'});
state = fakeTrack(
- state, {id: 'f', kind: SLICE_TRACK_KIND, trackGroup: 'g', name: 'T2'});
+ state, {id: 'f', uri: SLICE_TRACK_KIND, trackGroup: 'g', name: 'T2'});
state = fakeTrack(
- state, {id: 'g', kind: SLICE_TRACK_KIND, trackGroup: 'g', name: 'T10'});
+ state, {id: 'g', uri: SLICE_TRACK_KIND, trackGroup: 'g', name: 'T10'});
const after = produce(state, (draft) => {
StateActions.sortThreadTracks(draft, {});
@@ -404,7 +388,7 @@
state = fakeTrackGroup(state, {id: 'g', summaryTrackId: 'a'});
state = fakeTrack(state, {
id: 'a',
- kind: SLICE_TRACK_KIND,
+ uri: SLICE_TRACK_KIND,
trackSortKey: {
utid: 1,
priority: InThreadTrackSortKey.ORDINARY,
@@ -415,7 +399,7 @@
});
state = fakeTrack(state, {
id: 'b',
- kind: SLICE_TRACK_KIND,
+ uri: SLICE_TRACK_KIND,
trackSortKey: {
utid: 2,
priority: InThreadTrackSortKey.ORDINARY,
@@ -426,7 +410,7 @@
});
state = fakeTrack(state, {
id: 'c',
- kind: THREAD_STATE_TRACK_KIND,
+ uri: THREAD_STATE_TRACK_KIND,
trackSortKey: {
utid: 1,
priority: InThreadTrackSortKey.ORDINARY,
diff --git a/ui/src/common/basic_async_track.ts b/ui/src/common/basic_async_track.ts
index 2faf829..2f62dc6 100644
--- a/ui/src/common/basic_async_track.ts
+++ b/ui/src/common/basic_async_track.ts
@@ -19,7 +19,6 @@
import {globals} from '../frontend/globals';
import {PxSpan, TimeScale} from '../frontend/time_scale';
import {SliceRect} from '../frontend/track';
-import {TrackButtonAttrs} from '../frontend/track_panel';
import {Track} from '../public';
import {TrackData} from './track_data';
@@ -67,14 +66,10 @@
abstract getHeight(): number;
- getTrackShellButtons(): m.Vnode<TrackButtonAttrs, {}>[] {
+ getTrackShellButtons(): m.Children {
return [];
}
- getContextMenu(): m.Vnode<any, {}>|null {
- return null;
- }
-
onMouseMove(_position: {x: number; y: number;}): void {}
onMouseClick(_position: {x: number; y: number;}): boolean {
diff --git a/ui/src/common/empty_state.ts b/ui/src/common/empty_state.ts
index 23644e5..92ab59a 100644
--- a/ui/src/common/empty_state.ts
+++ b/ui/src/common/empty_state.ts
@@ -104,7 +104,6 @@
queries: {},
permalink: {},
notes: {},
- visualisedArgs: [],
recordConfig: AUTOLOAD_STARTED_CONFIG_FLAG.get() ?
autosaveConfigStore.get() :
diff --git a/ui/src/common/plugins.ts b/ui/src/common/plugins.ts
index 13a4e10..5ae6851 100644
--- a/ui/src/common/plugins.ts
+++ b/ui/src/common/plugins.ts
@@ -15,13 +15,7 @@
import {Disposable, Trash} from '../base/disposable';
import {assertFalse} from '../base/logging';
import {ViewerImpl, ViewerProxy} from '../common/viewer';
-import {
- TrackControllerFactory,
- trackControllerRegistry,
-} from '../controller/track_controller';
import {globals} from '../frontend/globals';
-import {TrackCreator} from '../frontend/track';
-import {trackRegistry} from '../frontend/track_registry';
import {
BasePlugin,
Command,
@@ -73,18 +67,6 @@
});
}
- LEGACY_registerTrackController(track: TrackControllerFactory): void {
- if (!this.alive) return;
- const unregister = trackControllerRegistry.register(track);
- this.trash.add(unregister);
- }
-
- LEGACY_registerTrack(track: TrackCreator): void {
- if (!this.alive) return;
- const unregister = trackRegistry.register(track);
- this.trash.add(unregister);
- }
-
dispose(): void {
this.trash.dispose();
this.alive = false;
@@ -109,18 +91,6 @@
this.trash.add(store);
}
- LEGACY_registerTrackController(track: TrackControllerFactory): void {
- // Silently ignore if context is dead.
- if (!this.alive) return;
- this.ctx.LEGACY_registerTrackController(track);
- }
-
- LEGACY_registerTrack(track: TrackCreator): void {
- // Silently ignore if context is dead.
- if (!this.alive) return;
- this.ctx.LEGACY_registerTrack(track);
- }
-
addCommand(cmd: Command): void {
// Silently ignore if context is dead.
if (!this.alive) return;
diff --git a/ui/src/common/state.ts b/ui/src/common/state.ts
index 798d7dc..2b69f0d 100644
--- a/ui/src/common/state.ts
+++ b/ui/src/common/state.ts
@@ -23,7 +23,7 @@
PivotTree,
TableColumn,
} from '../frontend/pivot_table_types';
-import {PrimaryTrackSortKey, TrackTags} from '../public/index';
+import {PrimaryTrackSortKey} from '../public/index';
import {Direction} from './event_set';
@@ -123,7 +123,8 @@
// state entries now require a URI and old track implementations are no
// longer registered.
// 40. Ported counter, process summary/sched, & cpu_freq to plugin tracks.
-export const STATE_VERSION = 40;
+// 41. Ported all remaining tracks.
+export const STATE_VERSION = 41;
export const SCROLLING_TRACK_GROUP = 'ScrollingTracks';
@@ -218,25 +219,17 @@
TraceFileSource|TraceArrayBufferSource|TraceUrlSource|TraceHttpRpcSource;
export interface TrackState {
+ uri: string;
id: string;
- engineId: string;
- kind: string;
name: string;
labels?: string[];
trackSortKey: TrackSortKey;
trackGroup?: string;
- tags: TrackTags;
- config: {
- trackId?: number;
- trackIds?: number[];
- };
- uri?: string;
state?: unknown;
}
export interface TrackGroupState {
id: string;
- engineId: string;
name: string;
collapsed: boolean;
tracks: string[]; // Child track ids.
@@ -350,7 +343,7 @@
export interface ChromeSliceSelection {
kind: 'CHROME_SLICE';
id: number;
- table: string;
+ table?: string;
}
export interface ThreadStateSelection {
@@ -554,7 +547,6 @@
ftracePagination: Pagination;
ftraceFilter: FtraceFilterState;
traceConversionInProgress: boolean;
- visualisedArgs: string[];
/**
* This state is updated on the frontend at 60Hz and eventually syncronised to
diff --git a/ui/src/common/state_unittest.ts b/ui/src/common/state_unittest.ts
index 34646ba..23832af 100644
--- a/ui/src/common/state_unittest.ts
+++ b/ui/src/common/state_unittest.ts
@@ -27,23 +27,17 @@
const state: State = createEmptyState();
state.tracks['a'] = {
id: 'a',
- engineId: 'engine',
- kind: 'Foo',
+ uri: 'Foo',
name: 'a track',
trackSortKey: PrimaryTrackSortKey.ORDINARY_TRACK,
- config: {},
- tags: {},
};
state.tracks['b'] = {
id: 'b',
- engineId: 'engine',
- kind: 'Foo',
+ uri: 'Foo',
name: 'b track',
trackSortKey: PrimaryTrackSortKey.ORDINARY_TRACK,
- config: {},
trackGroup: 'containsB',
- tags: {},
};
expect(getContainingTrackId(state, 'z')).toEqual(null);
diff --git a/ui/src/common/track_adapter.ts b/ui/src/common/track_adapter.ts
index 1c145d3..ffd7da8 100644
--- a/ui/src/common/track_adapter.ts
+++ b/ui/src/common/track_adapter.ts
@@ -20,7 +20,6 @@
import {EngineProxy} from '../common/engine';
import {PxSpan, TimeScale} from '../frontend/time_scale';
import {NewTrackArgs, SliceRect} from '../frontend/track';
-import {TrackButtonAttrs} from '../frontend/track_panel';
import {BasicAsyncTrack} from './basic_async_track';
@@ -76,14 +75,10 @@
return this.track.getHeight();
}
- getTrackShellButtons(): m.Vnode<TrackButtonAttrs, {}>[] {
+ getTrackShellButtons(): m.Children {
return this.track.getTrackShellButtons();
}
- getContextMenu(): m.Vnode<any, {}>|null {
- return this.track.getContextMenu();
- }
-
onMouseMove(position: {x: number; y: number;}): void {
this.track.onMouseMove(position);
}
@@ -155,14 +150,10 @@
return 40;
}
- getTrackShellButtons(): Array<m.Vnode<TrackButtonAttrs>> {
+ getTrackShellButtons(): m.Children {
return [];
}
- getContextMenu(): m.Vnode<any>|null {
- return null;
- }
-
onMouseMove(_position: {x: number, y: number}) {}
// Returns whether the mouse click has selected something.
diff --git a/ui/src/controller/aggregation/frame_aggregation_controller.ts b/ui/src/controller/aggregation/frame_aggregation_controller.ts
index a22a83d..2ad94d0 100644
--- a/ui/src/controller/aggregation/frame_aggregation_controller.ts
+++ b/ui/src/controller/aggregation/frame_aggregation_controller.ts
@@ -14,12 +14,10 @@
import {ColumnDef} from '../../common/aggregation_data';
import {Engine} from '../../common/engine';
+import {pluginManager} from '../../common/plugins';
import {Area, Sorting} from '../../common/state';
import {globals} from '../../frontend/globals';
-import {
- ACTUAL_FRAMES_SLICE_TRACK_KIND,
- Config,
-} from '../../tracks/actual_frames';
+import {ACTUAL_FRAMES_SLICE_TRACK_KIND} from '../../tracks/actual_frames';
import {AggregationController} from './aggregation_controller';
@@ -27,13 +25,15 @@
async createAggregateView(engine: Engine, area: Area) {
await engine.query(`drop view if exists ${this.kind};`);
- const selectedSqlTrackIds = [];
+ const selectedSqlTrackIds: number[] = [];
for (const trackId of area.tracks) {
const track = globals.state.tracks[trackId];
// Track will be undefined for track groups.
- if (track !== undefined &&
- track.kind === ACTUAL_FRAMES_SLICE_TRACK_KIND) {
- selectedSqlTrackIds.push((track.config as Config).trackIds);
+ if (track?.uri !== undefined) {
+ const trackInfo = pluginManager.resolveTrackInfo(track.uri);
+ if (trackInfo?.kind === ACTUAL_FRAMES_SLICE_TRACK_KIND) {
+ trackInfo.trackIds && selectedSqlTrackIds.push(...trackInfo.trackIds);
+ }
}
}
if (selectedSqlTrackIds.length === 0) return false;
diff --git a/ui/src/controller/aggregation/slice_aggregation_controller.ts b/ui/src/controller/aggregation/slice_aggregation_controller.ts
index 8dcaccc..4a2bfa4 100644
--- a/ui/src/controller/aggregation/slice_aggregation_controller.ts
+++ b/ui/src/controller/aggregation/slice_aggregation_controller.ts
@@ -14,33 +14,26 @@
import {ColumnDef} from '../../common/aggregation_data';
import {Engine} from '../../common/engine';
+import {pluginManager} from '../../common/plugins';
import {Area, Sorting} from '../../common/state';
import {globals} from '../../frontend/globals';
-import {
- ASYNC_SLICE_TRACK_KIND,
- Config as AsyncSliceConfig,
-} from '../../tracks/async_slices';
-import {
- Config as SliceConfig,
- SLICE_TRACK_KIND,
-} from '../../tracks/chrome_slices';
+import {ASYNC_SLICE_TRACK_KIND} from '../../tracks/async_slices';
+import {SLICE_TRACK_KIND} from '../../tracks/chrome_slices';
import {AggregationController} from './aggregation_controller';
export function getSelectedTrackIds(area: Area): number[] {
- const selectedTrackIds = [];
+ const selectedTrackIds: number[] = [];
for (const trackId of area.tracks) {
const track = globals.state.tracks[trackId];
// Track will be undefined for track groups.
- if (track !== undefined) {
- if (track.kind === SLICE_TRACK_KIND) {
- selectedTrackIds.push((track.config as SliceConfig).trackId);
+ if (track?.uri !== undefined) {
+ const trackInfo = pluginManager.resolveTrackInfo(track.uri);
+ if (trackInfo?.kind === SLICE_TRACK_KIND) {
+ trackInfo.trackIds && selectedTrackIds.push(...trackInfo.trackIds);
}
- if (track.kind === ASYNC_SLICE_TRACK_KIND) {
- const config = track.config as AsyncSliceConfig;
- for (const id of config.trackIds) {
- selectedTrackIds.push(id);
- }
+ if (trackInfo?.kind === ASYNC_SLICE_TRACK_KIND) {
+ trackInfo.trackIds && selectedTrackIds.push(...trackInfo.trackIds);
}
}
}
diff --git a/ui/src/controller/aggregation/thread_aggregation_controller.ts b/ui/src/controller/aggregation/thread_aggregation_controller.ts
index 7436a57..6818cfb 100644
--- a/ui/src/controller/aggregation/thread_aggregation_controller.ts
+++ b/ui/src/controller/aggregation/thread_aggregation_controller.ts
@@ -14,14 +14,12 @@
import {ColumnDef, ThreadStateExtra} from '../../common/aggregation_data';
import {Engine} from '../../common/engine';
+import {pluginManager} from '../../common/plugins';
import {NUM, NUM_NULL, STR_NULL} from '../../common/query_result';
import {Area, Sorting} from '../../common/state';
import {translateState} from '../../common/thread_state';
import {globals} from '../../frontend/globals';
-import {
- Config,
- THREAD_STATE_TRACK_KIND,
-} from '../../tracks/thread_state';
+import {THREAD_STATE_TRACK_KIND} from '../../tracks/thread_state';
import {AggregationController} from './aggregation_controller';
@@ -33,8 +31,11 @@
for (const trackId of tracks) {
const track = globals.state.tracks[trackId];
// Track will be undefined for track groups.
- if (track !== undefined && track.kind === THREAD_STATE_TRACK_KIND) {
- this.utids.push((track.config as Config).utid);
+ if (track?.uri) {
+ const trackInfo = pluginManager.resolveTrackInfo(track.uri);
+ if (trackInfo?.kind === THREAD_STATE_TRACK_KIND) {
+ trackInfo.utid && this.utids.push(trackInfo.utid);
+ }
}
}
}
diff --git a/ui/src/controller/flamegraph_controller.ts b/ui/src/controller/flamegraph_controller.ts
index 20bdb04..c9e6f02 100644
--- a/ui/src/controller/flamegraph_controller.ts
+++ b/ui/src/controller/flamegraph_controller.ts
@@ -26,14 +26,12 @@
PERF_SAMPLES_KEY,
SPACE_MEMORY_ALLOCATED_NOT_FREED_KEY,
} from '../common/flamegraph_util';
+import {pluginManager} from '../common/plugins';
import {NUM, STR} from '../common/query_result';
import {CallsiteInfo, FlamegraphState, ProfileType} from '../common/state';
import {FlamegraphDetails, globals} from '../frontend/globals';
import {publishFlamegraphDetails} from '../frontend/publish';
-import {
- Config as PerfSampleConfig,
- PERF_SAMPLES_PROFILE_TRACK_KIND,
-} from '../tracks/perf_samples_profile';
+import {PERF_SAMPLES_PROFILE_TRACK_KIND} from '../tracks/perf_samples_profile';
import {AreaSelectionHandler} from './area_selection_handler';
import {Controller} from './controller';
@@ -131,12 +129,13 @@
return;
}
for (const trackId of area.tracks) {
- const trackState = globals.state.tracks[trackId];
- if (!trackState ||
- trackState.kind !== PERF_SAMPLES_PROFILE_TRACK_KIND) {
- continue;
+ const track = globals.state.tracks[trackId];
+ if (track?.uri) {
+ const trackInfo = pluginManager.resolveTrackInfo(track.uri);
+ if (trackInfo?.kind === PERF_SAMPLES_PROFILE_TRACK_KIND) {
+ trackInfo.upid && upids.push(trackInfo.upid);
+ }
}
- upids.push((trackState.config as PerfSampleConfig).upid);
}
if (upids.length === 0) {
this.checkCompletionAndPublishFlamegraph(
diff --git a/ui/src/controller/flow_events_controller.ts b/ui/src/controller/flow_events_controller.ts
index a1c4170..fd5afb2 100644
--- a/ui/src/controller/flow_events_controller.ts
+++ b/ui/src/controller/flow_events_controller.ts
@@ -21,14 +21,8 @@
import {Flow, globals} from '../frontend/globals';
import {publishConnectedFlows, publishSelectedFlows} from '../frontend/publish';
import {asSliceSqlId} from '../frontend/sql_types';
-import {
- ACTUAL_FRAMES_SLICE_TRACK_KIND,
- Config as ActualConfig,
-} from '../tracks/actual_frames';
-import {
- Config as SliceConfig,
- SLICE_TRACK_KIND,
-} from '../tracks/chrome_slices';
+import {ACTUAL_FRAMES_SLICE_TRACK_KIND} from '../tracks/actual_frames';
+import {SLICE_TRACK_KIND} from '../tracks/chrome_slices';
import {Controller} from './controller';
@@ -237,24 +231,14 @@
// anything if there is only one TP track in this async track. In
// that case experimental_slice_layout is just an expensive way
// to find out depth === layout_depth.
- const trackIds = track.config.trackIds;
+ const trackInfo = pluginManager.resolveTrackInfo(track.uri);
+ const trackIds = trackInfo?.trackIds;
if (trackIds === undefined || trackIds.length <= 1) {
uiTrackIdToInfo.set(uiTrackId, null);
trackIdToInfo.set(trackId, null);
return null;
}
- // Perform the same check for "plugin" style tracks.
- if (track.uri) {
- const trackInfo = pluginManager.resolveTrackInfo(track.uri);
- const trackIds = trackInfo?.trackIds;
- if (trackIds === undefined || trackIds.length <= 1) {
- uiTrackIdToInfo.set(uiTrackId, null);
- trackIdToInfo.set(trackId, null);
- return null;
- }
- }
-
const newInfo = {
uiTrackId,
siblingTrackIds: trackIds,
@@ -390,19 +374,16 @@
for (const uiTrackId of area.tracks) {
const track = globals.state.tracks[uiTrackId];
- if (track === undefined) {
- continue;
- }
- if (track.kind === SLICE_TRACK_KIND) {
- trackIds.push((track.config as SliceConfig).trackId);
- } else if (track.kind === ACTUAL_FRAMES_SLICE_TRACK_KIND) {
- const actualConfig = track.config as ActualConfig;
- for (const trackId of actualConfig.trackIds) {
- trackIds.push(trackId);
- }
- } else if (track.config.trackIds !== undefined) {
- for (const trackId of track.config.trackIds) {
- trackIds.push(trackId);
+ if (track?.uri !== undefined) {
+ const trackInfo = pluginManager.resolveTrackInfo(track.uri);
+ const kind = trackInfo?.kind;
+ if (kind === SLICE_TRACK_KIND ||
+ kind === ACTUAL_FRAMES_SLICE_TRACK_KIND) {
+ if (trackInfo?.trackIds) {
+ for (const trackId of trackInfo.trackIds) {
+ trackIds.push(trackId);
+ }
+ }
}
}
}
diff --git a/ui/src/controller/search_controller.ts b/ui/src/controller/search_controller.ts
index 6055221..306c43f 100644
--- a/ui/src/controller/search_controller.ts
+++ b/ui/src/controller/search_controller.ts
@@ -282,8 +282,11 @@
} else if (it.source === 'track') {
trackId = globals.state.uiTrackIdByTraceTrackId[it.sourceId];
} else if (it.source === 'log') {
- const logTracks = Object.values(globals.state.tracks)
- .filter((t) => t.kind === 'AndroidLogTrack');
+ const logTracks =
+ Object.values(globals.state.tracks).filter((track) => {
+ const trackDesc = pluginManager.resolveTrackInfo(track.uri);
+ return (trackDesc && trackDesc.kind === 'AndroidLogTrack');
+ });
if (logTracks.length > 0) {
trackId = logTracks[0].id;
}
diff --git a/ui/src/controller/selection_controller.ts b/ui/src/controller/selection_controller.ts
index b2c8ee5..e6df129 100644
--- a/ui/src/controller/selection_controller.ts
+++ b/ui/src/controller/selection_controller.ts
@@ -16,6 +16,7 @@
import {Time, time} from '../base/time';
import {Args, ArgValue} from '../common/arg_types';
import {Engine} from '../common/engine';
+import {pluginManager} from '../common/plugins';
import {
durationFromSql,
LONG,
@@ -308,10 +309,15 @@
// UI track id for slice tracks this would be unnecessary.
let trackId = '';
for (const track of Object.values(globals.state.tracks)) {
- if (track.kind === SLICE_TRACK_KIND &&
- (track.config as {trackId: number}).trackId === Number(trackIdTp)) {
- trackId = track.id;
- break;
+ if (track.uri) {
+ const trackInfo = pluginManager.resolveTrackInfo(track.uri);
+ if (trackInfo?.kind === SLICE_TRACK_KIND) {
+ const trackIds = trackInfo?.trackIds;
+ if (trackIds && trackIds.length > 0 && trackIds[0] === trackIdTp) {
+ trackId = track.id;
+ break;
+ }
+ }
}
}
return trackId;
diff --git a/ui/src/controller/trace_controller.ts b/ui/src/controller/trace_controller.ts
index 31000d6..438cb1f 100644
--- a/ui/src/controller/trace_controller.ts
+++ b/ui/src/controller/trace_controller.ts
@@ -128,9 +128,7 @@
TraceHttpStream,
TraceStream,
} from './trace_stream';
-import {TrackControllerArgs, trackControllerRegistry} from './track_controller';
import {decideTracks} from './track_decider';
-import {VisualisedArgController} from './visualised_args_controller';
type States = 'init' | 'loading_trace' | 'ready';
@@ -217,6 +215,31 @@
});
}
+// TODO(stevegolton): Move this into some global "SQL extensions" file and
+// ensure it's only run once.
+async function defineMaxLayoutDepthSqlFunction(engine: Engine): Promise<void> {
+ await engine.query(`
+ select create_function(
+ 'max_layout_depth(track_count INT, track_ids STRING)',
+ 'INT',
+ '
+ select iif(
+ $track_count = 1,
+ (
+ select max(depth)
+ from slice
+ where track_id = cast($track_ids AS int)
+ ),
+ (
+ select max(layout_depth)
+ from experimental_slice_layout($track_ids)
+ )
+ );
+ '
+ );
+ `);
+}
+
// TraceController handles handshakes with the frontend for everything that
// concerns a single trace. It owns the WASM trace processor engine, handles
// tracks data and SQL queries. There is one TraceController instance for each
@@ -262,21 +285,6 @@
const engine = assertExists(this.engine);
const childControllers: Children = [];
- // Create a TrackController for each track.
- for (const trackId of Object.keys(globals.state.tracks)) {
- const trackCfg = globals.state.tracks[trackId];
- if (trackCfg.engineId !== this.engineId) continue;
- if (!trackControllerRegistry.has(trackCfg.kind)) continue;
- const trackCtlFactory = trackControllerRegistry.get(trackCfg.kind);
- const trackArgs: TrackControllerArgs = {trackId, engine};
- childControllers.push(Child(trackId, trackCtlFactory, trackArgs));
- }
-
- for (const argName of globals.state.visualisedArgs) {
- childControllers.push(
- Child(argName, VisualisedArgController, {argName, engine}));
- }
-
const selectionArgs: SelectionControllerArgs = {engine};
childControllers.push(
Child('selection', SelectionController, selectionArgs));
@@ -499,6 +507,8 @@
// Make sure the helper views are available before we start adding tracks.
await this.initialiseHelperViews();
+ await defineMaxLayoutDepthSqlFunction(engine);
+
pluginManager.onTraceLoad(engine);
{
@@ -722,7 +732,7 @@
private async listTracks() {
this.updateStatus('Loading tracks');
const engine = assertExists<Engine>(this.engine);
- const actions = await decideTracks(this.engineId, engine);
+ const actions = await decideTracks(engine);
globals.dispatchMultiple(actions);
}
diff --git a/ui/src/controller/track_controller.ts b/ui/src/controller/track_controller.ts
deleted file mode 100644
index 539e561..0000000
--- a/ui/src/controller/track_controller.ts
+++ /dev/null
@@ -1,202 +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.
-
-import {BigintMath} from '../base/bigint_math';
-import {assertExists} from '../base/logging';
-import {duration, time, Time, TimeSpan} from '../base/time';
-import {Engine} from '../common/engine';
-import {Registry} from '../common/registry';
-import {RESOLUTION_DEFAULT, TraceTime, TrackState} from '../common/state';
-import {LIMIT, TrackData} from '../common/track_data';
-import {globals} from '../frontend/globals';
-import {publishTrackData} from '../frontend/publish';
-
-import {Controller, ControllerFactory} from './controller';
-
-interface TrackConfig {}
-
-type TrackConfigWithNamespace = TrackConfig&{namespace: string};
-
-// TrackController is a base class overridden by track implementations (e.g.,
-// sched slices, nestable slices, counters).
-export abstract class TrackController<
- Config extends TrackConfig, Data extends TrackData = TrackData> extends
- Controller<'main'> {
- readonly trackId: string;
- readonly engine: Engine;
- private data?: TrackData;
- private requestingData = false;
- private queuedRequest = false;
- private isSetup = false;
- private lastReloadHandled = 0;
-
- constructor(args: TrackControllerArgs) {
- super('main');
- this.trackId = args.trackId;
- this.engine = args.engine;
- }
-
- // Can be overriden by the track implementation to allow one time setup work
- // to be performed before the first onBoundsChange invcation.
- async onSetup() {}
-
- // Can be overriden by the track implementation to allow some one-off work
- // when requested reload (e.g. recalculating height).
- async onReload() {}
-
- // Must be overridden by the track implementation. Is invoked when the track
- // frontend runs out of cached data. The derived track controller is expected
- // to publish new track data in response to this call.
- abstract onBoundsChange(start: time, end: time, resolution: duration):
- Promise<Data>;
-
- get trackState(): TrackState {
- return assertExists(globals.state.tracks[this.trackId]);
- }
-
- get config(): Config {
- return this.trackState.config as Config;
- }
-
- configHasNamespace(config: TrackConfig): config is TrackConfigWithNamespace {
- return 'namespace' in config;
- }
-
- namespaceTable(tableName: string): string {
- if (this.configHasNamespace(this.config)) {
- return this.config.namespace + '_' + tableName;
- } else {
- return tableName;
- }
- }
-
- publish(data: Data): void {
- this.data = data;
- publishTrackData({id: this.trackId, data});
- }
-
- // Returns a valid SQL table name with the given prefix that should be unique
- // for each track.
- tableName(prefix: string) {
- // Derive table name from, since that is unique for each track.
- // Track ID can be UUID but '-' is not valid for sql table name.
- const idSuffix = this.trackId.split('-').join('_');
- return `${prefix}_${idSuffix}`;
- }
-
- shouldSummarize(resolution: number): boolean {
- // |resolution| is in s/px (to nearest power of 10) assuming a display
- // of ~1000px 0.0008 is 0.8s.
- return resolution >= 0.0008;
- }
-
- protected async query(query: string) {
- const result = await this.engine.query(query);
- return result;
- }
-
- private shouldReload(): boolean {
- const {lastTrackReloadRequest} = globals.state;
- return !!lastTrackReloadRequest &&
- this.lastReloadHandled < lastTrackReloadRequest;
- }
-
- private markReloadHandled() {
- this.lastReloadHandled = globals.state.lastTrackReloadRequest || 0;
- }
-
- shouldRequestData(traceTime: TraceTime): boolean {
- const tspan = new TimeSpan(traceTime.start, traceTime.end);
- if (this.data === undefined) return true;
- if (this.shouldReload()) return true;
-
- // If at the limit only request more data if the view has moved.
- const atLimit = this.data.length === LIMIT;
- if (atLimit) {
- // We request more data than the window, so add window duration to find
- // the previous window.
- const prevWindowStart = this.data.start + tspan.duration;
- return tspan.start !== prevWindowStart;
- }
-
- // Otherwise request more data only when out of range of current data or
- // resolution has changed.
- const inRange =
- tspan.start >= this.data.start && tspan.end <= this.data.end;
- return !inRange ||
- this.data.resolution !==
- globals.state.frontendLocalState.visibleState.resolution;
- }
-
- run() {
- const visibleState = globals.state.frontendLocalState.visibleState;
- if (visibleState === undefined) {
- return;
- }
- const visibleTimeSpan = globals.stateVisibleTime();
- const dur = visibleTimeSpan.duration;
- if (globals.state.visibleTracks.includes(this.trackId) &&
- this.shouldRequestData(visibleState)) {
- if (this.requestingData) {
- this.queuedRequest = true;
- } else {
- this.requestingData = true;
- let promise = Promise.resolve();
- if (!this.isSetup) {
- promise = this.onSetup();
- } else if (this.shouldReload()) {
- promise = this.onReload().then(() => this.markReloadHandled());
- }
- promise
- .then(() => {
- this.isSetup = true;
- let resolution = visibleState.resolution;
-
- // If resolution is not a power of 2, reset to the default value
- if (BigintMath.popcount(resolution) !== 1) {
- resolution = RESOLUTION_DEFAULT;
- }
-
- return this.onBoundsChange(
- Time.sub(visibleTimeSpan.start, dur),
- Time.add(visibleTimeSpan.end, dur),
- resolution);
- })
- .then((data) => {
- this.publish(data);
- })
- .finally(() => {
- this.requestingData = false;
- if (this.queuedRequest) {
- this.queuedRequest = false;
- this.run();
- }
- });
- }
- }
- }
-}
-
-export interface TrackControllerArgs {
- trackId: string;
- engine: Engine;
-}
-
-export interface TrackControllerFactory extends
- ControllerFactory<TrackControllerArgs> {
- kind: string;
-}
-
-export const trackControllerRegistry =
- Registry.kindRegistry<TrackControllerFactory>();
diff --git a/ui/src/controller/track_decider.ts b/ui/src/controller/track_decider.ts
index a7cec8a..b72c20a 100644
--- a/ui/src/controller/track_decider.ts
+++ b/ui/src/controller/track_decider.ts
@@ -49,20 +49,12 @@
} from '../tracks/chrome_scroll_jank/chrome_tasks_scroll_jank_track';
import {SLICE_TRACK_KIND} from '../tracks/chrome_slices';
import {COUNTER_TRACK_KIND} from '../tracks/counter';
-import {CPU_PROFILE_TRACK_KIND} from '../tracks/cpu_profile';
-import {
- EXPECTED_FRAMES_SLICE_TRACK_KIND,
-} from '../tracks/expected_frames';
-import {HEAP_PROFILE_TRACK_KIND} from '../tracks/heap_profile';
-import {NULL_TRACK_KIND} from '../tracks/null_track';
-import {
- PERF_SAMPLES_PROFILE_TRACK_KIND,
-} from '../tracks/perf_samples_profile';
+import {EXPECTED_FRAMES_SLICE_TRACK_KIND} from '../tracks/expected_frames';
+import {NULL_TRACK_URI} from '../tracks/null_track';
import {
decideTracks as screenshotDecideTracks,
} from '../tracks/screenshots';
import {THREAD_STATE_TRACK_KIND} from '../tracks/thread_state';
-import {THREAD_STATE_TRACK_V2_KIND} from '../tracks/thread_state_v2';
const TRACKS_V2_FLAG = featureFlags.register({
id: 'tracksV2.1',
@@ -79,11 +71,6 @@
defaultValue: false,
});
-// Special kind reserved for plugin tracks.
-// There is no significance to this value, it simply something that's unlikely
-// to be used as a key in the trackRegistry.
-const PLUGIN_TRACK_KIND = 'PLUGIN_TRACK';
-
function showV2(): boolean {
return TRACKS_V2_FLAG.get();
}
@@ -124,21 +111,18 @@
const CHROME_TRACK_GROUP = 'Chrome Global Tracks';
const MISC_GROUP = 'Misc Global Tracks';
-export async function decideTracks(
- engineId: string, engine: Engine): Promise<DeferredAction[]> {
- return (new TrackDecider(engineId, engine)).decideTracks();
+export async function decideTracks(engine: Engine): Promise<DeferredAction[]> {
+ return (new TrackDecider(engine)).decideTracks();
}
class TrackDecider {
- private engineId: string;
private engine: Engine;
private upidToUuid = new Map<number, string>();
private utidToUuid = new Map<number, string>();
private tracksToAdd: AddTrackArgs[] = [];
private addTrackGroupActions: DeferredAction[] = [];
- constructor(engineId: string, engine: Engine) {
- this.engineId = engineId;
+ constructor(engine: Engine) {
this.engine = engine;
}
@@ -174,13 +158,10 @@
const size = cpuToSize.get(cpu);
const name = size === undefined ? `Cpu ${cpu}` : `Cpu ${cpu} (${size})`;
this.tracksToAdd.push({
- engineId: this.engineId,
- kind: PLUGIN_TRACK_KIND,
+ uri: `perfetto.CpuSlices#cpu${cpu}`,
trackSortKey: PrimaryTrackSortKey.ORDINARY_TRACK,
name,
trackGroup: SCROLLING_TRACK_GROUP,
- config: {},
- uri: `perfetto.CpuSlices#cpu${cpu}`,
});
}
}
@@ -210,13 +191,10 @@
if (cpuFreqIdleResult.numRows() > 0) {
this.tracksToAdd.push({
- engineId: this.engineId,
- kind: PLUGIN_TRACK_KIND,
+ uri: `perfetto.CpuFreq#${cpu}`,
trackSortKey: PrimaryTrackSortKey.ORDINARY_TRACK,
name: `Cpu ${cpu} Frequency`,
trackGroup: SCROLLING_TRACK_GROUP,
- config: {},
- uri: `perfetto.CpuFreq#${cpu}`,
});
}
}
@@ -263,7 +241,6 @@
name: STR_NULL,
parentName: STR_NULL,
parentId: NUM_NULL,
- trackIds: STR,
maxDepth: NUM_NULL,
});
@@ -274,8 +251,6 @@
const rawName = it.name === null ? undefined : it.name;
const rawParentName = it.parentName === null ? undefined : it.parentName;
const name = getTrackName({name: rawName, kind});
- const rawTrackIds = it.trackIds;
- const trackIds = rawTrackIds.split(',').map((v) => Number(v));
const parentTrackId = it.parentId;
const maxDepth = it.maxDepth;
let trackGroup = SCROLLING_TRACK_GROUP;
@@ -295,17 +270,14 @@
const summaryTrackId = uuidv4();
this.tracksToAdd.push({
+ uri: NULL_TRACK_URI,
id: summaryTrackId,
- engineId: this.engineId,
- kind: NULL_TRACK_KIND,
trackSortKey: PrimaryTrackSortKey.NULL_TRACK,
trackGroup: undefined,
name: parentName,
- config: {},
});
this.addTrackGroupActions.push(Actions.addTrackGroup({
- engineId: this.engineId,
summaryTrackId,
name: parentName,
id: trackGroup,
@@ -316,16 +288,11 @@
}
}
- const track = {
- engineId: this.engineId,
- kind,
+ const track: AddTrackArgs = {
+ uri: `perfetto.AsyncSlices#${rawName}`,
trackSortKey: PrimaryTrackSortKey.ASYNC_SLICE_TRACK,
trackGroup,
name,
- config: {
- maxDepth,
- trackIds,
- },
};
this.tracksToAdd.push(track);
@@ -345,13 +312,10 @@
`);
if (freqExistsResult.numRows() > 0) {
this.tracksToAdd.push({
- engineId: this.engineId,
- kind: PLUGIN_TRACK_KIND,
+ uri: `perfetto.Counter#gpu_freq${gpu}`,
name: `Gpu ${gpu} Frequency`,
trackSortKey: PrimaryTrackSortKey.COUNTER_TRACK,
trackGroup: SCROLLING_TRACK_GROUP,
- config: {},
- uri: `perfetto.Counter#gpu_freq${gpu}`,
});
}
}
@@ -395,13 +359,10 @@
const name = it.name;
const trackId = it.id;
this.tracksToAdd.push({
- engineId: this.engineId,
- kind: PLUGIN_TRACK_KIND,
+ uri: `perfetto.Counter#cpu${trackId}`,
name,
trackSortKey: PrimaryTrackSortKey.COUNTER_TRACK,
trackGroup: SCROLLING_TRACK_GROUP,
- config: {},
- uri: `perfetto.Counter#cpu${trackId}`,
});
}
}
@@ -441,7 +402,6 @@
}
const addGroup = Actions.addTrackGroup({
- engineId: this.engineId,
summaryTrackId,
name: MEM_DMA_COUNTER_NAME,
id,
@@ -479,17 +439,14 @@
const summaryTrackId = uuidv4();
this.tracksToAdd.push({
+ uri: NULL_TRACK_URI,
id: summaryTrackId,
- engineId: this.engineId,
- kind: NULL_TRACK_KIND,
trackSortKey: PrimaryTrackSortKey.NULL_TRACK,
name: groupName,
trackGroup: undefined,
- config: {},
});
const addGroup = Actions.addTrackGroup({
- engineId: this.engineId,
summaryTrackId,
name: groupName,
id: value,
@@ -520,7 +477,6 @@
}
const addGroup = Actions.addTrackGroup({
- engineId: this.engineId,
summaryTrackId,
name: group,
id,
@@ -562,17 +518,14 @@
const summaryTrackId = uuidv4();
this.tracksToAdd.push({
+ uri: NULL_TRACK_URI,
id: summaryTrackId,
- engineId: this.engineId,
- kind: NULL_TRACK_KIND,
trackSortKey: PrimaryTrackSortKey.NULL_TRACK,
name: groupName,
trackGroup: undefined,
- config: {},
});
const addGroup = Actions.addTrackGroup({
- engineId: this.engineId,
summaryTrackId,
name: groupName,
id: value,
@@ -593,7 +546,7 @@
track.trackGroup !== SCROLLING_TRACK_GROUP) {
continue;
}
- if (track.kind === NULL_TRACK_KIND) {
+ if (track.uri === NULL_TRACK_URI) {
continue;
}
if (groupUuid === undefined) {
@@ -606,17 +559,14 @@
if (groupUuid !== undefined) {
const summaryTrackId = uuidv4();
this.tracksToAdd.push({
+ uri: NULL_TRACK_URI,
id: summaryTrackId,
- engineId: this.engineId,
- kind: NULL_TRACK_KIND,
trackSortKey: PrimaryTrackSortKey.NULL_TRACK,
name: groupName,
trackGroup: undefined,
- config: {},
});
const addGroup = Actions.addTrackGroup({
- engineId: this.engineId,
summaryTrackId,
name: groupName,
id: groupUuid,
@@ -641,7 +591,7 @@
track.trackGroup !== SCROLLING_TRACK_GROUP) {
continue;
}
- if (track.kind === NULL_TRACK_KIND) {
+ if (track.uri === NULL_TRACK_URI) {
continue;
}
let allowlisted = false;
@@ -660,17 +610,14 @@
if (groupUuid !== undefined) {
const summaryTrackId = uuidv4();
this.tracksToAdd.push({
+ uri: NULL_TRACK_URI,
id: summaryTrackId,
- engineId: this.engineId,
- kind: NULL_TRACK_KIND,
trackSortKey: PrimaryTrackSortKey.NULL_TRACK,
name: groupName,
trackGroup: undefined,
- config: {},
});
const addGroup = Actions.addTrackGroup({
- engineId: this.engineId,
summaryTrackId,
name: groupName,
id: groupUuid,
@@ -689,7 +636,7 @@
track.trackGroup !== SCROLLING_TRACK_GROUP) {
continue;
}
- if (track.kind === NULL_TRACK_KIND) {
+ if (track.uri === NULL_TRACK_URI) {
continue;
}
if (groupUuid === undefined) {
@@ -702,17 +649,14 @@
if (groupUuid !== undefined) {
const summaryTrackId = uuidv4();
this.tracksToAdd.push({
+ uri: NULL_TRACK_URI,
id: summaryTrackId,
- engineId: this.engineId,
- kind: NULL_TRACK_KIND,
trackSortKey: PrimaryTrackSortKey.NULL_TRACK,
name: groupName,
trackGroup: undefined,
- config: {},
});
const addGroup = Actions.addTrackGroup({
- engineId: this.engineId,
summaryTrackId,
name: groupName,
id: groupUuid,
@@ -729,13 +673,10 @@
if (count > 0) {
this.tracksToAdd.push({
- engineId: this.engineId,
- kind: PLUGIN_TRACK_KIND,
+ uri: 'perfetto.AndroidLog',
name: 'Android logs',
trackSortKey: PrimaryTrackSortKey.ORDINARY_TRACK,
trackGroup: SCROLLING_TRACK_GROUP,
- config: {},
- uri: 'perfetto.AndroidLog',
});
}
}
@@ -755,29 +696,23 @@
groupUuid = 'ftrace-track-group';
summaryTrackId = uuidv4();
this.tracksToAdd.push({
- engineId: this.engineId,
- kind: NULL_TRACK_KIND,
+ uri: NULL_TRACK_URI,
trackSortKey: PrimaryTrackSortKey.NULL_TRACK,
name: `Ftrace Events`,
trackGroup: undefined,
- config: {},
id: summaryTrackId,
});
}
this.tracksToAdd.push({
- engineId: this.engineId,
- kind: PLUGIN_TRACK_KIND,
+ uri: `perfetto.FtraceRaw#cpu${it.cpu}`,
trackSortKey: PrimaryTrackSortKey.ORDINARY_TRACK,
name: `Ftrace Events Cpu ${it.cpu}`,
trackGroup: groupUuid,
- config: {},
- uri: `perfetto.FtraceRaw#cpu${it.cpu}`,
});
}
if (groupUuid !== undefined && summaryTrackId !== undefined) {
const addGroup = Actions.addTrackGroup({
- engineId: this.engineId,
name: 'Ftrace Events',
id: groupUuid,
collapsed: true,
@@ -836,23 +771,16 @@
}
this.tracksToAdd.push({
+ uri: `perfetto.Annotation#${id}`,
id: summaryTrackId,
- engineId: this.engineId,
- kind: SLICE_TRACK_KIND,
name,
trackSortKey: PrimaryTrackSortKey.ORDINARY_TRACK,
trackGroup: trackGroupId,
- config: {
- maxDepth: 0,
- namespace: 'annotation',
- trackId: id,
- },
});
}
for (const [groupName, groupIds] of groupNameToIds) {
const addGroup = Actions.addTrackGroup({
- engineId: this.engineId,
summaryTrackId: groupIds.summaryTrackId,
name: groupName,
id: groupIds.id,
@@ -876,16 +804,11 @@
const name = counterIt.name;
const upid = counterIt.upid;
this.tracksToAdd.push({
- engineId: this.engineId,
- kind: PLUGIN_TRACK_KIND,
+ uri: `perfetto.Annotation#counter${id}`,
name,
trackSortKey: PrimaryTrackSortKey.COUNTER_TRACK,
trackGroup: upid === 0 ? SCROLLING_TRACK_GROUP :
this.upidToUuid.get(upid),
- config: {
- namespace: 'annotation',
- },
- uri: `perfetto.Annotation#counter${id}`,
});
}
}
@@ -930,30 +853,26 @@
if (showV1()) {
const kind = THREAD_STATE_TRACK_KIND;
this.tracksToAdd.push({
- engineId: this.engineId,
- kind: THREAD_STATE_TRACK_KIND,
+ uri: `perfetto.ThreadState#${upid}.${utid}`,
name: getTrackName({utid, tid, threadName, kind}),
trackGroup: uuid,
trackSortKey: {
utid,
priority,
},
- config: {utid, tid},
});
}
if (showV2()) {
- const kind = THREAD_STATE_TRACK_V2_KIND;
this.tracksToAdd.push({
- engineId: this.engineId,
- kind,
- name: getTrackName({utid, tid, threadName, kind}),
+ uri: `perfetto.ThreadState#${utid}.v2`,
+ name:
+ getTrackName({utid, tid, threadName, kind: 'ThreadStateTrackV2'}),
trackGroup: uuid,
trackSortKey: {
utid,
priority,
},
- config: {utid, tid},
});
}
}
@@ -987,15 +906,13 @@
const threadName = it.threadName;
const uuid = this.getUuid(utid, upid);
this.tracksToAdd.push({
- engineId: this.engineId,
- kind: CPU_PROFILE_TRACK_KIND,
+ uri: `perfetto.CpuProfile#${utid}`,
trackSortKey: {
utid,
priority: InThreadTrackSortKey.CPU_STACK_SAMPLES_TRACK,
},
name: `${threadName} (CPU Stack Samples)`,
trackGroup: uuid,
- config: {utid},
});
}
}
@@ -1040,16 +957,13 @@
threadTrack: true,
});
this.tracksToAdd.push({
- engineId: this.engineId,
- kind: PLUGIN_TRACK_KIND,
+ uri: `perfetto.Counter#thread${trackId}`,
name,
trackSortKey: {
utid,
priority: InThreadTrackSortKey.ORDINARY,
},
trackGroup: uuid,
- config: {},
- uri: `perfetto.Counter#thread${trackId}`,
});
}
}
@@ -1091,7 +1005,6 @@
const upid = it.upid;
const trackName = it.trackName;
const rawTrackIds = it.trackIds;
- const trackIds = rawTrackIds.split(',').map((v) => Number(v));
const processName = it.processName;
const pid = it.pid;
const maxDepth = it.maxDepth;
@@ -1102,20 +1015,18 @@
}
const uuid = this.getUuid(0, upid);
-
- const kind = ASYNC_SLICE_TRACK_KIND;
- const name =
- getTrackName({name: trackName, upid, pid, processName, kind});
+ const name = getTrackName({
+ name: trackName,
+ upid,
+ pid,
+ processName,
+ kind: ASYNC_SLICE_TRACK_KIND,
+ });
this.tracksToAdd.push({
- engineId: this.engineId,
- kind,
+ uri: `perfetto.AsyncSlices#process.${pid}${rawTrackIds}`,
name,
trackSortKey: PrimaryTrackSortKey.ASYNC_SLICE_TRACK,
trackGroup: uuid,
- config: {
- trackIds,
- maxDepth,
- },
});
}
}
@@ -1146,7 +1057,6 @@
const it = result.iter({
upid: NUM,
trackName: STR_NULL,
- trackIds: STR,
processName: STR_NULL,
pid: NUM_NULL,
maxDepth: NUM_NULL,
@@ -1154,8 +1064,6 @@
for (; it.valid(); it.next()) {
const upid = it.upid;
const trackName = it.trackName;
- const rawTrackIds = it.trackIds;
- const trackIds = rawTrackIds.split(',').map((v) => Number(v));
const processName = it.processName;
const pid = it.pid;
const maxDepth = it.maxDepth;
@@ -1171,15 +1079,10 @@
const name =
getTrackName({name: trackName, upid, pid, processName, kind});
this.tracksToAdd.push({
- engineId: this.engineId,
- kind,
+ uri: `perfetto.ActualFrames#${upid}`,
name,
trackSortKey: PrimaryTrackSortKey.ACTUAL_FRAMES_SLICE_TRACK,
trackGroup: uuid,
- config: {
- trackIds,
- maxDepth,
- },
});
}
}
@@ -1210,7 +1113,6 @@
const it = result.iter({
upid: NUM,
trackName: STR_NULL,
- trackIds: STR,
processName: STR_NULL,
pid: NUM_NULL,
maxDepth: NUM_NULL,
@@ -1219,8 +1121,6 @@
for (; it.valid(); it.next()) {
const upid = it.upid;
const trackName = it.trackName;
- const rawTrackIds = it.trackIds;
- const trackIds = rawTrackIds.split(',').map((v) => Number(v));
const processName = it.processName;
const pid = it.pid;
const maxDepth = it.maxDepth;
@@ -1236,15 +1136,10 @@
const name =
getTrackName({name: trackName, upid, pid, processName, kind});
this.tracksToAdd.push({
- engineId: this.engineId,
- kind,
+ uri: `perfetto.ExpectedFrames#${upid}`,
name,
trackSortKey: PrimaryTrackSortKey.EXPECTED_FRAMES_SLICE_TRACK,
trackGroup: uuid,
- config: {
- trackIds,
- maxDepth,
- },
});
}
}
@@ -1259,7 +1154,6 @@
'is_root_in_scope') as isDefaultTrackForScope,
tid,
thread.name as threadName,
- max(slice.depth) as maxDepth,
process.upid as upid
from slice
join thread_track on slice.track_id = thread_track.id
@@ -1275,7 +1169,6 @@
isDefaultTrackForScope: NUM_NULL,
tid: NUM_NULL,
threadName: STR_NULL,
- maxDepth: NUM,
upid: NUM_NULL,
});
for (; it.valid(); it.next()) {
@@ -1287,7 +1180,6 @@
const tid = it.tid;
const threadName = it.threadName;
const upid = it.upid;
- const maxDepth = it.maxDepth;
const uuid = this.getUuid(utid, upid);
@@ -1295,8 +1187,7 @@
const name = getTrackName({name: trackName, utid, tid, threadName, kind});
if (showV1()) {
this.tracksToAdd.push({
- engineId: this.engineId,
- kind,
+ uri: `perfetto.ChromeSlices#${trackId}`,
name,
trackGroup: uuid,
trackSortKey: {
@@ -1305,18 +1196,12 @@
InThreadTrackSortKey.DEFAULT_TRACK :
InThreadTrackSortKey.ORDINARY,
},
- config: {
- trackId,
- maxDepth,
- tid,
- },
});
}
if (showV2()) {
this.tracksToAdd.push({
- engineId: this.engineId,
- kind: 'GenericSliceTrack',
+ uri: `perfetto.ChromeSlices#${trackId}.v2`,
name,
trackGroup: uuid,
trackSortKey: {
@@ -1325,7 +1210,6 @@
InThreadTrackSortKey.DEFAULT_TRACK :
InThreadTrackSortKey.ORDINARY,
},
- config: {sqlTrackId: trackId},
});
}
}
@@ -1359,14 +1243,11 @@
const name = getTrackName(
{name: trackName, upid, pid, kind: COUNTER_TRACK_KIND, processName});
this.tracksToAdd.push({
- engineId: this.engineId,
- kind: PLUGIN_TRACK_KIND,
+ uri: `perfetto.Counter#process${trackId}`,
name,
trackSortKey: await this.resolveTrackSortKeyForProcessCounterTrack(
upid, trackName || undefined),
trackGroup: uuid,
- config: {},
- uri: `perfetto.Counter#process${trackId}`,
});
}
}
@@ -1381,12 +1262,10 @@
const upid = it.upid;
const uuid = this.getUuid(0, upid);
this.tracksToAdd.push({
- engineId: this.engineId,
- kind: HEAP_PROFILE_TRACK_KIND,
+ uri: `perfetto.HeapProfile#${upid}`,
trackSortKey: PrimaryTrackSortKey.HEAP_PROFILE_TRACK,
name: `Heap Profile`,
trackGroup: uuid,
- config: {upid},
});
}
}
@@ -1402,12 +1281,10 @@
const pid = it.pid;
const uuid = this.getUuid(0, upid);
this.tracksToAdd.push({
- engineId: this.engineId,
- kind: PERF_SAMPLES_PROFILE_TRACK_KIND,
+ uri: `perfetto.PerfSamplesProfile#${upid}`,
trackSortKey: PrimaryTrackSortKey.PERF_SAMPLES_PROFILE_TRACK,
name: `Callstacks ${pid}`,
trackGroup: uuid,
- config: {upid},
});
}
}
@@ -1482,16 +1359,12 @@
const kthreadGroupUuid = uuidv4();
const summaryTrackId = uuidv4();
this.tracksToAdd.push({
+ uri: 'perfetto.ProcessSummary#kernel',
id: summaryTrackId,
- engineId: this.engineId,
- kind: PLUGIN_TRACK_KIND,
trackSortKey: PrimaryTrackSortKey.PROCESS_SUMMARY_TRACK,
name: `Kernel thread summary`,
- config: {},
- uri: 'perfetto.ProcessSummary#kernel',
});
const addTrackGroup = Actions.addTrackGroup({
- engineId: this.engineId,
summaryTrackId,
name: `Kernel threads`,
id: kthreadGroupUuid,
@@ -1659,22 +1532,18 @@
const uri = `perfetto.ProcessScheduling#${upid}.${utid}.${type}`;
this.tracksToAdd.push({
+ uri,
id: summaryTrackId,
- engineId: this.engineId,
- kind: PLUGIN_TRACK_KIND,
trackSortKey: hasSched ?
PrimaryTrackSortKey.PROCESS_SCHEDULING_TRACK :
PrimaryTrackSortKey.PROCESS_SUMMARY_TRACK,
name: `${upid === null ? tid : pid} summary`,
- config: {},
labels: it.chromeProcessLabels.split(','),
- uri,
});
const name =
getTrackName({utid, processName, pid, threadName, tid, upid});
const addTrackGroup = Actions.addTrackGroup({
- engineId: this.engineId,
summaryTrackId,
name,
id: pUuid,
@@ -1716,64 +1585,29 @@
return threadOrderingMetadata;
}
- private async defineMaxLayoutDepthSqlFunction(): Promise<void> {
- await this.engine.query(`
- select create_function(
- 'max_layout_depth(track_count INT, track_ids STRING)',
- 'INT',
- '
- select iif(
- $track_count = 1,
- (
- select max(depth)
- from slice
- where track_id = cast($track_ids AS int)
- ),
- (
- select max(layout_depth)
- from experimental_slice_layout($track_ids)
- )
- );
- '
- );
- `);
- }
-
addPluginTracks(): void {
const tracks = pluginManager.findPotentialTracks();
for (const info of tracks) {
this.tracksToAdd.push({
- engineId: this.engineId,
- kind: PLUGIN_TRACK_KIND,
- name: info.name,
uri: info.uri,
+ name: info.name,
// TODO(hjd): Fix how sorting works. Plugins should expose
// 'sort keys' which the user can use to choose a sort order.
trackSortKey: info.sortKey,
trackGroup: SCROLLING_TRACK_GROUP,
- config: {},
});
}
}
async addScrollJankPluginTracks(): Promise<void> {
if (ENABLE_SCROLL_JANK_PLUGIN_V2.get()) {
- const scrollJankTracksResult = await getScrollJankTracks(this.engine);
- const tracks = scrollJankTracksResult.tracks;
- const originalLength = this.tracksToAdd.length;
- this.tracksToAdd.length += tracks.tracksToAdd.length;
-
- for (let i = 0; i < tracks.tracksToAdd.length; ++i) {
- this.tracksToAdd[i + originalLength] = tracks.tracksToAdd[i];
- }
-
- this.addTrackGroupActions.push(scrollJankTracksResult.addTrackGroup);
+ const result = await getScrollJankTracks(this.engine);
+ this.tracksToAdd = this.tracksToAdd.concat(result.tracks.tracksToAdd);
+ this.addTrackGroupActions.push(result.addTrackGroup);
}
}
async decideTracks(): Promise<DeferredAction[]> {
- await this.defineMaxLayoutDepthSqlFunction();
-
{
const result = screenshotDecideTracks(this.engine);
if (result !== null) {
diff --git a/ui/src/controller/visualised_args_controller.ts b/ui/src/controller/visualised_args_controller.ts
deleted file mode 100644
index 8e709f5..0000000
--- a/ui/src/controller/visualised_args_controller.ts
+++ /dev/null
@@ -1,133 +0,0 @@
-// Copyright (C) 2022 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.
-
-import {v4 as uuidv4} from 'uuid';
-
-import {Actions, AddTrackArgs} from '../common/actions';
-import {Engine} from '../common/engine';
-import {NUM} from '../common/query_result';
-import {InThreadTrackSortKey} from '../common/state';
-import {globals} from '../frontend/globals';
-import {
- VISUALISED_ARGS_SLICE_TRACK_KIND,
-} from '../tracks/visualised_args/index';
-
-import {Controller} from './controller';
-
-export interface VisualisedArgControllerArgs {
- argName: string;
- engine: Engine;
-}
-
-export class VisualisedArgController extends Controller<'init'|'running'> {
- private engine: Engine;
- private argName: string;
- private escapedArgName: string;
- private tableName: string;
- private addedTrackIds: string[];
-
- constructor(args: VisualisedArgControllerArgs) {
- super('init');
- this.argName = args.argName;
- this.engine = args.engine;
- this.escapedArgName = this.argName.replace(/[^a-zA-Z]/g, '_');
- this.tableName = `__arg_visualisation_helper_${this.escapedArgName}_slice`;
- this.addedTrackIds = [];
- }
-
- onDestroy() {
- this.engine.query(`drop table if exists ${this.tableName}`);
- globals.dispatch(
- Actions.removeVisualisedArgTracks({trackIds: this.addedTrackIds}));
- }
-
- async createTracks() {
- const result = await this.engine.query(`
- drop table if exists ${this.tableName};
-
- create table ${this.tableName} as
- with slice_with_arg as (
- select
- slice.id,
- slice.track_id,
- slice.ts,
- slice.dur,
- slice.thread_dur,
- NULL as cat,
- args.display_value as name
- from slice
- join args using (arg_set_id)
- where args.key='${this.argName}'
- )
- select
- *,
- (select count()
- from ancestor_slice(s1.id) s2
- join slice_with_arg s3 on s2.id=s3.id
- ) as depth
- from slice_with_arg s1
- order by id;
-
- select
- track_id as trackId,
- max(depth) as maxDepth
- from ${this.tableName}
- group by track_id;
- `);
-
- const tracksToAdd: AddTrackArgs[] = [];
- const it = result.iter({'trackId': NUM, 'maxDepth': NUM});
- for (; it.valid(); it.next()) {
- const track =
- globals.state
- .tracks[globals.state.uiTrackIdByTraceTrackId[it.trackId]];
- const utid = (track.trackSortKey as {utid?: number}).utid;
- const id = uuidv4();
- this.addedTrackIds.push(id);
- tracksToAdd.push({
- id,
- trackGroup: track.trackGroup,
- engineId: this.engine.id,
- kind: VISUALISED_ARGS_SLICE_TRACK_KIND,
- name: this.argName,
- trackSortKey: utid === undefined ?
- track.trackSortKey :
- {utid, priority: InThreadTrackSortKey.VISUALISED_ARGS_TRACK},
- config: {
- maxDepth: it.maxDepth,
- namespace: `__arg_visualisation_helper_${this.escapedArgName}`,
- trackId: it.trackId,
- argName: this.argName,
- tid: (track.config as {tid?: number}).tid,
- },
- });
- }
- globals.dispatch(Actions.addTracks({tracks: tracksToAdd}));
- globals.dispatch(Actions.sortThreadTracks({}));
- }
-
- run() {
- switch (this.state) {
- case 'init':
- this.createTracks();
- this.setState('running');
- break;
- case 'running':
- // Nothing to do here.
- break;
- default:
- throw new Error(`Unexpected state ${this.state}`);
- }
- }
-}
diff --git a/ui/src/frontend/base_counter_track.ts b/ui/src/frontend/base_counter_track.ts
index 66e221c..4cefe00 100644
--- a/ui/src/frontend/base_counter_track.ts
+++ b/ui/src/frontend/base_counter_track.ts
@@ -93,7 +93,6 @@
constructor(args: NewTrackArgs) {
super(args);
- this.frontendOnly = true; // Disable auto checkerboarding.
this.tableName = `track_${this.trackId}`.replace(/[^a-zA-Z0-9_]+/g, '_');
}
@@ -121,7 +120,7 @@
});
}
- getContextMenu(): m.Vnode<any> {
+ getCounterContextMenu(): m.Child {
return m(
PopupMenu2,
{
@@ -131,6 +130,10 @@
);
}
+ getTrackShellButtons(): m.Children {
+ return this.getCounterContextMenu();
+ }
+
renderCanvas(ctx: CanvasRenderingContext2D) {
const {
visibleTimeScale: timeScale,
diff --git a/ui/src/frontend/base_slice_track.ts b/ui/src/frontend/base_slice_track.ts
index e95fb20..f932269 100644
--- a/ui/src/frontend/base_slice_track.ts
+++ b/ui/src/frontend/base_slice_track.ts
@@ -256,7 +256,6 @@
constructor(args: NewTrackArgs) {
super(args);
- this.frontendOnly = true; // Disable auto checkerboarding.
// TODO(hjd): Handle pinned tracks, which current cause a crash
// since the tableName we generate is the same for both.
this.tableName = `track_${this.trackId}`.replace(/[^a-zA-Z0-9_]+/g, '_');
diff --git a/ui/src/frontend/flow_events_renderer.ts b/ui/src/frontend/flow_events_renderer.ts
index c414454..48cc3b1 100644
--- a/ui/src/frontend/flow_events_renderer.ts
+++ b/ui/src/frontend/flow_events_renderer.ts
@@ -12,10 +12,9 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-import {TrackState} from 'src/common/state';
-
import {time} from '../base/time';
import {pluginManager} from '../common/plugins';
+import {TrackState} from '../common/state';
import {TRACK_SHELL_WIDTH} from './css_constants';
import {ALL_CATEGORIES, getFlowCategories} from './flow_events_panel';
@@ -54,14 +53,6 @@
height: number;
}
-function hasTrackId(obj: {}): obj is {trackId: number} {
- return (obj as {trackId?: number}).trackId !== undefined;
-}
-
-function hasManyTrackIds(obj: {}): obj is {trackIds: number[]} {
- return (obj as {trackIds?: number}).trackIds !== undefined;
-}
-
function hasId(obj: {}): obj is {id: number} {
return (obj as {id?: number}).id !== undefined;
}
@@ -71,19 +62,8 @@
}
function getTrackIds(track: TrackState): number[] {
- if (track.uri) {
- const trackInfo = pluginManager.resolveTrackInfo(track.uri);
- if (trackInfo?.trackIds) return trackInfo?.trackIds;
- } else {
- const config = track.config;
- if (hasTrackId(config)) {
- return [config.trackId];
- }
- if (hasManyTrackIds(config)) {
- return config.trackIds;
- }
- }
- return [];
+ const trackDesc = pluginManager.resolveTrackInfo(track.uri);
+ return trackDesc?.trackIds ?? [];
}
export class FlowEventsRendererArgs {
@@ -101,6 +81,17 @@
for (const trackId of getTrackIds(track)) {
this.trackIdToTrackPanel.set(trackId, {panel: panel.state, yStart});
}
+
+ // Register new "plugin track" ids
+ const trackState = globals.state.tracks[panel.attrs.id];
+ if (trackState.uri) {
+ const trackInfo = pluginManager.resolveTrackInfo(trackState.uri);
+ if (trackInfo?.trackIds) {
+ for (const trackId of trackInfo.trackIds) {
+ this.trackIdToTrackPanel.set(trackId, {panel: panel.state, yStart});
+ }
+ }
+ }
} else if (
panel.state instanceof TrackGroupPanel &&
hasTrackGroupId(panel.attrs)) {
diff --git a/ui/src/frontend/post_message_handler.ts b/ui/src/frontend/post_message_handler.ts
index ed9d078..c6b5546 100644
--- a/ui/src/frontend/post_message_handler.ts
+++ b/ui/src/frontend/post_message_handler.ts
@@ -22,6 +22,8 @@
import {showModal} from './modal';
import {focusHorizontalRange} from './scroll_helper';
+const TRUSTED_ORIGINS_KEY = 'trustedOrigins';
+
interface PostedTraceWrapped {
perfetto: PostedTrace;
}
@@ -40,6 +42,7 @@
];
if (origin === window.origin) return true;
if (TRUSTED_ORIGINS.includes(origin)) return true;
+ if (isUserTrustedOrigin(origin)) return true;
const hostname = new URL(origin).hostname;
if (hostname.endsWith('corp.google.com')) return true;
@@ -47,6 +50,33 @@
return false;
}
+// Returns whether the user saved this as an always-trusted origin.
+function isUserTrustedOrigin(hostname: string): boolean {
+ const trustedOrigins = window.localStorage.getItem(TRUSTED_ORIGINS_KEY);
+ if (trustedOrigins === null) return false;
+ try {
+ return JSON.parse(trustedOrigins).includes(hostname);
+ } catch {
+ return false;
+ }
+}
+
+// Saves the given hostname as a trusted origin.
+// This is used for user convenience: if it fails for any reason, it's not a
+// big deal.
+function saveUserTrustedOrigin(hostname: string) {
+ const s = window.localStorage.getItem(TRUSTED_ORIGINS_KEY);
+ let origins: string[];
+ try {
+ origins = JSON.parse(s || '[]');
+ if (origins.includes(hostname)) return;
+ origins.push(hostname);
+ window.localStorage.setItem(TRUSTED_ORIGINS_KEY, JSON.stringify(origins));
+ } catch (e) {
+ console.warn('unable to save trusted origins to localStorage', e);
+ }
+}
+
// Returns whether we should ignore a given message based on the value of
// the 'perfettoIgnore' field in the event data.
function shouldGracefullyIgnoreMessage(messageEvent: MessageEvent) {
@@ -162,6 +192,11 @@
globals.dispatch(Actions.openTraceFromBuffer(postedTrace));
};
+ const trustAndOpenTrace = () => {
+ saveUserTrustedOrigin(messageEvent.origin);
+ openTrace();
+ };
+
// If the origin is trusted open the trace directly.
if (isTrustedOrigin(messageEvent.origin)) {
openTrace();
@@ -176,8 +211,9 @@
m('div', `${messageEvent.origin} is trying to open a trace file.`),
m('div', 'Do you trust the origin and want to proceed?')),
buttons: [
- {text: 'NO', primary: true},
- {text: 'YES', primary: false, action: openTrace},
+ {text: 'No', primary: true},
+ {text: 'Yes', primary: false, action: openTrace},
+ {text: 'Always trust', primary: false, action: trustAndOpenTrace},
],
});
}
diff --git a/ui/src/frontend/slice_args.ts b/ui/src/frontend/slice_args.ts
index 5bb8a8c..f68b639 100644
--- a/ui/src/frontend/slice_args.ts
+++ b/ui/src/frontend/slice_args.ts
@@ -13,13 +13,20 @@
// limitations under the License.
import m from 'mithril';
+import {v4 as uuidv4} from 'uuid';
import {Icons} from '../base/semantic_icons';
import {sqliteString} from '../base/string_utils';
import {exists} from '../base/utils';
-import {Actions} from '../common/actions';
+import {Actions, AddTrackArgs} from '../common/actions';
import {EngineProxy} from '../common/engine';
+import {NUM} from '../common/query_result';
+import {InThreadTrackSortKey} from '../common/state';
import {ArgNode, convertArgsToTree, Key} from '../controller/args_parser';
+import {
+ VISUALISED_ARGS_SLICE_TRACK_URI,
+ VisualisedArgsState,
+} from '../tracks/visualised_args';
import {Anchor} from '../widgets/anchor';
import {MenuItem, PopupMenu2} from '../widgets/menu';
import {Section} from '../widgets/section';
@@ -62,7 +69,7 @@
return m(
TreeNode,
{
- left: renderArgKey(stringifyKey(key), value),
+ left: renderArgKey(engine, stringifyKey(key), value),
right: exists(value) && renderArgValue(value),
summary: children && renderSummary(children),
},
@@ -72,7 +79,8 @@
});
}
-function renderArgKey(key: string, value?: Arg): m.Children {
+function renderArgKey(
+ engine: EngineProxy, key: string, value?: Arg): m.Children {
if (value === undefined) {
return key;
} else {
@@ -107,13 +115,84 @@
label: 'Visualise argument values',
icon: 'query_stats',
onclick: () => {
- globals.dispatch(Actions.addVisualisedArg({argName: fullKey}));
+ addVisualisedArg(engine, fullKey);
},
}),
);
}
}
+async function addVisualisedArg(engine: EngineProxy, argName: string) {
+ const escapedArgName = argName.replace(/[^a-zA-Z]/g, '_');
+ const tableName = `__arg_visualisation_helper_${escapedArgName}_slice`;
+
+ const result = await engine.query(`
+ drop table if exists ${tableName};
+
+ create table ${tableName} as
+ with slice_with_arg as (
+ select
+ slice.id,
+ slice.track_id,
+ slice.ts,
+ slice.dur,
+ slice.thread_dur,
+ NULL as cat,
+ args.display_value as name
+ from slice
+ join args using (arg_set_id)
+ where args.key='${argName}'
+ )
+ select
+ *,
+ (select count()
+ from ancestor_slice(s1.id) s2
+ join slice_with_arg s3 on s2.id=s3.id
+ ) as depth
+ from slice_with_arg s1
+ order by id;
+
+ select
+ track_id as trackId,
+ max(depth) as maxDepth
+ from ${tableName}
+ group by track_id;
+ `);
+
+ const tracksToAdd: AddTrackArgs[] = [];
+ const it = result.iter({'trackId': NUM, 'maxDepth': NUM});
+ const addedTrackIds: string[] = [];
+ for (; it.valid(); it.next()) {
+ const track =
+ globals.state.tracks[globals.state.uiTrackIdByTraceTrackId[it.trackId]];
+ const utid = (track.trackSortKey as {utid?: number}).utid;
+ const id = uuidv4();
+ addedTrackIds.push(id);
+
+ const initialState: VisualisedArgsState = {
+ maxDepth: it.maxDepth,
+ trackId: it.trackId,
+ argName: argName,
+ };
+
+ tracksToAdd.push({
+ id,
+ trackGroup: track.trackGroup,
+ name: argName,
+ trackSortKey: utid === undefined ?
+ track.trackSortKey :
+ {utid, priority: InThreadTrackSortKey.VISUALISED_ARGS_TRACK},
+ initialState,
+ uri: VISUALISED_ARGS_SLICE_TRACK_URI,
+ });
+ }
+
+ globals.dispatchMultiple([
+ Actions.addTracks({tracks: tracksToAdd}),
+ Actions.sortThreadTracks({}),
+ ]);
+}
+
function renderArgValue({value}: Arg): m.Children {
if (isWebLink(value)) {
return renderWebLink(value);
diff --git a/ui/src/frontend/slice_details_panel.ts b/ui/src/frontend/slice_details_panel.ts
index 28bd796..05de7a5 100644
--- a/ui/src/frontend/slice_details_panel.ts
+++ b/ui/src/frontend/slice_details_panel.ts
@@ -15,7 +15,9 @@
import m from 'mithril';
import {Actions} from '../common/actions';
+import {pluginManager} from '../common/plugins';
import {translateState} from '../common/thread_state';
+import {THREAD_STATE_TRACK_KIND} from '../tracks/thread_state';
import {Anchor} from '../widgets/anchor';
import {DetailsShell} from '../widgets/details_shell';
import {DurationWidget} from '../widgets/duration';
@@ -206,8 +208,10 @@
let trackId: string|number|undefined;
for (const track of Object.values(globals.state.tracks)) {
- if (track.kind === 'ThreadStateTrack' &&
- (track.config as {utid: number}).utid === threadInfo.utid) {
+ const trackDesc = pluginManager.resolveTrackInfo(track.uri);
+ // TODO(stevegolton): Handle v2.
+ if (trackDesc && trackDesc.kind === THREAD_STATE_TRACK_KIND &&
+ trackDesc.utid === threadInfo.utid) {
trackId = track.id;
}
}
diff --git a/ui/src/frontend/slice_track_base.ts b/ui/src/frontend/slice_track_base.ts
new file mode 100644
index 0000000..e91d1e2
--- /dev/null
+++ b/ui/src/frontend/slice_track_base.ts
@@ -0,0 +1,339 @@
+// 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.
+
+import {duration, Span, Time, time} from '../base/time';
+import {Actions} from '../common/actions';
+import {BasicAsyncTrack} from '../common/basic_async_track';
+import {cropText, drawIncompleteSlice} from '../common/canvas_utils';
+import {
+ colorForThreadIdleSlice,
+ getColorForSlice,
+} from '../common/colorizer';
+import {HighPrecisionTime} from '../common/high_precision_time';
+import {TrackData} from '../common/track_data';
+
+import {checkerboardExcept} from './checkerboard';
+import {globals} from './globals';
+import {cachedHsluvToHex} from './hsluv_cache';
+import {PxSpan, TimeScale} from './time_scale';
+import {SliceRect} from './track';
+
+export const SLICE_TRACK_KIND = 'ChromeSliceTrack';
+const SLICE_HEIGHT = 18;
+const TRACK_PADDING = 2;
+const CHEVRON_WIDTH_PX = 10;
+const HALF_CHEVRON_WIDTH_PX = CHEVRON_WIDTH_PX / 2;
+
+export interface SliceData extends TrackData {
+ // Slices are stored in a columnar fashion.
+ strings: string[];
+ sliceIds: Float64Array;
+ starts: BigInt64Array;
+ ends: BigInt64Array;
+ depths: Uint16Array;
+ titles: Uint16Array; // Index into strings.
+ colors?: Uint16Array; // Index into strings.
+ isInstant: Uint16Array;
+ isIncomplete: Uint16Array;
+ cpuTimeRatio?: Float64Array;
+}
+
+// Track base class which handles rendering slices in a generic way.
+// This is the old way of rendering slices - i.e. "track v1" format - and
+// exists as a patch to allow old tracks to be converted to controller-less
+// tracks before they are ported to v2.
+// Slice tracks should extend this class and implement the abstract methods,
+// notably onBoundsChange().
+export abstract class SliceTrackBase extends BasicAsyncTrack<SliceData> {
+ constructor(
+ private maxDepth: number, protected trackInstanceId: string,
+ private tableName: string, private namespace?: string) {
+ super();
+ }
+
+ protected namespaceTable(tableName: string = this.tableName): string {
+ if (this.namespace) {
+ return this.namespace + '_' + tableName;
+ } else {
+ return tableName;
+ }
+ }
+
+ private hoveredTitleId = -1;
+
+ // Font used to render the slice name on the current track.
+ protected getFont() {
+ return '12px Roboto Condensed';
+ }
+
+ renderCanvas(ctx: CanvasRenderingContext2D): void {
+ // TODO: fonts and colors should come from the CSS and not hardcoded here.
+ const data = this.data;
+ if (data === undefined) return; // Can't possibly draw anything.
+
+ const {visibleTimeSpan, visibleWindowTime, visibleTimeScale, windowSpan} =
+ globals.frontendLocalState;
+
+ // If the cached trace slices don't fully cover the visible time range,
+ // show a gray rectangle with a "Loading..." label.
+ checkerboardExcept(
+ ctx,
+ this.getHeight(),
+ visibleTimeScale.hpTimeToPx(visibleWindowTime.start),
+ visibleTimeScale.hpTimeToPx(visibleWindowTime.end),
+ visibleTimeScale.timeToPx(data.start),
+ visibleTimeScale.timeToPx(data.end),
+ );
+
+ ctx.textAlign = 'center';
+
+ // measuretext is expensive so we only use it once.
+ const charWidth = ctx.measureText('ACBDLqsdfg').width / 10;
+
+ // The draw of the rect on the selected slice must happen after the other
+ // drawings, otherwise it would result under another rect.
+ let drawRectOnSelected = () => {};
+
+
+ for (let i = 0; i < data.starts.length; i++) {
+ const tStart = Time.fromRaw(data.starts[i]);
+ let tEnd = Time.fromRaw(data.ends[i]);
+ const depth = data.depths[i];
+ const titleId = data.titles[i];
+ const sliceId = data.sliceIds[i];
+ const isInstant = data.isInstant[i];
+ const isIncomplete = data.isIncomplete[i];
+ const title = data.strings[titleId];
+ const colorOverride = data.colors && data.strings[data.colors[i]];
+ if (isIncomplete) { // incomplete slice
+ // TODO(stevegolton): This isn't exactly equivalent, ideally we should
+ // choose tEnd once we've converted to screen space coords.
+ tEnd = visibleWindowTime.end.toTime('ceil');
+ }
+
+ if (!visibleTimeSpan.intersects(tStart, tEnd)) {
+ continue;
+ }
+
+ const rect = this.getSliceRect(
+ visibleTimeScale, visibleTimeSpan, windowSpan, tStart, tEnd, depth);
+ if (!rect || !rect.visible) {
+ continue;
+ }
+
+ const currentSelection = globals.state.currentSelection;
+ const isSelected = currentSelection &&
+ currentSelection.kind === 'CHROME_SLICE' &&
+ currentSelection.id !== undefined && currentSelection.id === sliceId;
+
+ const highlighted = titleId === this.hoveredTitleId ||
+ globals.state.highlightedSliceId === sliceId;
+
+ const hasFocus = highlighted || isSelected;
+ const colorObj = getColorForSlice(title, hasFocus);
+
+ let color: string;
+ if (colorOverride === undefined) {
+ color = colorObj.c;
+ } else {
+ color = colorOverride;
+ }
+ ctx.fillStyle = color;
+
+ // We draw instant events as upward facing chevrons starting at A:
+ // A
+ // ###
+ // ##C##
+ // ## ##
+ // D B
+ // Then B, C, D and back to A:
+ if (isInstant) {
+ if (isSelected) {
+ drawRectOnSelected = () => {
+ ctx.save();
+ ctx.translate(rect.left, rect.top);
+
+ // Draw a rectangle around the selected slice
+ ctx.strokeStyle = cachedHsluvToHex(colorObj.h, 100, 10);
+ ctx.beginPath();
+ ctx.lineWidth = 3;
+ ctx.strokeRect(
+ -HALF_CHEVRON_WIDTH_PX, 0, CHEVRON_WIDTH_PX, SLICE_HEIGHT);
+ ctx.closePath();
+
+ // Draw inner chevron as interior
+ ctx.fillStyle = color;
+ this.drawChevron(ctx);
+
+ ctx.restore();
+ };
+ } else {
+ ctx.save();
+ ctx.translate(rect.left, rect.top);
+ this.drawChevron(ctx);
+ ctx.restore();
+ }
+ continue;
+ }
+
+ if (isIncomplete && rect.width > SLICE_HEIGHT / 4) {
+ drawIncompleteSlice(ctx, rect.left, rect.top, rect.width, SLICE_HEIGHT);
+ } else if (
+ data.cpuTimeRatio !== undefined && data.cpuTimeRatio[i] < 1 - 1e-9) {
+ // We draw two rectangles, representing the ratio between wall time and
+ // time spent on cpu.
+ const cpuTimeRatio = data.cpuTimeRatio![i];
+ const firstPartWidth = rect.width * cpuTimeRatio;
+ const secondPartWidth = rect.width * (1 - cpuTimeRatio);
+ ctx.fillRect(rect.left, rect.top, firstPartWidth, SLICE_HEIGHT);
+ ctx.fillStyle = colorForThreadIdleSlice(
+ colorObj.h, colorObj.s, colorObj.l, hasFocus);
+ ctx.fillRect(
+ rect.left + firstPartWidth,
+ rect.top,
+ secondPartWidth,
+ SLICE_HEIGHT);
+ } else {
+ ctx.fillRect(rect.left, rect.top, rect.width, SLICE_HEIGHT);
+ }
+
+ // Selected case
+ if (isSelected) {
+ drawRectOnSelected = () => {
+ ctx.strokeStyle = cachedHsluvToHex(colorObj.h, 100, 10);
+ ctx.beginPath();
+ ctx.lineWidth = 3;
+ ctx.strokeRect(
+ rect.left, rect.top - 1.5, rect.width, SLICE_HEIGHT + 3);
+ ctx.closePath();
+ };
+ }
+
+ // Don't render text when we have less than 5px to play with.
+ if (rect.width >= 5) {
+ ctx.fillStyle = colorObj.l > 65 ? '#404040' : 'white';
+ const displayText = cropText(title, charWidth, rect.width);
+ const rectXCenter = rect.left + rect.width / 2;
+ ctx.textBaseline = 'middle';
+ ctx.font = this.getFont();
+ ctx.fillText(displayText, rectXCenter, rect.top + SLICE_HEIGHT / 2);
+ }
+ }
+ drawRectOnSelected();
+ }
+
+ drawChevron(ctx: CanvasRenderingContext2D) {
+ // Draw a chevron at a fixed location and size. Should be used with
+ // ctx.translate and ctx.scale to alter location and size.
+ ctx.beginPath();
+ ctx.moveTo(0, 0);
+ ctx.lineTo(HALF_CHEVRON_WIDTH_PX, SLICE_HEIGHT);
+ ctx.lineTo(0, SLICE_HEIGHT - HALF_CHEVRON_WIDTH_PX);
+ ctx.lineTo(-HALF_CHEVRON_WIDTH_PX, SLICE_HEIGHT);
+ ctx.lineTo(0, 0);
+ ctx.fill();
+ }
+
+ getSliceIndex({x, y}: {x: number, y: number}): number|void {
+ const data = this.data;
+ if (data === undefined) return;
+ const {
+ visibleTimeScale: timeScale,
+ visibleWindowTime: visibleHPTimeSpan,
+ } = globals.frontendLocalState;
+ if (y < TRACK_PADDING) return;
+ const instantWidthTime = timeScale.pxDeltaToDuration(HALF_CHEVRON_WIDTH_PX);
+ const t = timeScale.pxToHpTime(x);
+ const depth = Math.floor((y - TRACK_PADDING) / SLICE_HEIGHT);
+
+ for (let i = 0; i < data.starts.length; i++) {
+ if (depth !== data.depths[i]) {
+ continue;
+ }
+ const start = Time.fromRaw(data.starts[i]);
+ const tStart = HighPrecisionTime.fromTime(start);
+ if (data.isInstant[i]) {
+ if (tStart.sub(t).abs().lt(instantWidthTime)) {
+ return i;
+ }
+ } else {
+ const end = Time.fromRaw(data.ends[i]);
+ let tEnd = HighPrecisionTime.fromTime(end);
+ if (data.isIncomplete[i]) {
+ tEnd = visibleHPTimeSpan.end;
+ }
+ if (tStart.lte(t) && t.lte(tEnd)) {
+ return i;
+ }
+ }
+ }
+ }
+
+ onMouseMove({x, y}: {x: number, y: number}) {
+ this.hoveredTitleId = -1;
+ globals.dispatch(Actions.setHighlightedSliceId({sliceId: -1}));
+ const sliceIndex = this.getSliceIndex({x, y});
+ if (sliceIndex === undefined) return;
+ const data = this.data;
+ if (data === undefined) return;
+ this.hoveredTitleId = data.titles[sliceIndex];
+ const sliceId = data.sliceIds[sliceIndex];
+ globals.dispatch(Actions.setHighlightedSliceId({sliceId}));
+ }
+
+ onMouseOut() {
+ this.hoveredTitleId = -1;
+ globals.dispatch(Actions.setHighlightedSliceId({sliceId: -1}));
+ }
+
+ onMouseClick({x, y}: {x: number, y: number}): boolean {
+ const sliceIndex = this.getSliceIndex({x, y});
+ if (sliceIndex === undefined) return false;
+ const data = this.data;
+ if (data === undefined) return false;
+ const sliceId = data.sliceIds[sliceIndex];
+ if (sliceId !== undefined && sliceId !== -1) {
+ globals.makeSelection(Actions.selectChromeSlice({
+ id: sliceId,
+ trackId: this.trackInstanceId,
+ table: this.namespace,
+ }));
+ return true;
+ }
+ return false;
+ }
+
+ getHeight() {
+ return SLICE_HEIGHT * (this.maxDepth + 1) + 2 * TRACK_PADDING;
+ }
+
+ getSliceRect(
+ visibleTimeScale: TimeScale, visibleWindow: Span<time, duration>,
+ windowSpan: PxSpan, tStart: time, tEnd: time, depth: number): SliceRect
+ |undefined {
+ const pxEnd = windowSpan.end;
+ const left = Math.max(visibleTimeScale.timeToPx(tStart), 0);
+ const right = Math.min(visibleTimeScale.timeToPx(tEnd), pxEnd);
+
+ const visible = visibleWindow.intersects(tStart, tEnd);
+
+ return {
+ left,
+ width: Math.max(right - left, 1),
+ top: TRACK_PADDING + depth * SLICE_HEIGHT,
+ height: SLICE_HEIGHT,
+ visible,
+ };
+ }
+}
diff --git a/ui/src/frontend/thread_state.ts b/ui/src/frontend/thread_state.ts
index 80f690b..50be523 100644
--- a/ui/src/frontend/thread_state.ts
+++ b/ui/src/frontend/thread_state.ts
@@ -27,6 +27,7 @@
import {LONG, NUM, NUM_NULL, STR_NULL} from '../common/query_result';
import {translateState} from '../common/thread_state';
import {CPU_SLICE_TRACK_KIND} from '../tracks/cpu_slices';
+import {THREAD_STATE_TRACK_KIND} from '../tracks/thread_state';
import {Anchor} from '../widgets/anchor';
import {globals} from './globals';
@@ -179,8 +180,10 @@
onclick: () => {
let trackId: string|number|undefined;
for (const track of Object.values(globals.state.tracks)) {
- if (track.kind === 'ThreadStateTrack' &&
- (track.config as {utid: number}).utid === vnode.attrs.utid) {
+ const trackDesc = pluginManager.resolveTrackInfo(track.uri);
+ // TODO(stevegolton): Handle v2.
+ if (trackDesc && trackDesc.kind === THREAD_STATE_TRACK_KIND &&
+ trackDesc.utid === vnode.attrs.utid) {
trackId = track.id;
}
}
diff --git a/ui/src/frontend/track.ts b/ui/src/frontend/track.ts
index 6ddbc51..d916e7d 100644
--- a/ui/src/frontend/track.ts
+++ b/ui/src/frontend/track.ts
@@ -17,14 +17,10 @@
import {assertExists} from '../base/logging';
import {duration, Span, time} from '../base/time';
import {EngineProxy} from '../common/engine';
-import {TrackState} from '../common/state';
-import {TrackData} from '../common/track_data';
import {Track} from '../public';
-import {checkerboard} from './checkerboard';
import {globals} from './globals';
import {PxSpan, TimeScale} from './time_scale';
-import {TrackButtonAttrs} from './track_panel';
// Args passed to the track constructors when creating a new track.
export interface NewTrackArgs {
@@ -54,25 +50,23 @@
}
// The abstract class that needs to be implemented by all tracks.
-export abstract class TrackBase<Config = {}, Data extends TrackData = TrackData>
- implements Track {
+export abstract class TrackBase<Config = {}> implements Track {
// The UI-generated track ID (not to be confused with the SQL track.id).
protected readonly trackId: string;
protected readonly engine: EngineProxy;
+ private _config?: Config;
- // When true this is a new controller-less track type.
- // TODO(hjd): eventually all tracks will be controller-less and this
- // should be removed then.
- protected frontendOnly = false;
+ get config(): Config {
+ return assertExists(this._config);
+ }
- // Caches the last state.track[this.trackId]. This is to deal with track
- // deletion, see comments in trackState() below.
- private lastTrackState: TrackState;
+ set config(x: Config) {
+ this._config = x;
+ }
constructor(args: NewTrackArgs) {
this.trackId = args.trackId;
this.engine = args.engine;
- this.lastTrackState = assertExists(globals.state.tracks[this.trackId]);
}
onCreate() {}
@@ -83,44 +77,14 @@
protected abstract renderCanvas(ctx: CanvasRenderingContext2D): void;
- protected get trackState(): TrackState {
- // We can end up in a state where a Track is still in the mithril renderer
- // tree but its corresponding state has been deleted. This can happen in the
- // interval of time between a track being removed from the state and the
- // next animation frame that would remove the Track object. If a mouse event
- // is dispatched in the meanwhile (or a promise is resolved), we need to be
- // able to access the state. Hence the caching logic here.
- const trackState = globals.state.tracks[this.trackId];
- if (trackState === undefined) {
- return this.lastTrackState;
- }
- this.lastTrackState = trackState;
- return trackState;
- }
-
- get config(): Config {
- return this.trackState.config as Config;
- }
-
- data(): Data|undefined {
- if (this.frontendOnly) {
- return undefined;
- }
- return globals.trackDataStore.get(this.trackId) as Data;
- }
-
getHeight(): number {
return 40;
}
- getTrackShellButtons(): Array<m.Vnode<TrackButtonAttrs>> {
+ getTrackShellButtons(): m.Children {
return [];
}
- getContextMenu(): m.Vnode<any>|null {
- return null;
- }
-
onMouseMove(_position: {x: number, y: number}) {}
// Returns whether the mouse click has selected something.
@@ -134,17 +98,8 @@
onFullRedraw(): void {}
render(ctx: CanvasRenderingContext2D) {
- globals.frontendLocalState.addVisibleTrack(this.trackState.id);
- if (this.data() === undefined && !this.frontendOnly) {
- const {visibleWindowTime, visibleTimeScale} = globals.frontendLocalState;
- const startPx =
- Math.floor(visibleTimeScale.hpTimeToPx(visibleWindowTime.start));
- const endPx =
- Math.ceil(visibleTimeScale.hpTimeToPx(visibleWindowTime.end));
- checkerboard(ctx, this.getHeight(), startPx, endPx);
- } else {
- this.renderCanvas(ctx);
- }
+ globals.frontendLocalState.addVisibleTrack(this.trackId);
+ this.renderCanvas(ctx);
}
// Returns a place where a given slice should be drawn. Should be implemented
diff --git a/ui/src/frontend/track_group_panel.ts b/ui/src/frontend/track_group_panel.ts
index b378189..c9e1038 100644
--- a/ui/src/frontend/track_group_panel.ts
+++ b/ui/src/frontend/track_group_panel.ts
@@ -19,7 +19,6 @@
import {Icons} from '../base/semantic_icons';
import {Actions} from '../common/actions';
import {pluginManager} from '../common/plugins';
-import {RegistryError} from '../common/registry';
import {
getContainingTrackId,
TrackGroupState,
@@ -31,7 +30,6 @@
import {drawGridLines} from './gridline_helper';
import {Panel, PanelSize} from './panel';
import {renderChips, TrackContent} from './track_panel';
-import {trackRegistry} from './track_registry';
import {
drawVerticalLineAtTime,
} from './vertical_line_helper';
@@ -70,8 +68,7 @@
},
};
- this.summaryTrack =
- uri ? pluginManager.createTrack(uri, ctx) : loadTrack(trackState, id);
+ this.summaryTrack = pluginManager.createTrack(uri, ctx);
}
get trackGroupState(): TrackGroupState {
@@ -304,25 +301,3 @@
function StripPathFromExecutable(path: string) {
return path.split('/').slice(-1)[0];
}
-
-function loadTrack(trackState: TrackState, trackId: string): Track|undefined {
- const engine = globals.engines.get(trackState.engineId);
- if (engine === undefined) {
- return undefined;
- }
-
- try {
- const trackCreator = trackRegistry.get(trackState.kind);
- return trackCreator.create({
- trackId,
- engine:
- engine.getProxy(`Track; kind: ${trackState.kind}; id: ${trackId}`),
- });
- } catch (e) {
- if (e instanceof RegistryError) {
- return undefined;
- } else {
- throw e;
- }
- }
-}
diff --git a/ui/src/frontend/track_panel.ts b/ui/src/frontend/track_panel.ts
index c280ced..5cd384b 100644
--- a/ui/src/frontend/track_panel.ts
+++ b/ui/src/frontend/track_panel.ts
@@ -18,10 +18,8 @@
import {currentTargetOffset} from '../base/dom_utils';
import {Icons} from '../base/semantic_icons';
import {duration, Span, time} from '../base/time';
-import {exists} from '../base/utils';
import {Actions} from '../common/actions';
import {pluginManager} from '../common/plugins';
-import {RegistryError} from '../common/registry';
import {TrackState} from '../common/state';
import {raf} from '../core/raf_scheduler';
import {Migrate, Track, TrackContext} from '../public';
@@ -33,7 +31,6 @@
import {verticalScrollToTrack} from './scroll_helper';
import {PxSpan, TimeScale} from './time_scale';
import {SliceRect} from './track';
-import {trackRegistry} from './track_registry';
import {
drawVerticalLineAtTime,
} from './vertical_line_helper';
@@ -79,24 +76,12 @@
}
}
-export function renderChips({uri, config}: TrackState) {
+export function renderChips({uri}: TrackState) {
const tagElements: m.Children = [];
- if (exists(uri)) {
- const trackInfo = pluginManager.resolveTrackInfo(uri);
- const tags = trackInfo?.tags;
- tags?.metric && tagElements.push(m(TrackChip, {text: 'metric'}));
- tags?.debuggable && tagElements.push(m(TrackChip, {text: 'debuggable'}));
- } else {
- if (config && typeof config === 'object') {
- if ('namespace' in config) {
- tagElements.push(m(TrackChip, {text: 'metric'}));
- }
- if ('isDebuggable' in config && config.isDebuggable) {
- tagElements.push(m(TrackChip, {text: 'debuggable'}));
- }
- }
- }
-
+ const trackInfo = pluginManager.resolveTrackInfo(uri);
+ const tags = trackInfo?.tags;
+ tags?.metric && tagElements.push(m(TrackChip, {text: 'metric'}));
+ tags?.debuggable && tagElements.push(m(TrackChip, {text: 'debuggable'}));
return tagElements;
}
@@ -152,7 +137,6 @@
),
m('.track-buttons',
attrs.track.getTrackShellButtons(),
- attrs.track.getContextMenu(),
m(TrackButton, {
action: () => {
globals.dispatch(
@@ -379,8 +363,7 @@
},
};
- this.track = uri ? pluginManager.createTrack(uri, trackCtx) :
- loadTrack(trackState, id);
+ this.track = pluginManager.createTrack(uri, trackCtx);
this.track?.onCreate();
this.trackState = trackState;
@@ -519,25 +502,3 @@
visibleTimeScale, visibleWindow, windowSpan, tStart, tDur, depth);
}
}
-
-function loadTrack(trackState: TrackState, trackId: string): Track|undefined {
- const engine = globals.engines.get(trackState.engineId);
- if (engine === undefined) {
- return undefined;
- }
-
- try {
- const trackCreator = trackRegistry.get(trackState.kind);
- return trackCreator.create({
- trackId,
- engine:
- engine.getProxy(`Track; kind: ${trackState.kind}; id: ${trackId}`),
- });
- } catch (e) {
- if (e instanceof RegistryError) {
- return undefined;
- } else {
- throw e;
- }
- }
-}
diff --git a/ui/src/public/index.ts b/ui/src/public/index.ts
index 283449d..7a474a7 100644
--- a/ui/src/public/index.ts
+++ b/ui/src/public/index.ts
@@ -17,11 +17,9 @@
import {Hotkey} from '../base/hotkeys';
import {duration, Span, time} from '../base/time';
import {EngineProxy} from '../common/engine';
-import {TrackControllerFactory} from '../controller/track_controller';
import {Store} from '../frontend/store';
import {PxSpan, TimeScale} from '../frontend/time_scale';
-import {SliceRect, TrackCreator} from '../frontend/track';
-import {TrackButtonAttrs} from '../frontend/track_panel';
+import {SliceRect} from '../frontend/track';
export {EngineProxy} from '../common/engine';
export {
@@ -150,22 +148,6 @@
export interface PluginContext {
readonly viewer: Viewer;
- // DEPRECATED. In prior versions of the UI tracks were split into a
- // 'TrackController' and a 'Track'. In more recent versions of the UI
- // the functionality of |TrackController| has been merged into Track so
- // |TrackController|s are not necessary in new code.
- LEGACY_registerTrackController(track: TrackControllerFactory): void;
-
- // Register a track factory. The core UI invokes |TrackCreator| to
- // construct tracks discovered by invoking |TrackProvider|s.
- // The split between 'construction' and 'discovery' allows
- // plugins to reuse common tracks for new data. For example: the
- // dev.perfetto.AndroidGpu plugin could register a TrackProvider
- // which returns GPU counter tracks. The counter track factory itself
- // could be registered in dev.perfetto.CounterTrack - a whole
- // different plugin.
- LEGACY_registerTrack(track: TrackCreator): void;
-
// Add a command.
addCommand(command: Command): void;
}
@@ -196,8 +178,7 @@
windowSpan: PxSpan, tStart: time, tEnd: time, depth: number): SliceRect
|undefined;
getHeight(): number;
- getTrackShellButtons(): Array<m.Vnode<TrackButtonAttrs>>;
- getContextMenu(): m.Vnode<any>|null;
+ getTrackShellButtons(): m.Children;
onMouseMove(position: {x: number, y: number}): void;
onMouseClick(position: {x: number, y: number}): boolean;
onMouseOut(): void;
@@ -230,6 +211,12 @@
// Optional: The CPU number associated with this track.
cpu?: number;
+ // Optional: The UTID associated with this track.
+ utid?: number;
+
+ // Optional: The UPID associated with this track.
+ upid?: number;
+
// Optional: A list of tags used for sorting, grouping and "chips".
tags?: TrackTags;
}
diff --git a/ui/src/tracks/actual_frames/index.ts b/ui/src/tracks/actual_frames/index.ts
index 90de29a..e43f2b1 100644
--- a/ui/src/tracks/actual_frames/index.ts
+++ b/ui/src/tracks/actual_frames/index.ts
@@ -14,33 +14,26 @@
import {BigintMath as BIMath} from '../../base/bigint_math';
import {duration, time} from '../../base/time';
-import {LONG, LONG_NULL, NUM, STR} from '../../common/query_result';
-import {TrackData} from '../../common/track_data';
-import {TrackController} from '../../controller/track_controller';
-import {NewTrackArgs, TrackBase} from '../../frontend/track';
-import {Plugin, PluginContext, PluginDescriptor} from '../../public';
-import {ChromeSliceTrack} from '../chrome_slices';
+import {
+ LONG,
+ LONG_NULL,
+ NUM,
+ NUM_NULL,
+ STR,
+ STR_NULL,
+} from '../../common/query_result';
+import {SliceData, SliceTrackBase} from '../../frontend/slice_track_base';
+import {
+ EngineProxy,
+ Plugin,
+ PluginContext,
+ PluginContextTrace,
+ PluginDescriptor,
+} from '../../public';
+import {getTrackName} from '../../public/utils';
export const ACTUAL_FRAMES_SLICE_TRACK_KIND = 'ActualFramesSliceTrack';
-export interface Config {
- maxDepth: number;
- trackIds: number[];
-}
-
-export interface Data extends TrackData {
- // Slices are stored in a columnar fashion. All fields have the same length.
- strings: string[];
- sliceIds: Float64Array;
- starts: BigInt64Array;
- ends: BigInt64Array;
- depths: Uint16Array;
- titles: Uint16Array; // Index in |strings|.
- colors?: Uint16Array; // Index in |strings|.
- isInstant: Uint16Array;
- isIncomplete: Uint16Array;
-}
-
const BLUE_COLOR = '#03A9F4'; // Blue 500
const GREEN_COLOR = '#4CAF50'; // Green 500
const YELLOW_COLOR = '#FFEB3B'; // Yellow 500
@@ -48,55 +41,60 @@
const LIGHT_GREEN_COLOR = '#C0D588'; // Light Green 500
const PINK_COLOR = '#F515E0'; // Pink 500
-class ActualFramesSliceTrackController extends TrackController<Config, Data> {
- static readonly kind = ACTUAL_FRAMES_SLICE_TRACK_KIND;
+class SliceTrack extends SliceTrackBase {
private maxDur = 0n;
+ constructor(
+ private engine: EngineProxy, maxDepth: number, trackInstanceId: string,
+ private trackIds: number[], namespace?: string) {
+ super(maxDepth, trackInstanceId, 'actual_frame_timeline_slice', namespace);
+ }
+
async onBoundsChange(start: time, end: time, resolution: duration):
- Promise<Data> {
+ Promise<SliceData> {
if (this.maxDur === 0n) {
- const maxDurResult = await this.query(`
- select
- max(iif(dur = -1, (SELECT end_ts FROM trace_bounds) - ts, dur))
- as maxDur
- from experimental_slice_layout
- where filter_track_ids = '${this.config.trackIds.join(',')}'
- `);
+ const maxDurResult = await this.engine.query(`
+ select
+ max(iif(dur = -1, (SELECT end_ts FROM trace_bounds) - ts, dur))
+ as maxDur
+ from experimental_slice_layout
+ where filter_track_ids = '${this.trackIds.join(',')}'
+ `);
this.maxDur = maxDurResult.firstRow({maxDur: LONG_NULL}).maxDur || 0n;
}
- const rawResult = await this.query(`
- SELECT
- (s.ts + ${resolution / 2n}) / ${resolution} * ${resolution} as tsq,
- s.ts as ts,
- max(iif(s.dur = -1, (SELECT end_ts FROM trace_bounds) - s.ts, s.dur))
- as dur,
- s.layout_depth as layoutDepth,
- s.name as name,
- s.id as id,
- s.dur = 0 as isInstant,
- s.dur = -1 as isIncomplete,
- CASE afs.jank_tag
- WHEN 'Self Jank' THEN '${RED_COLOR}'
- WHEN 'Other Jank' THEN '${YELLOW_COLOR}'
- WHEN 'Dropped Frame' THEN '${BLUE_COLOR}'
- WHEN 'Buffer Stuffing' THEN '${LIGHT_GREEN_COLOR}'
- WHEN 'SurfaceFlinger Stuffing' THEN '${LIGHT_GREEN_COLOR}'
- WHEN 'No Jank' THEN '${GREEN_COLOR}'
- ELSE '${PINK_COLOR}'
- END as color
- from experimental_slice_layout s
- join actual_frame_timeline_slice afs using(id)
- where
- filter_track_ids = '${this.config.trackIds.join(',')}' and
- s.ts >= ${start - this.maxDur} and
- s.ts <= ${end}
- group by tsq, s.layout_depth
- order by tsq, s.layout_depth
- `);
+ const rawResult = await this.engine.query(`
+ SELECT
+ (s.ts + ${resolution / 2n}) / ${resolution} * ${resolution} as tsq,
+ s.ts as ts,
+ max(iif(s.dur = -1, (SELECT end_ts FROM trace_bounds) - s.ts, s.dur))
+ as dur,
+ s.layout_depth as layoutDepth,
+ s.name as name,
+ s.id as id,
+ s.dur = 0 as isInstant,
+ s.dur = -1 as isIncomplete,
+ CASE afs.jank_tag
+ WHEN 'Self Jank' THEN '${RED_COLOR}'
+ WHEN 'Other Jank' THEN '${YELLOW_COLOR}'
+ WHEN 'Dropped Frame' THEN '${BLUE_COLOR}'
+ WHEN 'Buffer Stuffing' THEN '${LIGHT_GREEN_COLOR}'
+ WHEN 'SurfaceFlinger Stuffing' THEN '${LIGHT_GREEN_COLOR}'
+ WHEN 'No Jank' THEN '${GREEN_COLOR}'
+ ELSE '${PINK_COLOR}'
+ END as color
+ from experimental_slice_layout s
+ join actual_frame_timeline_slice afs using(id)
+ where
+ filter_track_ids = '${this.trackIds.join(',')}' and
+ s.ts >= ${start - this.maxDur} and
+ s.ts <= ${end}
+ group by tsq, s.layout_depth
+ order by tsq, s.layout_depth
+`);
const numRows = rawResult.numRows();
- const slices: Data = {
+ const slices: SliceData = {
start,
end,
resolution,
@@ -154,17 +152,74 @@
}
}
-export class ActualFramesSliceTrack extends ChromeSliceTrack {
- static readonly kind = ACTUAL_FRAMES_SLICE_TRACK_KIND;
- static create(args: NewTrackArgs): TrackBase {
- return new ActualFramesSliceTrack(args);
- }
-}
-
class ActualFrames implements Plugin {
- onActivate(ctx: PluginContext): void {
- ctx.LEGACY_registerTrackController(ActualFramesSliceTrackController);
- ctx.LEGACY_registerTrack(ActualFramesSliceTrack);
+ onActivate(_ctx: PluginContext): void {}
+
+ async onTraceLoad(ctx: PluginContextTrace<undefined>): Promise<void> {
+ const {engine} = ctx;
+ const result = await engine.query(`
+ with process_async_tracks as materialized (
+ select
+ process_track.upid as upid,
+ process_track.name as trackName,
+ process.name as processName,
+ process.pid as pid,
+ group_concat(process_track.id) as trackIds,
+ count(1) as trackCount
+ from process_track
+ left join process using(upid)
+ where process_track.name = "Actual Timeline"
+ group by
+ process_track.upid,
+ process_track.name
+ )
+ select
+ t.*,
+ max_layout_depth(t.trackCount, t.trackIds) as maxDepth
+ from process_async_tracks t;
+ `);
+
+ const it = result.iter({
+ upid: NUM,
+ trackName: STR_NULL,
+ trackIds: STR,
+ processName: STR_NULL,
+ pid: NUM_NULL,
+ maxDepth: NUM_NULL,
+ });
+ for (; it.valid(); it.next()) {
+ const upid = it.upid;
+ const trackName = it.trackName;
+ const rawTrackIds = it.trackIds;
+ const trackIds = rawTrackIds.split(',').map((v) => Number(v));
+ const processName = it.processName;
+ const pid = it.pid;
+ const maxDepth = it.maxDepth;
+
+ if (maxDepth === null) {
+ // If there are no slices in this track, skip it.
+ continue;
+ }
+
+ const kind = 'ActualFrames';
+ const displayName =
+ getTrackName({name: trackName, upid, pid, processName, kind});
+
+ ctx.addTrack({
+ uri: `perfetto.ActualFrames#${upid}`,
+ displayName,
+ trackIds,
+ kind: ACTUAL_FRAMES_SLICE_TRACK_KIND,
+ track: ({trackInstanceId}) => {
+ return new SliceTrack(
+ engine,
+ maxDepth,
+ trackInstanceId,
+ trackIds,
+ );
+ },
+ });
+ }
}
}
diff --git a/ui/src/tracks/annotation/index.ts b/ui/src/tracks/annotation/index.ts
index 2c8649a..c1fdfce 100644
--- a/ui/src/tracks/annotation/index.ts
+++ b/ui/src/tracks/annotation/index.ts
@@ -23,6 +23,7 @@
PluginContextTrace,
PluginDescriptor,
} from '../../public';
+import {ChromeSliceTrack, SLICE_TRACK_KIND} from '../chrome_slices/';
import {
Config as CounterTrackConfig,
COUNTER_TRACK_KIND,
@@ -33,9 +34,48 @@
onActivate(_ctx: PluginContext): void {}
async onTraceLoad(ctx: PluginContextTrace): Promise<void> {
+ await this.addAnnotationTracks(ctx);
await this.addAnnotationCounterTracks(ctx);
}
+ private async addAnnotationTracks(ctx: PluginContextTrace<undefined>) {
+ const {engine} = ctx;
+
+ const result = await engine.query(`
+ select id, name
+ from annotation_slice_track
+ order by name
+ `);
+
+ const it = result.iter({
+ id: NUM,
+ name: STR,
+ });
+
+ for (; it.valid(); it.next()) {
+ const id = it.id;
+ const name = it.name;
+
+ ctx.addTrack({
+ uri: `perfetto.Annotation#${id}`,
+ displayName: name,
+ kind: SLICE_TRACK_KIND,
+ tags: {
+ metric: true,
+ },
+ track: (({trackInstanceId}) => {
+ return new ChromeSliceTrack(
+ engine,
+ 0,
+ trackInstanceId,
+ id,
+ 'annotation',
+ );
+ }),
+ });
+ }
+ }
+
private async addAnnotationCounterTracks(ctx: PluginContextTrace) {
const {engine} = ctx;
const counterResult = await engine.query(`
diff --git a/ui/src/tracks/async_slices/index.ts b/ui/src/tracks/async_slices/index.ts
index 09d0dda..01df88f 100644
--- a/ui/src/tracks/async_slices/index.ts
+++ b/ui/src/tracks/async_slices/index.ts
@@ -14,62 +14,57 @@
import {BigintMath as BIMath} from '../../base/bigint_math';
import {duration, time} from '../../base/time';
-import {LONG, LONG_NULL, NUM, STR} from '../../common/query_result';
-import {TrackData} from '../../common/track_data';
import {
- TrackController,
-} from '../../controller/track_controller';
-import {NewTrackArgs, TrackBase} from '../../frontend/track';
-import {Plugin, PluginContext, PluginDescriptor} from '../../public';
-import {ChromeSliceTrack} from '../chrome_slices';
+ LONG,
+ LONG_NULL,
+ NUM,
+ NUM_NULL,
+ STR,
+ STR_NULL,
+} from '../../common/query_result';
+import {SliceData, SliceTrackBase} from '../../frontend/slice_track_base';
+import {
+ EngineProxy,
+ Plugin,
+ PluginContext,
+ PluginContextTrace,
+ PluginDescriptor,
+} from '../../public';
+import {getTrackName} from '../../public/utils';
export const ASYNC_SLICE_TRACK_KIND = 'AsyncSliceTrack';
-export interface Config {
- maxDepth: number;
- trackIds: number[];
-}
-
-export interface Data extends TrackData {
- // Slices are stored in a columnar fashion. All fields have the same length.
- strings: string[];
- sliceIds: Float64Array;
- starts: BigInt64Array;
- ends: BigInt64Array;
- depths: Uint16Array;
- titles: Uint16Array; // Index in |strings|.
- isInstant: Uint16Array;
- isIncomplete: Uint16Array;
-}
-
-class AsyncSliceTrackController extends TrackController<Config, Data> {
- static readonly kind = ASYNC_SLICE_TRACK_KIND;
+class AsyncSliceTrack extends SliceTrackBase {
private maxDurNs: duration = 0n;
+ constructor(
+ private engine: EngineProxy, maxDepth: number, trackInstanceId: string,
+ private trackIds: number[], namespace?: string) {
+ // TODO is 'slice' right here?
+ super(maxDepth, trackInstanceId, 'slice', namespace);
+ }
+
async onBoundsChange(start: time, end: time, resolution: duration):
- Promise<Data> {
+ Promise<SliceData> {
if (this.maxDurNs === 0n) {
- const maxDurResult = await this.query(`
- select max(iif(dur = -1, (SELECT end_ts FROM trace_bounds) - ts, dur))
- as maxDur from experimental_slice_layout
- where filter_track_ids = '${this.config.trackIds.join(',')}'
+ const maxDurResult = await this.engine.query(`
+ select max(iif(dur = -1, (SELECT end_ts FROM trace_bounds) - ts,
+ dur)) as maxDur from experimental_slice_layout where filter_track_ids
+ = '${this.trackIds.join(',')}'
`);
this.maxDurNs = maxDurResult.firstRow({maxDur: LONG_NULL}).maxDur || 0n;
}
- const queryRes = await this.query(`
+ const queryRes = await this.engine.query(`
SELECT
(ts + ${resolution / 2n}) / ${resolution} * ${resolution} as tsq,
ts,
- max(iif(dur = -1, (SELECT end_ts FROM trace_bounds) - ts, dur)) as dur,
- layout_depth as depth,
- ifnull(name, '[null]') as name,
- id,
- dur = 0 as isInstant,
- dur = -1 as isIncomplete
+ max(iif(dur = -1, (SELECT end_ts FROM trace_bounds) - ts, dur)) as
+ dur, layout_depth as depth, ifnull(name, '[null]') as name, id, dur =
+ 0 as isInstant, dur = -1 as isIncomplete
from experimental_slice_layout
where
- filter_track_ids = '${this.config.trackIds.join(',')}' and
+ filter_track_ids = '${this.trackIds.join(',')}' and
ts >= ${start - this.maxDurNs} and
ts <= ${end}
group by tsq, layout_depth
@@ -77,7 +72,7 @@
`);
const numRows = queryRes.numRows();
- const slices: Data = {
+ const slices: SliceData = {
start,
end,
resolution,
@@ -132,17 +127,168 @@
}
}
-export class AsyncSliceTrack extends ChromeSliceTrack {
- static readonly kind = ASYNC_SLICE_TRACK_KIND;
- static create(args: NewTrackArgs): TrackBase {
- return new AsyncSliceTrack(args);
- }
-}
-
class AsyncSlicePlugin implements Plugin {
- onActivate(ctx: PluginContext) {
- ctx.LEGACY_registerTrackController(AsyncSliceTrackController);
- ctx.LEGACY_registerTrack(AsyncSliceTrack);
+ onActivate(_ctx: PluginContext) {}
+
+ async onTraceLoad(ctx: PluginContextTrace): Promise<void> {
+ await this.addGlobalAsyncTracks(ctx);
+ await this.addProcessAsyncSliceTracks(ctx);
+ }
+
+ async addGlobalAsyncTracks(ctx: PluginContextTrace): Promise<void> {
+ const {engine} = ctx;
+ const rawGlobalAsyncTracks = await engine.query(`
+ with tracks_with_slices as materialized (
+ select distinct track_id
+ from slice
+ ),
+ global_tracks as (
+ select
+ track.parent_id as parent_id,
+ track.id as track_id,
+ track.name as name
+ from track
+ join tracks_with_slices on tracks_with_slices.track_id = track.id
+ where
+ track.type = "track"
+ or track.type = "gpu_track"
+ or track.type = "cpu_track"
+ ),
+ global_tracks_grouped as (
+ select
+ parent_id,
+ name,
+ group_concat(track_id) as trackIds,
+ count(track_id) as trackCount
+ from global_tracks track
+ group by parent_id, name
+ )
+ select
+ t.parent_id as parentId,
+ p.name as parentName,
+ t.name as name,
+ t.trackIds as trackIds,
+ max_layout_depth(t.trackCount, t.trackIds) as maxDepth
+ from global_tracks_grouped AS t
+ left join track p on (t.parent_id = p.id)
+ order by p.name, t.name;
+ `);
+ const it = rawGlobalAsyncTracks.iter({
+ name: STR_NULL,
+ parentName: STR_NULL,
+ parentId: NUM_NULL,
+ trackIds: STR,
+ maxDepth: NUM_NULL,
+ });
+
+ // let scrollJankRendered = false;
+
+ for (; it.valid(); it.next()) {
+ const rawName = it.name === null ? undefined : it.name;
+ // const rawParentName = it.parentName === null ? undefined :
+ // it.parentName;
+ const displayName = getTrackName({name: rawName, kind: 'AsyncSlice'});
+ const rawTrackIds = it.trackIds;
+ const trackIds = rawTrackIds.split(',').map((v) => Number(v));
+ // const parentTrackId = it.parentId;
+ const maxDepth = it.maxDepth;
+
+ // If there are no slices in this track, skip it.
+ if (maxDepth === null) {
+ continue;
+ }
+
+ // if (ENABLE_SCROLL_JANK_PLUGIN_V2.get() && !scrollJankRendered &&
+ // name.includes(INPUT_LATENCY_TRACK)) {
+ // // This ensures that the scroll jank tracks render above the tracks
+ // // for GestureScrollUpdate.
+ // await this.addScrollJankTracks(this.engine);
+ // scrollJankRendered = true;
+ // }
+
+ ctx.addTrack({
+ uri: `perfetto.AsyncSlices#${rawName}`,
+ displayName,
+ trackIds,
+ kind: ASYNC_SLICE_TRACK_KIND,
+ track: ({trackInstanceId}) => {
+ return new AsyncSliceTrack(
+ engine,
+ maxDepth,
+ trackInstanceId,
+ trackIds,
+ );
+ },
+ });
+ }
+ }
+
+ async addProcessAsyncSliceTracks(ctx: PluginContextTrace): Promise<void> {
+ const result = await ctx.engine.query(`
+ with process_async_tracks as materialized (
+ select
+ process_track.upid as upid,
+ process_track.name as trackName,
+ process.name as processName,
+ process.pid as pid,
+ group_concat(process_track.id) as trackIds,
+ count(1) as trackCount
+ from process_track
+ left join process using(upid)
+ where
+ process_track.name is null or
+ process_track.name not like "% Timeline"
+ group by
+ process_track.upid,
+ process_track.name
+ )
+ select
+ t.*,
+ max_layout_depth(t.trackCount, t.trackIds) as maxDepth
+ from process_async_tracks t;
+ `);
+
+ const it = result.iter({
+ upid: NUM,
+ trackName: STR_NULL,
+ trackIds: STR,
+ processName: STR_NULL,
+ pid: NUM_NULL,
+ maxDepth: NUM_NULL,
+ });
+ for (; it.valid(); it.next()) {
+ const upid = it.upid;
+ const trackName = it.trackName;
+ const rawTrackIds = it.trackIds;
+ const trackIds = rawTrackIds.split(',').map((v) => Number(v));
+ const processName = it.processName;
+ const pid = it.pid;
+ const maxDepth = it.maxDepth;
+
+ if (maxDepth === null) {
+ // If there are no slices in this track, skip it.
+ continue;
+ }
+
+ const kind = ASYNC_SLICE_TRACK_KIND;
+ const displayName =
+ getTrackName({name: trackName, upid, pid, processName, kind});
+
+ ctx.addTrack({
+ uri: `perfetto.AsyncSlices#process.${pid}${rawTrackIds}`,
+ displayName,
+ trackIds,
+ kind: ASYNC_SLICE_TRACK_KIND,
+ track: ({trackInstanceId}) => {
+ return new AsyncSliceTrack(
+ ctx.engine,
+ maxDepth,
+ trackInstanceId,
+ trackIds,
+ );
+ },
+ });
+ }
}
}
diff --git a/ui/src/tracks/chrome_scroll_jank/chrome_tasks_scroll_jank_track.ts b/ui/src/tracks/chrome_scroll_jank/chrome_tasks_scroll_jank_track.ts
index 1026328..301a207 100644
--- a/ui/src/tracks/chrome_scroll_jank/chrome_tasks_scroll_jank_track.ts
+++ b/ui/src/tracks/chrome_scroll_jank/chrome_tasks_scroll_jank_track.ts
@@ -12,8 +12,6 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-import {v4 as uuidv4} from 'uuid';
-
import {Engine} from '../../common/engine';
import {NUM} from '../../common/query_result';
import {InThreadTrackSortKey} from '../../common/state';
@@ -79,20 +77,18 @@
}
result.tracksToAdd.push({
- id: uuidv4(),
- engineId: engine.id,
- kind: ChromeTasksScrollJankTrack.kind,
+ uri: 'perfetto.ChromeScrollJank',
trackSortKey: {
utid: it.utid,
priority: InThreadTrackSortKey.ORDINARY,
},
name: 'Scroll Jank causes - long tasks',
- config: {},
trackGroup: getTrackGroupUuid(it.utid, it.upid),
});
// Initialise the chrome_tasks_delaying_input_processing table. It will be
// used in the sql table above.
+ // TODO(stevegolton): Use viewer.tabs.openQuery().
await engine.query(`
select RUN_METRIC(
'chrome/chrome_tasks_delaying_input_processing.sql',
diff --git a/ui/src/tracks/chrome_scroll_jank/event_latency_track.ts b/ui/src/tracks/chrome_scroll_jank/event_latency_track.ts
index 42ecf77..539d782 100644
--- a/ui/src/tracks/chrome_scroll_jank/event_latency_track.ts
+++ b/ui/src/tracks/chrome_scroll_jank/event_latency_track.ts
@@ -12,15 +12,9 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-import {v4 as uuidv4} from 'uuid';
-
import {
getColorForSlice,
} from '../../common/colorizer';
-import {Engine} from '../../common/engine';
-import {
- generateSqlWithInternalLayout,
-} from '../../common/internal_layout_utils';
import {globals} from '../../frontend/globals';
import {
NamedSliceTrackTypes,
@@ -41,15 +35,18 @@
} from './index';
import {DEEP_RED_COLOR, RED_COLOR} from './jank_colors';
-const JANKY_LATENCY_NAME = 'Janky EventLatency';
+export const JANKY_LATENCY_NAME = 'Janky EventLatency';
export interface EventLatencyTrackTypes extends NamedSliceTrackTypes {
config: {baseTable: string;}
}
+const CHROME_EVENT_LATENCY_TRACK_KIND =
+ 'org.chromium.ScrollJank.event_latencies';
+
export class EventLatencyTrack extends
CustomSqlTableSliceTrack<EventLatencyTrackTypes> {
- static readonly kind = 'org.chromium.ScrollJank.event_latencies';
+ static readonly kind = CHROME_EVENT_LATENCY_TRACK_KIND;
static create(args: NewTrackArgs): TrackBase {
return new EventLatencyTrack(args);
@@ -117,83 +114,15 @@
// this behavior should be customized to show jank-related data.
}
-export async function addLatencyTracks(engine: Engine):
- Promise<DecideTracksResult> {
+export async function addLatencyTracks(): Promise<DecideTracksResult> {
const result: DecideTracksResult = {
tracksToAdd: [],
};
- const subTableSql = generateSqlWithInternalLayout({
- columns: ['id', 'ts', 'dur', 'track_id', 'name'],
- sourceTable: 'slice',
- ts: 'ts',
- dur: 'dur',
- whereClause: `
- EXTRACT_ARG(arg_set_id, 'event_latency.event_type') IN (
- 'FIRST_GESTURE_SCROLL_UPDATE',
- 'GESTURE_SCROLL_UPDATE',
- 'INERTIAL_GESTURE_SCROLL_UPDATE')
- AND HAS_DESCENDANT_SLICE_WITH_NAME(
- id,
- 'SubmitCompositorFrameToPresentationCompositorFrame')`,
- });
-
- // Table name must be unique - it cannot include '-' characters or begin with
- // a numeric value.
- const baseTable =
- `table_${uuidv4().split('-').join('_')}_janky_event_latencies_v3`;
- const tableDefSql = `CREATE TABLE ${baseTable} AS
- WITH event_latencies AS (
- ${subTableSql}
- ), latency_stages AS (
- SELECT
- d.id,
- d.ts,
- d.dur,
- d.track_id,
- d.name,
- d.depth,
- min(a.id) AS parent_id
- FROM slice s
- JOIN descendant_slice(s.id) d
- JOIN ancestor_slice(d.id) a
- WHERE s.id IN (SELECT id FROM event_latencies)
- GROUP BY d.id, d.ts, d.dur, d.track_id, d.name, d.parent_id, d.depth)
- SELECT
- id,
- ts,
- dur,
- CASE
- WHEN id IN (
- SELECT id FROM chrome_janky_event_latencies_v3)
- THEN '${JANKY_LATENCY_NAME}'
- ELSE name
- END
- AS name,
- depth * 3 AS depth
- FROM event_latencies
- UNION ALL
- SELECT
- ls.id,
- ls.ts,
- ls.dur,
- ls.name,
- depth + (
- (SELECT depth FROM event_latencies
- WHERE id = ls.parent_id LIMIT 1) * 3) AS depth
- FROM latency_stages ls;`;
-
- await engine.query(
- `INCLUDE PERFETTO MODULE chrome.scroll_jank.scroll_jank_intervals`);
- await engine.query(tableDefSql);
-
result.tracksToAdd.push({
- id: uuidv4(),
- engineId: engine.id,
- kind: EventLatencyTrack.kind,
+ uri: 'perfetto.ChromeScrollJank#eventLatency',
trackSortKey: PrimaryTrackSortKey.ASYNC_SLICE_TRACK,
name: 'Chrome Scroll Input Latencies',
- config: {baseTable: baseTable},
trackGroup: SCROLL_JANK_GROUP_ID,
});
diff --git a/ui/src/tracks/chrome_scroll_jank/index.ts b/ui/src/tracks/chrome_scroll_jank/index.ts
index 5494921..b8c028f 100644
--- a/ui/src/tracks/chrome_scroll_jank/index.ts
+++ b/ui/src/tracks/chrome_scroll_jank/index.ts
@@ -17,25 +17,35 @@
import {Actions, AddTrackArgs, DeferredAction} from '../../common/actions';
import {Engine} from '../../common/engine';
import {featureFlags} from '../../common/feature_flags';
+import {
+ generateSqlWithInternalLayout,
+} from '../../common/internal_layout_utils';
import {ObjectById} from '../../common/state';
import {
Plugin,
PluginContext,
+ PluginContextTrace,
PluginDescriptor,
PrimaryTrackSortKey,
} from '../../public';
import {CustomSqlDetailsPanelConfig} from '../custom_sql_table_slices';
-import {NULL_TRACK_KIND} from '../null_track';
+import {NULL_TRACK_URI} from '../null_track';
import {ChromeTasksScrollJankTrack} from './chrome_tasks_scroll_jank_track';
-import {addLatencyTracks, EventLatencyTrack} from './event_latency_track';
+import {
+ addLatencyTracks,
+ EventLatencyTrack,
+ JANKY_LATENCY_NAME,
+} from './event_latency_track';
import {
addScrollJankV3ScrollTrack,
ScrollJankV3Track,
} from './scroll_jank_v3_track';
-import {addTopLevelScrollTrack, TopLevelScrollTrack} from './scroll_track';
-
-export {Data} from '../chrome_slices';
+import {
+ addTopLevelScrollTrack,
+ CHROME_TOPLEVEL_SCROLLS_KIND,
+ TopLevelScrollTrack,
+} from './scroll_track';
export const ENABLE_CHROME_SCROLL_JANK_PLUGIN = featureFlags.register({
id: 'enableChromeScrollJankPlugin',
@@ -106,41 +116,31 @@
}
}
-export async function getScrollJankTracks(engine: Engine):
+export async function getScrollJankTracks(_engine: Engine):
Promise<ScrollJankTrackGroup> {
const result: ScrollJankTracks = {
tracksToAdd: [],
};
- const summaryTrackId = uuidv4();
+ const scrolls = await addTopLevelScrollTrack();
+ result.tracksToAdd = result.tracksToAdd.concat(scrolls.tracksToAdd);
+ const janks = await addScrollJankV3ScrollTrack();
+ result.tracksToAdd = result.tracksToAdd.concat(janks.tracksToAdd);
+
+ const eventLatencies = await addLatencyTracks();
+ result.tracksToAdd = result.tracksToAdd.concat(eventLatencies.tracksToAdd);
+
+ const summaryTrackId = uuidv4();
result.tracksToAdd.push({
- engineId: engine.id,
- kind: NULL_TRACK_KIND,
+ uri: NULL_TRACK_URI,
trackSortKey: PrimaryTrackSortKey.ASYNC_SLICE_TRACK,
- name: ``,
+ name: '', // TODO(stevegolton): We should probably put some name here.
trackGroup: undefined,
- config: {},
id: summaryTrackId,
});
- const scrolls = addTopLevelScrollTrack(engine);
- for (const scroll of (await scrolls).tracksToAdd) {
- result.tracksToAdd.push(scroll);
- }
-
- const janks = addScrollJankV3ScrollTrack(engine);
- for (const jank of (await janks).tracksToAdd) {
- result.tracksToAdd.push(jank);
- }
-
- const eventLatencies = addLatencyTracks(engine);
- for (const eventLatency of (await eventLatencies).tracksToAdd) {
- result.tracksToAdd.push(eventLatency);
- }
-
const addTrackGroup = Actions.addTrackGroup({
- engineId: engine.id,
name: 'Chrome Scroll Jank',
id: SCROLL_JANK_GROUP_ID,
collapsed: false,
@@ -152,11 +152,149 @@
}
class ChromeScrollJankPlugin implements Plugin {
- onActivate(ctx: PluginContext): void {
- ctx.LEGACY_registerTrack(ChromeTasksScrollJankTrack);
- ctx.LEGACY_registerTrack(EventLatencyTrack);
- ctx.LEGACY_registerTrack(ScrollJankV3Track);
- ctx.LEGACY_registerTrack(TopLevelScrollTrack);
+ onActivate(_ctx: PluginContext): void {}
+
+ async onTraceLoad(ctx: PluginContextTrace): Promise<void> {
+ await this.addChromeScrollJankTrack(ctx);
+ await this.addTopLevelScrollTrack(ctx);
+ await this.addEventLatencyTrack(ctx);
+ await this.addScrollJankV3ScrollTrack(ctx);
+ }
+
+ private async addChromeScrollJankTrack(ctx: PluginContextTrace):
+ Promise<void> {
+ ctx.addTrack({
+ uri: 'perfetto.ChromeScrollJank',
+ displayName: 'Scroll Jank causes - long tasks',
+ kind: ChromeTasksScrollJankTrack.kind,
+ track: ({trackInstanceId}) => {
+ return new ChromeTasksScrollJankTrack({
+ engine: ctx.engine,
+ trackId: trackInstanceId,
+ });
+ },
+ });
+ }
+
+ private async addTopLevelScrollTrack(ctx: PluginContextTrace): Promise<void> {
+ await ctx.engine.query(`
+ INCLUDE PERFETTO MODULE chrome.chrome_scrolls;
+ INCLUDE PERFETTO MODULE chrome.scroll_jank.scroll_offsets;
+ `);
+
+ ctx.addTrack({
+ uri: 'perfetto.ChromeScrollJank#toplevelScrolls',
+ displayName: 'Chrome Scrolls',
+ kind: CHROME_TOPLEVEL_SCROLLS_KIND,
+ track: ({trackInstanceId}) => {
+ return new TopLevelScrollTrack({
+ engine: ctx.engine,
+ trackId: trackInstanceId,
+ });
+ },
+ });
+ }
+
+ private async addEventLatencyTrack(ctx: PluginContextTrace): Promise<void> {
+ const subTableSql = generateSqlWithInternalLayout({
+ columns: ['id', 'ts', 'dur', 'track_id', 'name'],
+ sourceTable: 'slice',
+ ts: 'ts',
+ dur: 'dur',
+ whereClause: `
+ EXTRACT_ARG(arg_set_id, 'event_latency.event_type') IN (
+ 'FIRST_GESTURE_SCROLL_UPDATE',
+ 'GESTURE_SCROLL_UPDATE',
+ 'INERTIAL_GESTURE_SCROLL_UPDATE')
+ AND HAS_DESCENDANT_SLICE_WITH_NAME(
+ id,
+ 'SubmitCompositorFrameToPresentationCompositorFrame')`,
+ });
+
+ // Table name must be unique - it cannot include '-' characters or begin
+ // with a numeric value.
+ const baseTable =
+ `table_${uuidv4().split('-').join('_')}_janky_event_latencies_v3`;
+ const tableDefSql = `CREATE TABLE ${baseTable} AS
+ WITH event_latencies AS (
+ ${subTableSql}
+ ), latency_stages AS (
+ SELECT
+ d.id,
+ d.ts,
+ d.dur,
+ d.track_id,
+ d.name,
+ d.depth,
+ min(a.id) AS parent_id
+ FROM slice s
+ JOIN descendant_slice(s.id) d
+ JOIN ancestor_slice(d.id) a
+ WHERE s.id IN (SELECT id FROM event_latencies)
+ GROUP BY d.id, d.ts, d.dur, d.track_id, d.name, d.parent_id, d.depth)
+ SELECT
+ id,
+ ts,
+ dur,
+ CASE
+ WHEN id IN (
+ SELECT id FROM chrome_janky_event_latencies_v3)
+ THEN '${JANKY_LATENCY_NAME}'
+ ELSE name
+ END
+ AS name,
+ depth * 3 AS depth
+ FROM event_latencies
+ UNION ALL
+ SELECT
+ ls.id,
+ ls.ts,
+ ls.dur,
+ ls.name,
+ depth + (
+ (SELECT depth FROM event_latencies
+ WHERE id = ls.parent_id LIMIT 1) * 3) AS depth
+ FROM latency_stages ls;`;
+
+ await ctx.engine.query(
+ `INCLUDE PERFETTO MODULE chrome.scroll_jank.scroll_jank_intervals`);
+ await ctx.engine.query(tableDefSql);
+
+ ctx.addTrack({
+ uri: 'perfetto.ChromeScrollJank#eventLatency',
+ displayName: 'Chrome Scroll Input Latencies',
+ kind: EventLatencyTrack.kind,
+ track: ({trackInstanceId}) => {
+ const track = new EventLatencyTrack({
+ engine: ctx.engine,
+ trackId: trackInstanceId,
+ });
+
+ track.config = {
+ baseTable,
+ };
+
+ return track;
+ },
+ });
+ }
+
+ private async addScrollJankV3ScrollTrack(ctx: PluginContextTrace):
+ Promise<void> {
+ await ctx.engine.query(
+ `INCLUDE PERFETTO MODULE chrome.scroll_jank.scroll_jank_intervals`);
+
+ ctx.addTrack({
+ uri: 'perfetto.ChromeScrollJank#scrollJankV3',
+ displayName: 'Chrome Scroll Janks',
+ kind: ScrollJankV3Track.kind,
+ track: ({trackInstanceId}) => {
+ return new ScrollJankV3Track({
+ engine: ctx.engine,
+ trackId: trackInstanceId,
+ });
+ },
+ });
}
}
diff --git a/ui/src/tracks/chrome_scroll_jank/scroll_jank_v3_track.ts b/ui/src/tracks/chrome_scroll_jank/scroll_jank_v3_track.ts
index df2556c..aa32889 100644
--- a/ui/src/tracks/chrome_scroll_jank/scroll_jank_v3_track.ts
+++ b/ui/src/tracks/chrome_scroll_jank/scroll_jank_v3_track.ts
@@ -12,12 +12,9 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-import {v4 as uuidv4} from 'uuid';
-
import {
getColorForSlice,
} from '../../common/colorizer';
-import {Engine} from '../../common/engine';
import {globals} from '../../frontend/globals';
import {NamedSliceTrackTypes} from '../../frontend/named_slice_track';
import {NewTrackArgs, TrackBase} from '../../frontend/track';
@@ -37,8 +34,6 @@
import {DEEP_RED_COLOR, RED_COLOR} from './jank_colors';
import {ScrollJankV3DetailsPanel} from './scroll_jank_v3_details_panel';
-export {Data} from '../chrome_slices';
-
const UNKNOWN_SLICE_NAME = 'Unknown';
const JANK_SLICE_NAME = ' Jank';
@@ -125,22 +120,16 @@
}
}
-export async function addScrollJankV3ScrollTrack(engine: Engine):
+export async function addScrollJankV3ScrollTrack():
Promise<DecideTracksResult> {
const result: DecideTracksResult = {
tracksToAdd: [],
};
- await engine.query(
- `INCLUDE PERFETTO MODULE chrome.scroll_jank.scroll_jank_intervals`);
-
result.tracksToAdd.push({
- id: uuidv4(),
- engineId: engine.id,
- kind: ScrollJankV3Track.kind,
+ uri: 'perfetto.ChromeScrollJank#scrollJankV3',
trackSortKey: PrimaryTrackSortKey.ASYNC_SLICE_TRACK,
name: 'Chrome Scroll Janks',
- config: {},
trackGroup: SCROLL_JANK_GROUP_ID,
});
diff --git a/ui/src/tracks/chrome_scroll_jank/scroll_track.ts b/ui/src/tracks/chrome_scroll_jank/scroll_track.ts
index fcfa639..70c273f 100644
--- a/ui/src/tracks/chrome_scroll_jank/scroll_track.ts
+++ b/ui/src/tracks/chrome_scroll_jank/scroll_track.ts
@@ -12,10 +12,6 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-import {v4 as uuidv4} from 'uuid';
-
-import {Engine} from '../../common/engine';
-
import {NamedSliceTrackTypes} from '../../frontend/named_slice_track';
import {NewTrackArgs, TrackBase} from '../../frontend/track';
import {PrimaryTrackSortKey} from '../../public';
@@ -31,12 +27,12 @@
} from './index';
import {ScrollDetailsPanel} from './scroll_details_panel';
-export {Data} from '../chrome_slices';
+export const CHROME_TOPLEVEL_SCROLLS_KIND =
+ 'org.chromium.TopLevelScrolls.scrolls';
export class TopLevelScrollTrack extends
CustomSqlTableSliceTrack<NamedSliceTrackTypes> {
- static readonly kind = 'org.chromium.TopLevelScrolls.scrolls';
-
+ public static kind = CHROME_TOPLEVEL_SCROLLS_KIND;
static create(args: NewTrackArgs): TrackBase {
return new TopLevelScrollTrack(args);
}
@@ -76,24 +72,15 @@
}
}
-export async function addTopLevelScrollTrack(engine: Engine):
- Promise<DecideTracksResult> {
+export async function addTopLevelScrollTrack(): Promise<DecideTracksResult> {
const result: DecideTracksResult = {
tracksToAdd: [],
};
- await engine.query(`
- INCLUDE PERFETTO MODULE chrome.chrome_scrolls;
- INCLUDE PERFETTO MODULE chrome.scroll_jank.scroll_offsets;
- `);
-
result.tracksToAdd.push({
- id: uuidv4(),
- engineId: engine.id,
- kind: TopLevelScrollTrack.kind,
+ uri: 'perfetto.ChromeScrollJank#toplevelScrolls',
trackSortKey: PrimaryTrackSortKey.ASYNC_SLICE_TRACK,
name: 'Chrome Scrolls',
- config: {},
trackGroup: SCROLL_JANK_GROUP_ID,
});
diff --git a/ui/src/tracks/generic_slice_track/index.ts b/ui/src/tracks/chrome_slices/generic_slice_track.ts
similarity index 80%
rename from ui/src/tracks/generic_slice_track/index.ts
rename to ui/src/tracks/chrome_slices/generic_slice_track.ts
index 6053621..802236b 100644
--- a/ui/src/tracks/generic_slice_track/index.ts
+++ b/ui/src/tracks/chrome_slices/generic_slice_track.ts
@@ -17,7 +17,6 @@
NamedSliceTrackTypes,
} from '../../frontend/named_slice_track';
import {NewTrackArgs} from '../../frontend/track';
-import {Plugin, PluginContext, PluginDescriptor} from '../../public';
export interface GenericSliceTrackConfig {
sqlTrackId: number;
@@ -44,14 +43,3 @@
await this.engine.query(sql);
}
}
-
-class GenericSliceTrackPlugin implements Plugin {
- onActivate(ctx: PluginContext): void {
- ctx.LEGACY_registerTrack(GenericSliceTrack);
- }
-}
-
-export const plugin: PluginDescriptor = {
- pluginId: 'perfetto.GenericSliceTrack',
- plugin: GenericSliceTrackPlugin,
-};
diff --git a/ui/src/tracks/chrome_slices/index.ts b/ui/src/tracks/chrome_slices/index.ts
index 28efb24..1392820 100644
--- a/ui/src/tracks/chrome_slices/index.ts
+++ b/ui/src/tracks/chrome_slices/index.ts
@@ -13,63 +13,50 @@
// limitations under the License.
import {BigintMath as BIMath} from '../../base/bigint_math';
-import {duration, Span, Time, time} from '../../base/time';
-import {Actions} from '../../common/actions';
-import {cropText, drawIncompleteSlice} from '../../common/canvas_utils';
+import {Duration, duration, time} from '../../base/time';
import {
- colorForThreadIdleSlice,
- getColorForSlice,
-} from '../../common/colorizer';
-import {HighPrecisionTime} from '../../common/high_precision_time';
-import {LONG, LONG_NULL, NUM, STR} from '../../common/query_result';
-import {TrackData} from '../../common/track_data';
-import {TrackController} from '../../controller/track_controller';
-import {checkerboardExcept} from '../../frontend/checkerboard';
-import {globals} from '../../frontend/globals';
-import {cachedHsluvToHex} from '../../frontend/hsluv_cache';
-import {PxSpan, TimeScale} from '../../frontend/time_scale';
-import {NewTrackArgs, SliceRect, TrackBase} from '../../frontend/track';
-import {Plugin, PluginContext, PluginDescriptor} from '../../public';
+ LONG,
+ LONG_NULL,
+ NUM,
+ NUM_NULL,
+ STR,
+ STR_NULL,
+} from '../../common/query_result';
+import {
+ SliceData,
+ SliceTrackBase,
+} from '../../frontend/slice_track_base';
+import {
+ EngineProxy,
+ Plugin,
+ PluginContext,
+ PluginContextTrace,
+ PluginDescriptor,
+} from '../../public';
+import {getTrackName} from '../../public/utils';
+
+import {GenericSliceTrack} from './generic_slice_track';
export const SLICE_TRACK_KIND = 'ChromeSliceTrack';
-const SLICE_HEIGHT = 18;
-const TRACK_PADDING = 2;
-const CHEVRON_WIDTH_PX = 10;
-const HALF_CHEVRON_WIDTH_PX = CHEVRON_WIDTH_PX / 2;
-export interface Config {
- maxDepth: number;
- namespace: string;
- trackId: number;
-}
-
-export interface Data extends TrackData {
- // Slices are stored in a columnar fashion.
- strings: string[];
- sliceIds: Float64Array;
- starts: BigInt64Array;
- ends: BigInt64Array;
- depths: Uint16Array;
- titles: Uint16Array; // Index into strings.
- colors?: Uint16Array; // Index into strings.
- isInstant: Uint16Array;
- isIncomplete: Uint16Array;
- cpuTimeRatio?: Float64Array;
-}
-
-export class ChromeSliceTrackController extends TrackController<Config, Data> {
- static kind = SLICE_TRACK_KIND;
+export class ChromeSliceTrack extends SliceTrackBase {
private maxDurNs: duration = 0n;
+ constructor(
+ protected engine: EngineProxy, maxDepth: number, trackInstanceId: string,
+ private tpTrackId: number, namespace?: string) {
+ super(maxDepth, trackInstanceId, 'slice', namespace);
+ }
+
async onBoundsChange(start: time, end: time, resolution: duration):
- Promise<Data> {
+ Promise<SliceData> {
const tableName = this.namespaceTable('slice');
- if (this.maxDurNs === 0n) {
+ if (this.maxDurNs === Duration.ZERO) {
const query = `
SELECT max(iif(dur = -1, (SELECT end_ts FROM trace_bounds) - ts, dur))
- AS maxDur FROM ${tableName} WHERE track_id = ${this.config.trackId}`;
- const queryRes = await this.query(query);
+ AS maxDur FROM ${tableName} WHERE track_id = ${this.tpTrackId}`;
+ const queryRes = await this.engine.query(query);
this.maxDurNs = queryRes.firstRow({maxDur: LONG_NULL}).maxDur || 0n;
}
@@ -85,14 +72,14 @@
dur = -1 as isIncomplete,
thread_dur as threadDur
FROM ${tableName}
- WHERE track_id = ${this.config.trackId} AND
+ WHERE track_id = ${this.tpTrackId} AND
ts >= (${start - this.maxDurNs}) AND
ts <= ${end}
GROUP BY depth, tsq`;
- const queryRes = await this.query(query);
+ const queryRes = await this.engine.query(query);
const numRows = queryRes.numRows();
- const slices: Data = {
+ const slices: SliceData = {
start,
end,
resolution,
@@ -159,288 +146,87 @@
}
}
-export class ChromeSliceTrack extends TrackBase<Config, Data> {
- static readonly kind: string = SLICE_TRACK_KIND;
- static create(args: NewTrackArgs): TrackBase {
- return new ChromeSliceTrack(args);
- }
-
- private hoveredTitleId = -1;
-
- constructor(args: NewTrackArgs) {
- super(args);
- }
-
- // Font used to render the slice name on the current track.
- protected getFont() {
- return '12px Roboto Condensed';
- }
-
- renderCanvas(ctx: CanvasRenderingContext2D): void {
- // TODO: fonts and colors should come from the CSS and not hardcoded here.
- const data = this.data();
- if (data === undefined) return; // Can't possibly draw anything.
-
- const {visibleTimeSpan, visibleWindowTime, visibleTimeScale, windowSpan} =
- globals.frontendLocalState;
-
- // If the cached trace slices don't fully cover the visible time range,
- // show a gray rectangle with a "Loading..." label.
- checkerboardExcept(
- ctx,
- this.getHeight(),
- visibleTimeScale.hpTimeToPx(visibleWindowTime.start),
- visibleTimeScale.hpTimeToPx(visibleWindowTime.end),
- visibleTimeScale.timeToPx(data.start),
- visibleTimeScale.timeToPx(data.end),
- );
-
- ctx.textAlign = 'center';
-
- // measuretext is expensive so we only use it once.
- const charWidth = ctx.measureText('ACBDLqsdfg').width / 10;
-
- // The draw of the rect on the selected slice must happen after the other
- // drawings, otherwise it would result under another rect.
- let drawRectOnSelected = () => {};
-
-
- for (let i = 0; i < data.starts.length; i++) {
- const tStart = Time.fromRaw(data.starts[i]);
- let tEnd = Time.fromRaw(data.ends[i]);
- const depth = data.depths[i];
- const titleId = data.titles[i];
- const sliceId = data.sliceIds[i];
- const isInstant = data.isInstant[i];
- const isIncomplete = data.isIncomplete[i];
- const title = data.strings[titleId];
- const colorOverride = data.colors && data.strings[data.colors[i]];
- if (isIncomplete) { // incomplete slice
- // TODO(stevegolton): This isn't exactly equivalent, ideally we should
- // choose tEnd once we've conerted to screen space coords.
- tEnd = visibleWindowTime.end.toTime('ceil');
- }
-
- if (!visibleTimeSpan.intersects(tStart, tEnd)) {
- continue;
- }
-
- const rect = this.getSliceRect(
- visibleTimeScale, visibleTimeSpan, windowSpan, tStart, tEnd, depth);
- if (!rect || !rect.visible) {
- continue;
- }
-
- const currentSelection = globals.state.currentSelection;
- const isSelected = currentSelection &&
- currentSelection.kind === 'CHROME_SLICE' &&
- currentSelection.id !== undefined && currentSelection.id === sliceId;
-
- const highlighted = titleId === this.hoveredTitleId ||
- globals.state.highlightedSliceId === sliceId;
-
- const hasFocus = highlighted || isSelected;
- const colorObj = getColorForSlice(title, hasFocus);
-
- let color: string;
- if (colorOverride === undefined) {
- color = colorObj.c;
- } else {
- color = colorOverride;
- }
- ctx.fillStyle = color;
-
- // We draw instant events as upward facing chevrons starting at A:
- // A
- // ###
- // ##C##
- // ## ##
- // D B
- // Then B, C, D and back to A:
- if (isInstant) {
- if (isSelected) {
- drawRectOnSelected = () => {
- ctx.save();
- ctx.translate(rect.left, rect.top);
-
- // Draw a rectangle around the selected slice
- ctx.strokeStyle = cachedHsluvToHex(colorObj.h, 100, 10);
- ctx.beginPath();
- ctx.lineWidth = 3;
- ctx.strokeRect(
- -HALF_CHEVRON_WIDTH_PX, 0, CHEVRON_WIDTH_PX, SLICE_HEIGHT);
- ctx.closePath();
-
- // Draw inner chevron as interior
- ctx.fillStyle = color;
- this.drawChevron(ctx);
-
- ctx.restore();
- };
- } else {
- ctx.save();
- ctx.translate(rect.left, rect.top);
- this.drawChevron(ctx);
- ctx.restore();
- }
- continue;
- }
-
- if (isIncomplete && rect.width > SLICE_HEIGHT / 4) {
- drawIncompleteSlice(ctx, rect.left, rect.top, rect.width, SLICE_HEIGHT);
- } else if (
- data.cpuTimeRatio !== undefined && data.cpuTimeRatio[i] < 1 - 1e-9) {
- // We draw two rectangles, representing the ratio between wall time and
- // time spent on cpu.
- const cpuTimeRatio = data.cpuTimeRatio![i];
- const firstPartWidth = rect.width * cpuTimeRatio;
- const secondPartWidth = rect.width * (1 - cpuTimeRatio);
- ctx.fillRect(rect.left, rect.top, firstPartWidth, SLICE_HEIGHT);
- ctx.fillStyle = colorForThreadIdleSlice(
- colorObj.h, colorObj.s, colorObj.l, hasFocus);
- ctx.fillRect(
- rect.left + firstPartWidth,
- rect.top,
- secondPartWidth,
- SLICE_HEIGHT);
- } else {
- ctx.fillRect(rect.left, rect.top, rect.width, SLICE_HEIGHT);
- }
-
- // Selected case
- if (isSelected) {
- drawRectOnSelected = () => {
- ctx.strokeStyle = cachedHsluvToHex(colorObj.h, 100, 10);
- ctx.beginPath();
- ctx.lineWidth = 3;
- ctx.strokeRect(
- rect.left, rect.top - 1.5, rect.width, SLICE_HEIGHT + 3);
- ctx.closePath();
- };
- }
-
- // Don't render text when we have less than 5px to play with.
- if (rect.width >= 5) {
- ctx.fillStyle = colorObj.l > 65 ? '#404040' : 'white';
- const displayText = cropText(title, charWidth, rect.width);
- const rectXCenter = rect.left + rect.width / 2;
- ctx.textBaseline = 'middle';
- ctx.font = this.getFont();
- ctx.fillText(displayText, rectXCenter, rect.top + SLICE_HEIGHT / 2);
- }
- }
- drawRectOnSelected();
- }
-
- drawChevron(ctx: CanvasRenderingContext2D) {
- // Draw a chevron at a fixed location and size. Should be used with
- // ctx.translate and ctx.scale to alter location and size.
- ctx.beginPath();
- ctx.moveTo(0, 0);
- ctx.lineTo(HALF_CHEVRON_WIDTH_PX, SLICE_HEIGHT);
- ctx.lineTo(0, SLICE_HEIGHT - HALF_CHEVRON_WIDTH_PX);
- ctx.lineTo(-HALF_CHEVRON_WIDTH_PX, SLICE_HEIGHT);
- ctx.lineTo(0, 0);
- ctx.fill();
- }
-
- getSliceIndex({x, y}: {x: number, y: number}): number|void {
- const data = this.data();
- if (data === undefined) return;
- const {
- visibleTimeScale: timeScale,
- visibleWindowTime: visibleHPTimeSpan,
- } = globals.frontendLocalState;
- if (y < TRACK_PADDING) return;
- const instantWidthTime = timeScale.pxDeltaToDuration(HALF_CHEVRON_WIDTH_PX);
- const t = timeScale.pxToHpTime(x);
- const depth = Math.floor((y - TRACK_PADDING) / SLICE_HEIGHT);
-
- for (let i = 0; i < data.starts.length; i++) {
- if (depth !== data.depths[i]) {
- continue;
- }
- const start = Time.fromRaw(data.starts[i]);
- const tStart = HighPrecisionTime.fromTime(start);
- if (data.isInstant[i]) {
- if (tStart.sub(t).abs().lt(instantWidthTime)) {
- return i;
- }
- } else {
- const end = Time.fromRaw(data.ends[i]);
- let tEnd = HighPrecisionTime.fromTime(end);
- if (data.isIncomplete[i]) {
- tEnd = visibleHPTimeSpan.end;
- }
- if (tStart.lte(t) && t.lte(tEnd)) {
- return i;
- }
- }
- }
- }
-
- onMouseMove({x, y}: {x: number, y: number}) {
- this.hoveredTitleId = -1;
- globals.dispatch(Actions.setHighlightedSliceId({sliceId: -1}));
- const sliceIndex = this.getSliceIndex({x, y});
- if (sliceIndex === undefined) return;
- const data = this.data();
- if (data === undefined) return;
- this.hoveredTitleId = data.titles[sliceIndex];
- const sliceId = data.sliceIds[sliceIndex];
- globals.dispatch(Actions.setHighlightedSliceId({sliceId}));
- }
-
- onMouseOut() {
- this.hoveredTitleId = -1;
- globals.dispatch(Actions.setHighlightedSliceId({sliceId: -1}));
- }
-
- onMouseClick({x, y}: {x: number, y: number}): boolean {
- const sliceIndex = this.getSliceIndex({x, y});
- if (sliceIndex === undefined) return false;
- const data = this.data();
- if (data === undefined) return false;
- const sliceId = data.sliceIds[sliceIndex];
- if (sliceId !== undefined && sliceId !== -1) {
- globals.makeSelection(Actions.selectChromeSlice({
- id: sliceId,
- trackId: this.trackState.id,
- table: this.config.namespace,
- }));
- return true;
- }
- return false;
- }
-
- getHeight() {
- return SLICE_HEIGHT * (this.config.maxDepth + 1) + 2 * TRACK_PADDING;
- }
-
- getSliceRect(
- visibleTimeScale: TimeScale, visibleWindow: Span<time, duration>,
- windowSpan: PxSpan, tStart: time, tEnd: time, depth: number): SliceRect
- |undefined {
- const pxEnd = windowSpan.end;
- const left = Math.max(visibleTimeScale.timeToPx(tStart), 0);
- const right = Math.min(visibleTimeScale.timeToPx(tEnd), pxEnd);
-
- const visible = visibleWindow.intersects(tStart, tEnd);
-
- return {
- left,
- width: Math.max(right - left, 1),
- top: TRACK_PADDING + depth * SLICE_HEIGHT,
- height: SLICE_HEIGHT,
- visible,
- };
- }
-}
-
class ChromeSlicesPlugin implements Plugin {
- onActivate(ctx: PluginContext): void {
- ctx.LEGACY_registerTrackController(ChromeSliceTrackController);
- ctx.LEGACY_registerTrack(ChromeSliceTrack);
+ onActivate(_ctx: PluginContext): void {}
+
+ async onTraceLoad(ctx: PluginContextTrace): Promise<void> {
+ const {engine} = ctx;
+ const result = await engine.query(`
+ select
+ thread_track.utid as utid,
+ thread_track.id as trackId,
+ thread_track.name as trackName,
+ EXTRACT_ARG(thread_track.source_arg_set_id,
+ 'is_root_in_scope') as isDefaultTrackForScope,
+ tid,
+ thread.name as threadName,
+ max(slice.depth) as maxDepth,
+ process.upid as upid
+ from slice
+ join thread_track on slice.track_id = thread_track.id
+ join thread using(utid)
+ left join process using(upid)
+ group by thread_track.id
+ `);
+
+ const it = result.iter({
+ utid: NUM,
+ trackId: NUM,
+ trackName: STR_NULL,
+ isDefaultTrackForScope: NUM_NULL,
+ tid: NUM_NULL,
+ threadName: STR_NULL,
+ maxDepth: NUM,
+ upid: NUM_NULL,
+ });
+
+ for (; it.valid(); it.next()) {
+ const utid = it.utid;
+ const trackId = it.trackId;
+ const trackName = it.trackName;
+ const tid = it.tid;
+ const threadName = it.threadName;
+ const maxDepth = it.maxDepth;
+
+ const displayName = getTrackName({
+ name: trackName,
+ utid,
+ tid,
+ threadName,
+ kind: 'Slices',
+ });
+
+ ctx.addTrack({
+ uri: `perfetto.ChromeSlices#${trackId}`,
+ displayName,
+ trackIds: [trackId],
+ kind: SLICE_TRACK_KIND,
+ track: ({trackInstanceId}) => {
+ return new ChromeSliceTrack(
+ engine,
+ maxDepth,
+ trackInstanceId,
+ trackId,
+ );
+ },
+ });
+
+ // trackIds can only be registered by one track at a time.
+ // TODO(hjd): Move trackIds to only be on V2.
+ ctx.addTrack({
+ uri: `perfetto.ChromeSlices#${trackId}.v2`,
+ displayName,
+ kind: SLICE_TRACK_KIND,
+ track: ({trackInstanceId}) => {
+ const track = GenericSliceTrack.create({
+ engine: ctx.engine,
+ trackId: trackInstanceId,
+ });
+ track.config = {sqlTrackId: trackId};
+ return track;
+ },
+ });
+ }
}
}
diff --git a/ui/src/tracks/counter/index.ts b/ui/src/tracks/counter/index.ts
index 1fbc53f..4d22c31 100644
--- a/ui/src/tracks/counter/index.ts
+++ b/ui/src/tracks/counter/index.ts
@@ -318,7 +318,7 @@
return MARGIN_TOP + RECT_HEIGHT;
}
- getContextMenu(): m.Vnode<any> {
+ getTrackShellButtons(): m.Children {
const currentScale = this.store.state.scale;
const scales: {name: CounterScaleOptions, humanName: string}[] = [
{name: 'ZERO_BASED', humanName: 'Zero based'},
diff --git a/ui/src/tracks/cpu_profile/index.ts b/ui/src/tracks/cpu_profile/index.ts
index 616e9a2..0afbd57 100644
--- a/ui/src/tracks/cpu_profile/index.ts
+++ b/ui/src/tracks/cpu_profile/index.ts
@@ -17,16 +17,23 @@
import {duration, Time, time} from '../../base/time';
import {Actions} from '../../common/actions';
import {hslForSlice} from '../../common/colorizer';
-import {LONG, NUM} from '../../common/query_result';
-import {TrackData} from '../../common/track_data';
+import {LONG, NUM, NUM_NULL, STR_NULL} from '../../common/query_result';
import {
- TrackController,
-} from '../../controller/track_controller';
+ TrackAdapter,
+ TrackControllerAdapter,
+ TrackWithControllerAdapter,
+} from '../../common/track_adapter';
+import {TrackData} from '../../common/track_data';
import {globals} from '../../frontend/globals';
import {cachedHsluvToHex} from '../../frontend/hsluv_cache';
import {TimeScale} from '../../frontend/time_scale';
-import {NewTrackArgs, TrackBase} from '../../frontend/track';
-import {Plugin, PluginContext, PluginDescriptor} from '../../public';
+import {NewTrackArgs} from '../../frontend/track';
+import {
+ Plugin,
+ PluginContext,
+ PluginContextTrace,
+ PluginDescriptor,
+} from '../../public';
const BAR_HEIGHT = 3;
const MARGIN_TOP = 4.5;
@@ -44,8 +51,7 @@
utid: number;
}
-class CpuProfileTrackController extends TrackController<Config, Data> {
- static readonly kind = CPU_PROFILE_TRACK_KIND;
+class CpuProfileTrackController extends TrackControllerAdapter<Config, Data> {
async onBoundsChange(start: time, end: time, resolution: duration):
Promise<Data> {
const query = `select
@@ -85,8 +91,7 @@
return cachedHsluvToHex(hue, saturation, lightness);
}
-class CpuProfileTrack extends TrackBase<Config, Data> {
- static readonly kind = CPU_PROFILE_TRACK_KIND;
+class CpuProfileTrack extends TrackAdapter<Config, Data> {
static create(args: NewTrackArgs): CpuProfileTrack {
return new CpuProfileTrack(args);
}
@@ -245,9 +250,48 @@
}
class CpuProfile implements Plugin {
- onActivate(ctx: PluginContext): void {
- ctx.LEGACY_registerTrackController(CpuProfileTrackController);
- ctx.LEGACY_registerTrack(CpuProfileTrack);
+ onActivate(_ctx: PluginContext): void {}
+
+ async onTraceLoad(ctx: PluginContextTrace): Promise<void> {
+ const result = await ctx.engine.query(`
+ select
+ utid,
+ tid,
+ upid,
+ thread.name as threadName
+ from
+ thread
+ join (select utid
+ from cpu_profile_stack_sample group by utid
+ ) using(utid)
+ left join process using(upid)
+ where utid != 0
+ group by utid`);
+
+ const it = result.iter({
+ utid: NUM,
+ upid: NUM_NULL,
+ tid: NUM_NULL,
+ threadName: STR_NULL,
+ });
+ for (; it.valid(); it.next()) {
+ const utid = it.utid;
+ const threadName = it.threadName;
+ ctx.addTrack({
+ uri: `perfetto.CpuProfile#${utid}`,
+ displayName: `${threadName} (CPU Stack Samples)`,
+ kind: CPU_PROFILE_TRACK_KIND,
+ utid,
+ track: ({trackInstanceId}) => {
+ return new TrackWithControllerAdapter(
+ ctx.engine,
+ trackInstanceId,
+ {utid},
+ CpuProfileTrack,
+ CpuProfileTrackController);
+ },
+ });
+ }
}
}
diff --git a/ui/src/tracks/cpu_slices/index.ts b/ui/src/tracks/cpu_slices/index.ts
index c2de3f6..b251188 100644
--- a/ui/src/tracks/cpu_slices/index.ts
+++ b/ui/src/tracks/cpu_slices/index.ts
@@ -454,7 +454,6 @@
}
onMouseClick({x}: {x: number}) {
- console.log(this.mousePos);
const data = this.data();
if (data === undefined) return false;
const {visibleTimeScale} = globals.frontendLocalState;
diff --git a/ui/src/tracks/debug/counter_track.ts b/ui/src/tracks/debug/counter_track.ts
index 4879f27..adcc92d 100644
--- a/ui/src/tracks/debug/counter_track.ts
+++ b/ui/src/tracks/debug/counter_track.ts
@@ -16,10 +16,14 @@
import {Actions, DEBUG_COUNTER_TRACK_KIND} from '../../common/actions';
import {EngineProxy} from '../../common/engine';
+import {SCROLLING_TRACK_GROUP} from '../../common/state';
import {BaseCounterTrack} from '../../frontend/base_counter_track';
import {globals} from '../../frontend/globals';
import {NewTrackArgs} from '../../frontend/track';
-import {TrackButton, TrackButtonAttrs} from '../../frontend/track_panel';
+import {TrackButton} from '../../frontend/track_panel';
+import {PrimaryTrackSortKey} from '../../public';
+
+import {DEBUG_COUNTER_TRACK_URI} from '.';
// Names of the columns of the underlying view to be used as ts / dur / name.
export interface CounterColumns {
@@ -44,15 +48,19 @@
super(args);
}
- getTrackShellButtons(): Array<m.Vnode<TrackButtonAttrs>> {
- return [m(TrackButton, {
- action: () => {
- globals.dispatch(Actions.removeDebugTrack({trackId: this.trackId}));
- },
- i: 'close',
- tooltip: 'Close',
- showButton: true,
- })];
+ getTrackShellButtons(): m.Children {
+ return [
+ this.getCounterContextMenu(),
+ m(TrackButton, {
+ action: () => {
+ globals.dispatch(
+ Actions.removeTracks({trackInstanceIds: [this.trackId]}));
+ },
+ i: 'close',
+ tooltip: 'Close',
+ showButton: true,
+ }),
+ ];
}
async initSqlTable(tableName: string): Promise<void> {
@@ -95,10 +103,12 @@
from data
order by ts;`);
- globals.dispatch(Actions.addDebugCounterTrack({
- engineId: engine.engineId,
+ globals.dispatch(Actions.addTrack({
+ uri: DEBUG_COUNTER_TRACK_URI,
name: trackName.trim() || `Debug Track ${debugTrackId}`,
- config: {
+ trackSortKey: PrimaryTrackSortKey.DEBUG_TRACK,
+ trackGroup: SCROLLING_TRACK_GROUP,
+ initialState: {
sqlTableName,
columns,
},
diff --git a/ui/src/tracks/debug/index.ts b/ui/src/tracks/debug/index.ts
index e419c5d..1dcf0b1 100644
--- a/ui/src/tracks/debug/index.ts
+++ b/ui/src/tracks/debug/index.ts
@@ -12,15 +12,56 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-import {Plugin, PluginContext, PluginDescriptor} from '../../public';
+import {
+ Plugin,
+ PluginContext,
+ PluginContextTrace,
+ PluginDescriptor,
+} from '../../public';
+import {SLICE_TRACK_KIND} from '../chrome_slices';
-import {DebugCounterTrack} from './counter_track';
-import {DebugTrackV2} from './slice_track';
+import {CounterDebugTrackConfig, DebugCounterTrack} from './counter_track';
+import {DebugTrackV2, DebugTrackV2Config} from './slice_track';
+
+export const DEBUG_SLICE_TRACK_URI = 'perfetto.DebugSlices';
+export const DEBUG_COUNTER_TRACK_URI = 'perfetto.DebugCounter';
class DebugTrackPlugin implements Plugin {
- onActivate(ctx: PluginContext): void {
- ctx.LEGACY_registerTrack(DebugTrackV2);
- ctx.LEGACY_registerTrack(DebugCounterTrack);
+ onActivate(_ctx: PluginContext): void {}
+
+ async onTraceLoad(ctx: PluginContextTrace): Promise<void> {
+ // Add debug slice track
+ ctx.addTrack({
+ displayName: '',
+ kind: SLICE_TRACK_KIND,
+ uri: DEBUG_SLICE_TRACK_URI,
+ track: (trackCtx) => {
+ const store = trackCtx.mountStore((init) => init as DebugTrackV2Config);
+ const track = new DebugTrackV2({
+ engine: ctx.engine,
+ trackId: trackCtx.trackInstanceId,
+ });
+ track.config = store.state;
+ return track;
+ },
+ });
+
+ // Add debug counter track
+ ctx.addTrack({
+ displayName: '',
+ kind: SLICE_TRACK_KIND,
+ uri: DEBUG_COUNTER_TRACK_URI,
+ track: (trackCtx) => {
+ const store =
+ trackCtx.mountStore((init) => init as CounterDebugTrackConfig);
+ const track = new DebugCounterTrack({
+ engine: ctx.engine,
+ trackId: trackCtx.trackInstanceId,
+ });
+ track.config = store.state;
+ return track;
+ },
+ });
}
}
diff --git a/ui/src/tracks/debug/slice_track.ts b/ui/src/tracks/debug/slice_track.ts
index 3b18788..9640312 100644
--- a/ui/src/tracks/debug/slice_track.ts
+++ b/ui/src/tracks/debug/slice_track.ts
@@ -16,18 +16,21 @@
import {Actions, DEBUG_SLICE_TRACK_KIND} from '../../common/actions';
import {EngineProxy} from '../../common/engine';
+import {SCROLLING_TRACK_GROUP} from '../../common/state';
import {globals} from '../../frontend/globals';
import {
NamedSliceTrackTypes,
} from '../../frontend/named_slice_track';
import {NewTrackArgs} from '../../frontend/track';
-import {TrackButton, TrackButtonAttrs} from '../../frontend/track_panel';
+import {TrackButton} from '../../frontend/track_panel';
+import {PrimaryTrackSortKey} from '../../public';
import {
CustomSqlDetailsPanelConfig,
CustomSqlTableDefConfig,
CustomSqlTableSliceTrack,
} from '../custom_sql_table_slices';
+import {DEBUG_SLICE_TRACK_URI} from '.';
import {ARG_PREFIX} from './add_debug_track_menu';
import {DebugSliceDetailsTab} from './details_tab';
@@ -78,15 +81,16 @@
super.initSqlTable(tableName);
}
- getTrackShellButtons(): Array<m.Vnode<TrackButtonAttrs>> {
- return [m(TrackButton, {
+ getTrackShellButtons(): m.Children {
+ return m(TrackButton, {
action: () => {
- globals.dispatch(Actions.removeDebugTrack({trackId: this.trackId}));
+ globals.dispatch(
+ Actions.removeTracks({trackInstanceIds: [this.trackId]}));
},
i: 'close',
tooltip: 'Close',
showButton: true,
- })];
+ });
}
}
@@ -140,10 +144,12 @@
from prepared_data
order by ts;`);
- globals.dispatch(Actions.addDebugSliceTrack({
- engineId: engine.engineId,
+ globals.dispatch(Actions.addTrack({
+ uri: DEBUG_SLICE_TRACK_URI,
name: trackName.trim() || `Debug Track ${debugTrackId}`,
- config: {
+ trackSortKey: PrimaryTrackSortKey.DEBUG_TRACK,
+ trackGroup: SCROLLING_TRACK_GROUP,
+ initialState: {
sqlTableName,
columns: sliceColumns,
},
diff --git a/ui/src/tracks/expected_frames/index.ts b/ui/src/tracks/expected_frames/index.ts
index b30d31e..b25abed 100644
--- a/ui/src/tracks/expected_frames/index.ts
+++ b/ui/src/tracks/expected_frames/index.ts
@@ -12,56 +12,53 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-import {TrackData} from '../../common/track_data';
+import {BigintMath as BIMath} from '../../base/bigint_math';
+import {Duration, duration, time} from '../../base/time';
+import {
+ LONG,
+ LONG_NULL,
+ NUM,
+ NUM_NULL,
+ STR,
+ STR_NULL,
+} from '../../common/query_result';
+import {
+ SliceData,
+ SliceTrackBase,
+} from '../../frontend/slice_track_base';
+import {
+ EngineProxy,
+ Plugin,
+ PluginContext,
+ PluginContextTrace,
+ PluginDescriptor,
+} from '../../public';
+import {getTrackName} from '../../public/utils';
export const EXPECTED_FRAMES_SLICE_TRACK_KIND = 'ExpectedFramesSliceTrack';
-import {NewTrackArgs, TrackBase} from '../../frontend/track';
-import {ChromeSliceTrack} from '../chrome_slices';
+class SliceTrack extends SliceTrackBase {
+ private maxDur = Duration.ZERO;
-import {LONG, LONG_NULL, NUM, STR} from '../../common/query_result';
-import {duration, time} from '../../base/time';
-import {
- TrackController,
-} from '../../controller/track_controller';
-import {Plugin, PluginContext, PluginDescriptor} from '../../public';
-import {BigintMath as BIMath} from '../../base/bigint_math';
-
-export interface Config {
- maxDepth: number;
- trackIds: number[];
-}
-
-export interface Data extends TrackData {
- // Slices are stored in a columnar fashion. All fields have the same length.
- strings: string[];
- sliceIds: Float64Array;
- starts: BigInt64Array;
- ends: BigInt64Array;
- depths: Uint16Array;
- titles: Uint16Array; // Index in |strings|.
- colors?: Uint16Array; // Index in |strings|.
- isInstant: Uint16Array;
- isIncomplete: Uint16Array;
-}
-
-class ExpectedFramesSliceTrackController extends TrackController<Config, Data> {
- static readonly kind = EXPECTED_FRAMES_SLICE_TRACK_KIND;
- private maxDurNs: duration = 0n;
+ constructor(
+ private engine: EngineProxy, maxDepth: number, trackInstanceId: string,
+ private trackIds: number[], namespace?: string) {
+ super(maxDepth, trackInstanceId, '', namespace);
+ }
async onBoundsChange(start: time, end: time, resolution: duration):
- Promise<Data> {
- if (this.maxDurNs === 0n) {
- const maxDurResult = await this.query(`
+ Promise<SliceData> {
+ if (this.maxDur === Duration.ZERO) {
+ const maxDurResult = await this.engine.query(`
select max(iif(dur = -1, (SELECT end_ts FROM trace_bounds) - ts, dur))
as maxDur
from experimental_slice_layout
- where filter_track_ids = '${this.config.trackIds.join(',')}'
+ where filter_track_ids = '${this.trackIds.join(',')}'
`);
- this.maxDurNs = maxDurResult.firstRow({maxDur: LONG_NULL}).maxDur || 0n;
+ this.maxDur = maxDurResult.firstRow({maxDur: LONG_NULL}).maxDur || 0n;
}
- const queryRes = await this.query(`
+ const queryRes = await this.engine.query(`
SELECT
(ts + ${resolution / 2n}) / ${resolution} * ${resolution} as tsq,
ts,
@@ -73,15 +70,15 @@
dur = -1 as isIncomplete
from experimental_slice_layout
where
- filter_track_ids = '${this.config.trackIds.join(',')}' and
- ts >= ${start - this.maxDurNs} and
+ filter_track_ids = '${this.trackIds.join(',')}' and
+ ts >= ${start - this.maxDur} and
ts <= ${end}
group by tsq, layout_depth
order by tsq, layout_depth
`);
const numRows = queryRes.numRows();
- const slices: Data = {
+ const slices: SliceData = {
start,
end,
resolution,
@@ -139,18 +136,74 @@
}
}
-
-export class ExpectedFramesSliceTrack extends ChromeSliceTrack {
- static readonly kind = EXPECTED_FRAMES_SLICE_TRACK_KIND;
- static create(args: NewTrackArgs): TrackBase {
- return new ExpectedFramesSliceTrack(args);
- }
-}
-
class ExpectedFramesPlugin implements Plugin {
- onActivate(ctx: PluginContext): void {
- ctx.LEGACY_registerTrackController(ExpectedFramesSliceTrackController);
- ctx.LEGACY_registerTrack(ExpectedFramesSliceTrack);
+ onActivate(_ctx: PluginContext): void {}
+
+ async onTraceLoad(ctx: PluginContextTrace): Promise<void> {
+ const {engine} = ctx;
+ const result = await engine.query(`
+ with process_async_tracks as materialized (
+ select
+ process_track.upid as upid,
+ process_track.name as trackName,
+ process.name as processName,
+ process.pid as pid,
+ group_concat(process_track.id) as trackIds,
+ count(1) as trackCount
+ from process_track
+ left join process using(upid)
+ where process_track.name = "Expected Timeline"
+ group by
+ process_track.upid,
+ process_track.name
+ )
+ select
+ t.*,
+ max_layout_depth(t.trackCount, t.trackIds) as maxDepth
+ from process_async_tracks t;
+ `);
+
+ const it = result.iter({
+ upid: NUM,
+ trackName: STR_NULL,
+ trackIds: STR,
+ processName: STR_NULL,
+ pid: NUM_NULL,
+ maxDepth: NUM_NULL,
+ });
+
+ for (; it.valid(); it.next()) {
+ const upid = it.upid;
+ const trackName = it.trackName;
+ const rawTrackIds = it.trackIds;
+ const trackIds = rawTrackIds.split(',').map((v) => Number(v));
+ const processName = it.processName;
+ const pid = it.pid;
+ const maxDepth = it.maxDepth;
+
+ if (maxDepth === null) {
+ // If there are no slices in this track, skip it.
+ continue;
+ }
+
+ const displayName = getTrackName(
+ {name: trackName, upid, pid, processName, kind: 'ExpectedFrames'});
+
+ ctx.addTrack({
+ uri: `perfetto.ExpectedFrames#${upid}`,
+ displayName,
+ trackIds,
+ kind: EXPECTED_FRAMES_SLICE_TRACK_KIND,
+ track: ({trackInstanceId}) => {
+ return new SliceTrack(
+ engine,
+ maxDepth,
+ trackInstanceId,
+ trackIds,
+ );
+ },
+ });
+ }
}
}
diff --git a/ui/src/tracks/heap_profile/index.ts b/ui/src/tracks/heap_profile/index.ts
index 38b19e7..d7257dd 100644
--- a/ui/src/tracks/heap_profile/index.ts
+++ b/ui/src/tracks/heap_profile/index.ts
@@ -15,16 +15,25 @@
import {searchSegment} from '../../base/binary_search';
import {duration, Time, time} from '../../base/time';
import {Actions} from '../../common/actions';
-import {LONG, STR} from '../../common/query_result';
+import {LONG, NUM, STR} from '../../common/query_result';
import {ProfileType} from '../../common/state';
+import {
+ TrackAdapter,
+ TrackControllerAdapter,
+ TrackWithControllerAdapter,
+} from '../../common/track_adapter';
import {TrackData} from '../../common/track_data';
import {profileType} from '../../controller/flamegraph_controller';
-import {TrackController} from '../../controller/track_controller';
import {FLAMEGRAPH_HOVERED_COLOR} from '../../frontend/flamegraph';
import {globals} from '../../frontend/globals';
import {TimeScale} from '../../frontend/time_scale';
-import {NewTrackArgs, TrackBase} from '../../frontend/track';
-import {Plugin, PluginContext, PluginDescriptor} from '../../public';
+import {NewTrackArgs} from '../../frontend/track';
+import {
+ Plugin,
+ PluginContext,
+ PluginContextTrace,
+ PluginDescriptor,
+} from '../../public';
export const HEAP_PROFILE_TRACK_KIND = 'HeapProfileTrack';
@@ -37,8 +46,7 @@
upid: number;
}
-class HeapProfileTrackController extends TrackController<Config, Data> {
- static readonly kind = HEAP_PROFILE_TRACK_KIND;
+class HeapProfileTrackController extends TrackControllerAdapter<Config, Data> {
async onBoundsChange(start: time, end: time, resolution: duration):
Promise<Data> {
if (this.config.upid === undefined) {
@@ -88,8 +96,7 @@
const MARGIN_TOP = 4.5;
const RECT_HEIGHT = 30.5;
-class HeapProfileTrack extends TrackBase<Config, Data> {
- static readonly kind = HEAP_PROFILE_TRACK_KIND;
+class HeapProfileTrack extends TrackAdapter<Config, Data> {
static create(args: NewTrackArgs): HeapProfileTrack {
return new HeapProfileTrack(args);
}
@@ -216,9 +223,30 @@
}
class HeapProfilePlugin implements Plugin {
- onActivate(ctx: PluginContext): void {
- ctx.LEGACY_registerTrackController(HeapProfileTrackController);
- ctx.LEGACY_registerTrack(HeapProfileTrack);
+ onActivate(_ctx: PluginContext): void {}
+ async onTraceLoad(ctx: PluginContextTrace): Promise<void> {
+ const result = await ctx.engine.query(`
+ select distinct(upid) from heap_profile_allocation
+ union
+ select distinct(upid) from heap_graph_object
+ `);
+ for (const it = result.iter({upid: NUM}); it.valid(); it.next()) {
+ const upid = it.upid;
+ ctx.addTrack({
+ uri: `perfetto.HeapProfile#${upid}`,
+ displayName: 'Heap Profile',
+ kind: HEAP_PROFILE_TRACK_KIND,
+ upid,
+ track: ({trackInstanceId}) => {
+ return new TrackWithControllerAdapter(
+ ctx.engine,
+ trackInstanceId,
+ {upid},
+ HeapProfileTrack,
+ HeapProfileTrackController);
+ },
+ });
+ }
}
}
diff --git a/ui/src/tracks/null_track/index.ts b/ui/src/tracks/null_track/index.ts
index a007185..ffd84aa 100644
--- a/ui/src/tracks/null_track/index.ts
+++ b/ui/src/tracks/null_track/index.ts
@@ -13,15 +13,19 @@
// limitations under the License.
import {NewTrackArgs, TrackBase} from '../../frontend/track';
-import {Plugin, PluginContext, PluginDescriptor} from '../../public';
+import {
+ Plugin,
+ PluginContext,
+ PluginContextTrace,
+ PluginDescriptor,
+} from '../../public';
+export const NULL_TRACK_URI = 'perfetto.NullTrack';
export const NULL_TRACK_KIND = 'NullTrack';
export class NullTrack extends TrackBase {
- static readonly kind = NULL_TRACK_KIND;
constructor(args: NewTrackArgs) {
super(args);
- this.frontendOnly = true;
}
static create(args: NewTrackArgs): NullTrack {
@@ -36,8 +40,21 @@
}
class NullTrackPlugin implements Plugin {
- onActivate(ctx: PluginContext): void {
- ctx.LEGACY_registerTrack(NullTrack);
+ onActivate(_ctx: PluginContext): void {}
+
+ async onTraceLoad(ctx: PluginContextTrace<undefined>): Promise<void> {
+ // TODO(stevegolton): This is not the right way to handle blank tracks,
+ // instead we should probably just render some blank element at render time
+ // if no track uri is supplied.
+ ctx.addTrack({
+ uri: NULL_TRACK_URI,
+ displayName: 'Null Track',
+ kind: NULL_TRACK_KIND,
+ track: ({trackInstanceId}) => NullTrack.create({
+ engine: ctx.engine,
+ trackId: trackInstanceId,
+ }),
+ });
}
}
diff --git a/ui/src/tracks/perf_samples_profile/index.ts b/ui/src/tracks/perf_samples_profile/index.ts
index b6e624a..1d8b7b1 100644
--- a/ui/src/tracks/perf_samples_profile/index.ts
+++ b/ui/src/tracks/perf_samples_profile/index.ts
@@ -15,15 +15,24 @@
import {searchSegment} from '../../base/binary_search';
import {duration, Time, time} from '../../base/time';
import {Actions} from '../../common/actions';
-import {LONG} from '../../common/query_result';
+import {LONG, NUM} from '../../common/query_result';
import {ProfileType} from '../../common/state';
+import {
+ TrackAdapter,
+ TrackControllerAdapter,
+ TrackWithControllerAdapter,
+} from '../../common/track_adapter';
import {TrackData} from '../../common/track_data';
-import {TrackController} from '../../controller/track_controller';
import {FLAMEGRAPH_HOVERED_COLOR} from '../../frontend/flamegraph';
import {globals} from '../../frontend/globals';
import {TimeScale} from '../../frontend/time_scale';
-import {NewTrackArgs, TrackBase} from '../../frontend/track';
-import {Plugin, PluginContext, PluginDescriptor} from '../../public';
+import {NewTrackArgs} from '../../frontend/track';
+import {
+ Plugin,
+ PluginContext,
+ PluginContextTrace,
+ PluginDescriptor,
+} from '../../public';
export const PERF_SAMPLES_PROFILE_TRACK_KIND = 'PerfSamplesProfileTrack';
@@ -35,8 +44,8 @@
upid: number;
}
-class PerfSamplesProfileTrackController extends TrackController<Config, Data> {
- static readonly kind = PERF_SAMPLES_PROFILE_TRACK_KIND;
+class PerfSamplesProfileTrackController extends
+ TrackControllerAdapter<Config, Data> {
async onBoundsChange(start: time, end: time, resolution: duration):
Promise<Data> {
if (this.config.upid === undefined) {
@@ -77,8 +86,7 @@
const MARGIN_TOP = 4.5;
const RECT_HEIGHT = 30.5;
-class PerfSamplesProfileTrack extends TrackBase<Config, Data> {
- static readonly kind = PERF_SAMPLES_PROFILE_TRACK_KIND;
+class PerfSamplesProfileTrack extends TrackAdapter<Config, Data> {
static create(args: NewTrackArgs): PerfSamplesProfileTrack {
return new PerfSamplesProfileTrack(args);
}
@@ -209,9 +217,32 @@
}
class PerfSamplesProfilePlugin implements Plugin {
- onActivate(ctx: PluginContext): void {
- ctx.LEGACY_registerTrackController(PerfSamplesProfileTrackController);
- ctx.LEGACY_registerTrack(PerfSamplesProfileTrack);
+ onActivate(_ctx: PluginContext): void {}
+
+ async onTraceLoad(ctx: PluginContextTrace): Promise<void> {
+ const result = await ctx.engine.query(`
+ select distinct upid, pid
+ from perf_sample join thread using (utid) join process using (upid)
+ where callsite_id is not null
+ `);
+ for (const it = result.iter({upid: NUM, pid: NUM}); it.valid(); it.next()) {
+ const upid = it.upid;
+ const pid = it.pid;
+ ctx.addTrack({
+ uri: `perfetto.PerfSamplesProfile#${upid}`,
+ displayName: `Callstacks ${pid}`,
+ kind: PERF_SAMPLES_PROFILE_TRACK_KIND,
+ upid,
+ track: ({trackInstanceId}) => {
+ return new TrackWithControllerAdapter(
+ ctx.engine,
+ trackInstanceId,
+ {upid},
+ PerfSamplesProfileTrack,
+ PerfSamplesProfileTrackController);
+ },
+ });
+ }
}
}
diff --git a/ui/src/tracks/screenshots/index.ts b/ui/src/tracks/screenshots/index.ts
index cc85c16..3e1d8c2 100644
--- a/ui/src/tracks/screenshots/index.ts
+++ b/ui/src/tracks/screenshots/index.ts
@@ -12,8 +12,6 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-import {v4 as uuidv4} from 'uuid';
-
import {AddTrackArgs} from '../../common/actions';
import {Engine} from '../../common/engine';
import {
@@ -23,6 +21,7 @@
import {
Plugin,
PluginContext,
+ PluginContextTrace,
PluginDescriptor,
PrimaryTrackSortKey,
} from '../../public';
@@ -36,8 +35,6 @@
ScreenshotTab,
} from './screenshot_panel';
-export {Data} from '../chrome_slices';
-
class ScreenshotsTrack extends CustomSqlTableSliceTrack<NamedSliceTrackTypes> {
static readonly kind = 'dev.perfetto.ScreenshotsTrack';
static create(args: NewTrackArgs): TrackBase {
@@ -66,6 +63,7 @@
tracksToAdd: AddTrackArgs[],
};
+// TODO(stevegolton): Use suggestTrack().
export async function decideTracks(engine: Engine):
Promise<DecideTracksResult> {
const result: DecideTracksResult = {
@@ -75,20 +73,28 @@
await engine.query(`INCLUDE PERFETTO MODULE android.screenshots`);
result.tracksToAdd.push({
- id: uuidv4(),
- engineId: engine.id,
- kind: ScreenshotsTrack.kind,
- trackSortKey: PrimaryTrackSortKey.ASYNC_SLICE_TRACK,
+ uri: 'perfetto.Screenshots',
name: 'Screenshots',
- config: {},
- trackGroup: undefined,
+ trackSortKey: PrimaryTrackSortKey.ASYNC_SLICE_TRACK,
});
return result;
}
class ScreenshotsPlugin implements Plugin {
- onActivate(ctx: PluginContext): void {
- ctx.LEGACY_registerTrack(ScreenshotsTrack);
+ onActivate(_ctx: PluginContext): void {}
+
+ async onTraceLoad(ctx: PluginContextTrace<undefined>): Promise<void> {
+ ctx.addTrack({
+ uri: 'perfetto.Screenshots',
+ displayName: 'Screenshots',
+ kind: ScreenshotsTrack.kind,
+ track: ({trackInstanceId}) => {
+ return new ScreenshotsTrack({
+ engine: ctx.engine,
+ trackId: trackInstanceId,
+ });
+ },
+ });
}
}
diff --git a/ui/src/tracks/thread_state/index.ts b/ui/src/tracks/thread_state/index.ts
index 807f8f9..a2fad70 100644
--- a/ui/src/tracks/thread_state/index.ts
+++ b/ui/src/tracks/thread_state/index.ts
@@ -21,17 +21,31 @@
import {colorForState} from '../../common/colorizer';
import {LONG, NUM, NUM_NULL, STR_NULL} from '../../common/query_result';
import {translateState} from '../../common/thread_state';
+import {
+ TrackAdapter,
+ TrackControllerAdapter,
+ TrackWithControllerAdapter,
+} from '../../common/track_adapter';
import {TrackData} from '../../common/track_data';
-import {TrackController} from '../../controller/track_controller';
import {checkerboardExcept} from '../../frontend/checkerboard';
import {globals} from '../../frontend/globals';
-import {NewTrackArgs, TrackBase} from '../../frontend/track';
-import {Plugin, PluginContext, PluginDescriptor} from '../../public';
+import {NewTrackArgs} from '../../frontend/track';
+import {
+ Plugin,
+ PluginContext,
+ PluginContextTrace,
+ PluginDescriptor,
+} from '../../public';
+import {getTrackName} from '../../public/utils';
+import {
+ ThreadStateTrack as ThreadStateTrackV2,
+} from './thread_state_v2';
export const THREAD_STATE_TRACK_KIND = 'ThreadStateTrack';
+export const THREAD_STATE_TRACK_V2_KIND = 'ThreadStateTrackV2';
-export interface Data extends TrackData {
+interface Data extends TrackData {
strings: string[];
ids: Float64Array;
starts: BigInt64Array;
@@ -40,13 +54,11 @@
state: Uint16Array; // Index into |strings|.
}
-export interface Config {
+interface Config {
utid: number;
}
-class ThreadStateTrackController extends TrackController<Config, Data> {
- static readonly kind = THREAD_STATE_TRACK_KIND;
-
+class ThreadStateTrackController extends TrackControllerAdapter<Config, Data> {
private maxDurNs: duration = 0n;
async onSetup() {
@@ -162,8 +174,7 @@
const RECT_HEIGHT = 12;
const EXCESS_WIDTH = 10;
-class ThreadStateTrack extends TrackBase<Config, Data> {
- static readonly kind = THREAD_STATE_TRACK_KIND;
+class ThreadStateTrack extends TrackAdapter<Config, Data> {
static create(args: NewTrackArgs): ThreadStateTrack {
return new ThreadStateTrack(args);
}
@@ -277,16 +288,76 @@
const index = search(data.starts, time.toTime());
if (index === -1) return false;
const id = data.ids[index];
- globals.makeSelection(
- Actions.selectThreadState({id, trackId: this.trackState.id}));
+ globals.makeSelection(Actions.selectThreadState({id, trackId: this.id}));
return true;
}
}
+
class ThreadState implements Plugin {
- onActivate(ctx: PluginContext): void {
- ctx.LEGACY_registerTrack(ThreadStateTrack);
- ctx.LEGACY_registerTrackController(ThreadStateTrackController);
+ onActivate(_ctx: PluginContext): void {}
+
+ async onTraceLoad(ctx: PluginContextTrace<undefined>): Promise<void> {
+ const {engine} = ctx;
+ const result = await engine.query(`
+ select
+ utid,
+ upid,
+ tid,
+ pid,
+ thread.name as threadName
+ from
+ thread_state
+ left join thread using(utid)
+ left join process using(upid)
+ where utid != 0
+ group by utid`);
+
+ const it = result.iter({
+ utid: NUM,
+ upid: NUM_NULL,
+ tid: NUM_NULL,
+ pid: NUM_NULL,
+ threadName: STR_NULL,
+ });
+ for (; it.valid(); it.next()) {
+ const utid = it.utid;
+ const upid = it.upid;
+ const tid = it.tid;
+ const threadName = it.threadName;
+ const displayName =
+ getTrackName({utid, tid, threadName, kind: THREAD_STATE_TRACK_KIND});
+
+ ctx.addTrack({
+ uri: `perfetto.ThreadState#${upid}.${utid}`,
+ displayName,
+ kind: THREAD_STATE_TRACK_KIND,
+ utid: utid,
+ track: ({trackInstanceId}) => {
+ return new TrackWithControllerAdapter<Config, Data>(
+ ctx.engine,
+ trackInstanceId,
+ {utid},
+ ThreadStateTrack,
+ ThreadStateTrackController);
+ },
+ });
+
+ ctx.addTrack({
+ uri: `perfetto.ThreadState#${utid}.v2`,
+ displayName,
+ kind: THREAD_STATE_TRACK_V2_KIND,
+ utid,
+ track: ({trackInstanceId}) => {
+ const track = ThreadStateTrackV2.create({
+ engine: ctx.engine,
+ trackId: trackInstanceId,
+ });
+ track.config = {utid};
+ return track;
+ },
+ });
+ }
}
}
diff --git a/ui/src/tracks/thread_state_v2/index.ts b/ui/src/tracks/thread_state/thread_state_track_v2.ts
similarity index 86%
copy from ui/src/tracks/thread_state_v2/index.ts
copy to ui/src/tracks/thread_state/thread_state_track_v2.ts
index 9c465b6..5973960 100644
--- a/ui/src/tracks/thread_state_v2/index.ts
+++ b/ui/src/tracks/thread_state/thread_state_track_v2.ts
@@ -1,4 +1,4 @@
-// Copyright (C) 2023 The Android Open Source Project
+// Copyright (C) 2021 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.
@@ -29,15 +29,14 @@
SliceLayout,
} from '../../frontend/slice_layout';
import {NewTrackArgs} from '../../frontend/track';
-import {Plugin, PluginContext, PluginDescriptor} from '../../public';
export const THREAD_STATE_ROW = {
...BASE_SLICE_ROW,
state: STR,
ioWait: NUM_NULL,
};
-export type ThreadStateRow = typeof THREAD_STATE_ROW;
+export type ThreadStateRow = typeof THREAD_STATE_ROW;
export interface ThreadStateTrackConfig {
utid: number;
@@ -48,10 +47,7 @@
config: ThreadStateTrackConfig;
}
-export const THREAD_STATE_TRACK_V2_KIND = 'ThreadStateTrackV2';
-
export class ThreadStateTrack extends BaseSliceTrack<ThreadStateTrackTypes> {
- static readonly kind = THREAD_STATE_TRACK_V2_KIND;
static create(args: NewTrackArgs) {
return new ThreadStateTrack(args);
}
@@ -123,14 +119,3 @@
return selection.kind === 'THREAD_STATE';
}
}
-
-class ThreadStateTrackV2 implements Plugin {
- onActivate(ctx: PluginContext): void {
- ctx.LEGACY_registerTrack(ThreadStateTrack);
- }
-}
-
-export const plugin: PluginDescriptor = {
- pluginId: 'perfetto.ThreadStateTrackV2',
- plugin: ThreadStateTrackV2,
-};
diff --git a/ui/src/tracks/thread_state_v2/index.ts b/ui/src/tracks/thread_state/thread_state_v2.ts
similarity index 89%
rename from ui/src/tracks/thread_state_v2/index.ts
rename to ui/src/tracks/thread_state/thread_state_v2.ts
index 9c465b6..5f17530 100644
--- a/ui/src/tracks/thread_state_v2/index.ts
+++ b/ui/src/tracks/thread_state/thread_state_v2.ts
@@ -29,7 +29,6 @@
SliceLayout,
} from '../../frontend/slice_layout';
import {NewTrackArgs} from '../../frontend/track';
-import {Plugin, PluginContext, PluginDescriptor} from '../../public';
export const THREAD_STATE_ROW = {
...BASE_SLICE_ROW,
@@ -51,7 +50,6 @@
export const THREAD_STATE_TRACK_V2_KIND = 'ThreadStateTrackV2';
export class ThreadStateTrack extends BaseSliceTrack<ThreadStateTrackTypes> {
- static readonly kind = THREAD_STATE_TRACK_V2_KIND;
static create(args: NewTrackArgs) {
return new ThreadStateTrack(args);
}
@@ -123,14 +121,3 @@
return selection.kind === 'THREAD_STATE';
}
}
-
-class ThreadStateTrackV2 implements Plugin {
- onActivate(ctx: PluginContext): void {
- ctx.LEGACY_registerTrack(ThreadStateTrack);
- }
-}
-
-export const plugin: PluginDescriptor = {
- pluginId: 'perfetto.ThreadStateTrackV2',
- plugin: ThreadStateTrackV2,
-};
diff --git a/ui/src/tracks/visualised_args/index.ts b/ui/src/tracks/visualised_args/index.ts
index 3385bf9..19e6fb6 100644
--- a/ui/src/tracks/visualised_args/index.ts
+++ b/ui/src/tracks/visualised_args/index.ts
@@ -12,63 +12,128 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+// import {NewTrackArgs, Track} from '../../frontend/track';
+// import {TrackButton, TrackButtonAttrs} from '../../frontend/track_panel';
import m from 'mithril';
+import {v4 as uuidv4} from 'uuid';
import {Actions} from '../../common/actions';
import {globals} from '../../frontend/globals';
-import {NewTrackArgs, TrackBase} from '../../frontend/track';
-import {TrackButton, TrackButtonAttrs} from '../../frontend/track_panel';
-import {Plugin, PluginContext, PluginDescriptor} from '../../public';
+import {TrackButton} from '../../frontend/track_panel';
import {
- ChromeSliceTrack,
- ChromeSliceTrackController,
- Config as ChromeSliceConfig,
-} from '../chrome_slices';
-
-export {Data} from '../chrome_slices';
+ EngineProxy,
+ Plugin,
+ PluginContext,
+ PluginContextTrace,
+ PluginDescriptor,
+} from '../../public';
+import {ChromeSliceTrack} from '../chrome_slices';
export const VISUALISED_ARGS_SLICE_TRACK_KIND = 'VisualisedArgsTrack';
+export const VISUALISED_ARGS_SLICE_TRACK_URI = 'perfetto.VisualisedArgs';
-export interface Config extends ChromeSliceConfig {
+export interface VisualisedArgsState {
argName: string;
-}
-
-// The controller for arg visualisation is exactly the same as the controller
-// for Chrome slices. All customisation is done on the frontend.
-class VisualisedArgsTrackController extends ChromeSliceTrackController {
- static readonly kind = VISUALISED_ARGS_SLICE_TRACK_KIND;
+ maxDepth: number;
+ trackId: number;
}
export class VisualisedArgsTrack extends ChromeSliceTrack {
- static readonly kind = VISUALISED_ARGS_SLICE_TRACK_KIND;
- static create(args: NewTrackArgs): TrackBase {
- return new VisualisedArgsTrack(args);
+ private helperViewName: string;
+
+ constructor(
+ engine: EngineProxy, maxDepth: number, trackInstanceId: string,
+ trackId: number, private argName: string) {
+ const uuid = uuidv4();
+ const namespace = `__arg_visualisation_helper_${argName}_${uuid}`;
+ const escapedNamespace = namespace.replace(/[^a-zA-Z]/g, '_');
+ super(engine, maxDepth, trackInstanceId, trackId, escapedNamespace);
+ this.helperViewName = `${escapedNamespace}_slice`;
+ }
+
+ async onCreate(): Promise<void> {
+ // Create the helper view - just one which is relevant to this slice
+ await this.engine.query(`
+ create view ${this.helperViewName} as
+ with slice_with_arg as (
+ select
+ slice.id,
+ slice.track_id,
+ slice.ts,
+ slice.dur,
+ slice.thread_dur,
+ NULL as cat,
+ args.display_value as name
+ from slice
+ join args using (arg_set_id)
+ where args.key='${this.argName}'
+ )
+ select
+ *,
+ (select count()
+ from ancestor_slice(s1.id) s2
+ join slice_with_arg s3 on s2.id=s3.id
+ ) as depth
+ from slice_with_arg s1
+ order by id;
+ `);
+ }
+
+ async onDestroy(): Promise<void> {
+ this.engine.query(`drop view ${this.helperViewName}`);
}
getFont() {
return 'italic 11px Roboto';
}
- getTrackShellButtons(): Array<m.Vnode<TrackButtonAttrs>> {
- const config = this.config as Config;
- const buttons: Array<m.Vnode<TrackButtonAttrs>> = [];
- buttons.push(m(TrackButton, {
+ getTrackShellButtons(): m.Children {
+ return m(TrackButton, {
action: () => {
+ // This behavior differs to the original behavior a little.
+ // Originally, hitting the close button on a single track removed ALL
+ // tracks with this argName, whereas this one only closes the single
+ // track.
+ // This will be easily fixable once we transition to using dynamic
+ // tracks instead of this "initial state" approach to add these tracks.
globals.dispatch(
- Actions.removeVisualisedArg({argName: config.argName}));
+ Actions.removeTracks({trackInstanceIds: [this.trackInstanceId]}));
},
i: 'close',
tooltip: 'Close',
showButton: true,
- }));
- return buttons;
+ });
}
}
class VisualisedArgsPlugin implements Plugin {
- onActivate(ctx: PluginContext): void {
- ctx.LEGACY_registerTrackController(VisualisedArgsTrackController);
- ctx.LEGACY_registerTrack(VisualisedArgsTrack);
+ onActivate(_ctx: PluginContext): void {}
+ async onTraceLoad(ctx: PluginContextTrace<undefined>): Promise<void> {
+ ctx.addTrack({
+ uri: VISUALISED_ARGS_SLICE_TRACK_URI,
+ displayName: 'Visualised Args',
+ kind: VISUALISED_ARGS_SLICE_TRACK_KIND,
+ tags: {
+ metric: true, // TODO(stevegolton): Is this track really a metric?
+ },
+ track: (trackCtx) => {
+ // Mount the store and migrate initial state.
+ const store = trackCtx.mountStore((initialState) => {
+ // TODO(stevegolton): Check initialState properly. Note, this is no
+ // worse than the situation we had before with track config.
+ // When we migrate to "proper" dynamic tracks, the problem of
+ // migrating state will be pushed up to the plugin anyway.
+ return initialState as VisualisedArgsState;
+ });
+ return new VisualisedArgsTrack(
+ ctx.engine,
+ store.state.maxDepth,
+ trackCtx.trackInstanceId,
+ store.state.trackId,
+ store.state.argName,
+ );
+ },
+ });
}
}