tp: backport startup metric for cold/warm starts to API 23
This CL backports the startup metric for non-hot starts until API 23.
We do this by relying entirely on launching slices to guide when
the startup happened.
Change-Id: I63ec94bf0fe870ec87e886f138231664c57e9442
Bug: 190219056
diff --git a/Android.bp b/Android.bp
index b0a5498..63ee186 100644
--- a/Android.bp
+++ b/Android.bp
@@ -8103,6 +8103,8 @@
"src/trace_processor/metrics/sql/android/span_view_stats.sql",
"src/trace_processor/metrics/sql/android/startup/hsc.sql",
"src/trace_processor/metrics/sql/android/startup/launches.sql",
+ "src/trace_processor/metrics/sql/android/startup/launches_maxsdk28.sql",
+ "src/trace_processor/metrics/sql/android/startup/launches_minsdk29.sql",
"src/trace_processor/metrics/sql/android/thread_counter_span_view.sql",
"src/trace_processor/metrics/sql/android/unsymbolized_frames.sql",
"src/trace_processor/metrics/sql/chrome/actual_power_by_category.sql",
diff --git a/BUILD b/BUILD
index 85ba196..5d0f51a 100644
--- a/BUILD
+++ b/BUILD
@@ -1088,6 +1088,8 @@
"src/trace_processor/metrics/sql/android/span_view_stats.sql",
"src/trace_processor/metrics/sql/android/startup/hsc.sql",
"src/trace_processor/metrics/sql/android/startup/launches.sql",
+ "src/trace_processor/metrics/sql/android/startup/launches_maxsdk28.sql",
+ "src/trace_processor/metrics/sql/android/startup/launches_minsdk29.sql",
"src/trace_processor/metrics/sql/android/thread_counter_span_view.sql",
"src/trace_processor/metrics/sql/android/unsymbolized_frames.sql",
"src/trace_processor/metrics/sql/chrome/actual_power_by_category.sql",
diff --git a/src/trace_processor/metrics/metrics.cc b/src/trace_processor/metrics/metrics.cc
index 6926cff..6c2536e 100644
--- a/src/trace_processor/metrics/metrics.cc
+++ b/src/trace_processor/metrics/metrics.cc
@@ -620,8 +620,9 @@
auto metric_it = std::find_if(
ctx->metrics->begin(), ctx->metrics->end(),
[path](const SqlMetricFile& metric) { return metric.path == path; });
- if (metric_it == ctx->metrics->end())
- return base::ErrStatus("RUN_METRIC: Unknown filename provided");
+ if (metric_it == ctx->metrics->end()) {
+ return base::ErrStatus("RUN_METRIC: Unknown filename provided %s", path);
+ }
const auto& sql = metric_it->sql;
std::unordered_map<std::string, std::string> substitutions;
diff --git a/src/trace_processor/metrics/sql/BUILD.gn b/src/trace_processor/metrics/sql/BUILD.gn
index 064630b..7ddbf2a 100644
--- a/src/trace_processor/metrics/sql/BUILD.gn
+++ b/src/trace_processor/metrics/sql/BUILD.gn
@@ -71,6 +71,8 @@
"android/gpu_counter_span_view.sql",
"android/thread_counter_span_view.sql",
"android/unsymbolized_frames.sql",
+ "android/startup/launches_maxsdk28.sql",
+ "android/startup/launches_minsdk29.sql",
"android/startup/launches.sql",
"android/startup/hsc.sql",
"chrome/actual_power_by_category.sql",
diff --git a/src/trace_processor/metrics/sql/android/startup/launches.sql b/src/trace_processor/metrics/sql/android/startup/launches.sql
index c3be64c..4993cd5 100644
--- a/src/trace_processor/metrics/sql/android/startup/launches.sql
+++ b/src/trace_processor/metrics/sql/android/startup/launches.sql
@@ -12,29 +12,6 @@
-- 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.
---
-
--- Marks the beginning of the trace and is equivalent to when the statsd launch
--- logging begins.
-DROP VIEW IF EXISTS activity_intent_received;
-CREATE VIEW activity_intent_received AS
-SELECT ts FROM slice
-WHERE name = 'MetricsLogger:launchObserverNotifyIntentStarted';
-
--- We partition the trace into spans based on posted activity intents.
--- We will refine these progressively in the next steps to only encompass
--- activity starts.
-DROP TABLE IF EXISTS activity_intent_recv_spans;
-CREATE TABLE activity_intent_recv_spans(id INT, ts BIG INT, dur BIG INT);
-
-INSERT INTO activity_intent_recv_spans
-SELECT
- ROW_NUMBER()
- OVER(ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) AS id,
- ts,
- LEAD(ts, 1, (SELECT end_ts FROM trace_bounds)) OVER(ORDER BY ts) - ts AS dur
-FROM activity_intent_received
-ORDER BY ts;
-- The start of the launching event corresponds to the end of the AM handling
-- the startActivity intent, whereas the end corresponds to the first frame drawn.
@@ -52,50 +29,28 @@
WHERE s.name GLOB 'launching: *'
AND (process.name IS NULL OR process.name = 'system_server');
--- Filter activity_intent_recv_spans, keeping only the ones that triggered
--- a launch.
-DROP VIEW IF EXISTS launch_partitions;
-CREATE VIEW launch_partitions AS
-SELECT * FROM activity_intent_recv_spans AS spans
-WHERE 1 = (
- SELECT COUNT(1)
- FROM launching_events
- WHERE launching_events.ts BETWEEN spans.ts AND spans.ts + spans.dur);
+SELECT CREATE_FUNCTION(
+ 'ANDROID_SDK_LEVEL()',
+ 'INT', "
+ SELECT int_value
+ FROM metadata
+ WHERE name = 'android_sdk_version'
+ ");
--- Successful activity launch. The end of the 'launching' event is not related
--- to whether it actually succeeded or not.
-DROP VIEW IF EXISTS activity_intent_launch_successful;
-CREATE VIEW activity_intent_launch_successful AS
-SELECT ts FROM slice
-WHERE name = 'MetricsLogger:launchObserverNotifyActivityLaunchFinished';
-
--- All activity launches in the trace, keyed by ID.
-DROP TABLE IF EXISTS launches;
-CREATE TABLE launches(
- ts BIG INT,
- ts_end BIG INT,
- dur BIG INT,
- id INT,
- package STRING);
-
--- Use the starting event package name. The finish event package name
--- is not reliable in the case of failed launches.
-INSERT INTO launches
-SELECT
- lpart.ts AS ts,
- launching_events.ts_end AS ts_end,
- launching_events.ts_end - lpart.ts AS dur,
- lpart.id AS id,
- package_name AS package
-FROM launch_partitions AS lpart
-JOIN launching_events ON
- (launching_events.ts BETWEEN lpart.ts AND lpart.ts + lpart.dur) AND
- (launching_events.ts_end BETWEEN lpart.ts AND lpart.ts + lpart.dur)
-WHERE (
- SELECT COUNT(1)
- FROM activity_intent_launch_successful AS successful
- WHERE successful.ts BETWEEN lpart.ts AND lpart.ts + lpart.dur
-) > 0;
+-- Note: on Q, we didn't have Android fingerprints but we *did*
+-- have ActivityMetricsLogger events so we will use this approach
+-- if we see any such events.
+SELECT CASE
+ WHEN (
+ ANDROID_SDK_LEVEL() >= 29
+ OR (
+ SELECT COUNT(1) FROM slice
+ WHERE name GLOB 'MetricsLogger:*'
+ ) > 0
+ )
+ THEN RUN_METRIC('android/startup/launches_minsdk29.sql')
+ ELSE RUN_METRIC('android/startup/launches_maxsdk28.sql')
+END;
-- Maps a launch to the corresponding set of processes that handled the
-- activity start. The vast majority of cases should be a single process.
@@ -107,9 +62,17 @@
INSERT INTO launch_processes
SELECT launches.id, process.upid
FROM launches
- LEFT JOIN package_list ON (launches.package = package_list.package_name)
- JOIN process ON (launches.package = process.name OR process.uid = package_list.uid)
- JOIN thread ON (process.upid = thread.upid AND process.pid = thread.tid)
+LEFT JOIN package_list ON (
+ launches.package = package_list.package_name
+)
+JOIN process ON (
+ launches.package = process.name OR
+ process.uid = package_list.uid
+)
+JOIN thread ON (
+ process.upid = thread.upid AND
+ process.pid = thread.tid
+)
WHERE (process.start_ts IS NULL OR process.start_ts < launches.ts_end)
AND (thread.end_ts IS NULL OR thread.end_ts > launches.ts_end)
ORDER BY process.start_ts DESC;
diff --git a/src/trace_processor/metrics/sql/android/startup/launches_maxsdk28.sql b/src/trace_processor/metrics/sql/android/startup/launches_maxsdk28.sql
new file mode 100644
index 0000000..8753da1
--- /dev/null
+++ b/src/trace_processor/metrics/sql/android/startup/launches_maxsdk28.sql
@@ -0,0 +1,36 @@
+--
+-- Copyright 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.
+-- 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.
+--
+
+-- All activity launches in the trace, keyed by ID.
+DROP TABLE IF EXISTS launches;
+CREATE TABLE launches(
+ id INTEGER PRIMARY KEY,
+ ts BIG INT,
+ ts_end BIG INT,
+ dur BIG INT,
+ package STRING
+);
+
+-- Cold/warm starts emitted launching slices on API level 28-.
+INSERT INTO launches(ts, ts_end, dur, package)
+SELECT
+ launching_events.ts AS ts,
+ launching_events.ts_end AS ts_end,
+ launching_events.ts_end - launching_events.ts AS dur,
+ package_name AS package
+FROM launching_events;
+
+-- TODO(lalitm): add handling of hot starts using frame timings.
diff --git a/src/trace_processor/metrics/sql/android/startup/launches_minsdk29.sql b/src/trace_processor/metrics/sql/android/startup/launches_minsdk29.sql
new file mode 100644
index 0000000..1f4c0f7
--- /dev/null
+++ b/src/trace_processor/metrics/sql/android/startup/launches_minsdk29.sql
@@ -0,0 +1,82 @@
+--
+-- Copyright 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.
+-- 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.
+--
+
+-- Marks the beginning of the trace and is equivalent to when the statsd launch
+-- logging begins.
+DROP VIEW IF EXISTS activity_intent_received;
+CREATE VIEW activity_intent_received AS
+SELECT ts FROM slice
+WHERE name = 'MetricsLogger:launchObserverNotifyIntentStarted';
+
+-- We partition the trace into spans based on posted activity intents.
+-- We will refine these progressively in the next steps to only encompass
+-- activity starts.
+DROP TABLE IF EXISTS activity_intent_recv_spans;
+CREATE TABLE activity_intent_recv_spans(id INT, ts BIG INT, dur BIG INT);
+
+INSERT INTO activity_intent_recv_spans
+SELECT
+ ROW_NUMBER()
+ OVER(ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) AS id,
+ ts,
+ LEAD(ts, 1, (SELECT end_ts FROM trace_bounds)) OVER(ORDER BY ts) - ts AS dur
+FROM activity_intent_received
+ORDER BY ts;
+
+-- Filter activity_intent_recv_spans, keeping only the ones that triggered
+-- a launch.
+DROP VIEW IF EXISTS launch_partitions;
+CREATE VIEW launch_partitions AS
+SELECT * FROM activity_intent_recv_spans AS spans
+WHERE 1 = (
+ SELECT COUNT(1)
+ FROM launching_events
+ WHERE launching_events.ts BETWEEN spans.ts AND spans.ts + spans.dur);
+
+-- Successful activity launch. The end of the 'launching' event is not related
+-- to whether it actually succeeded or not.
+DROP VIEW IF EXISTS activity_intent_launch_successful;
+CREATE VIEW activity_intent_launch_successful AS
+SELECT ts FROM slice
+WHERE name = 'MetricsLogger:launchObserverNotifyActivityLaunchFinished';
+
+-- All activity launches in the trace, keyed by ID.
+DROP TABLE IF EXISTS launches;
+CREATE TABLE launches(
+ ts BIG INT,
+ ts_end BIG INT,
+ dur BIG INT,
+ id INT,
+ package STRING);
+
+-- Use the starting event package name. The finish event package name
+-- is not reliable in the case of failed launches.
+INSERT INTO launches
+SELECT
+ lpart.ts AS ts,
+ launching_events.ts_end AS ts_end,
+ launching_events.ts_end - lpart.ts AS dur,
+ lpart.id AS id,
+ package_name AS package
+FROM launch_partitions AS lpart
+JOIN launching_events ON
+ (launching_events.ts BETWEEN lpart.ts AND lpart.ts + lpart.dur) AND
+ (launching_events.ts_end BETWEEN lpart.ts AND lpart.ts + lpart.dur)
+WHERE (
+ SELECT COUNT(1)
+ FROM activity_intent_launch_successful AS successful
+ WHERE successful.ts BETWEEN lpart.ts AND lpart.ts + lpart.dur
+) > 0;
diff --git a/tools/gen_amalgamated_sql_metrics.py b/tools/gen_amalgamated_sql_metrics.py
index eed5d8e..16f6aac 100755
--- a/tools/gen_amalgamated_sql_metrics.py
+++ b/tools/gen_amalgamated_sql_metrics.py
@@ -85,7 +85,7 @@
with open(file_name, 'r') as f:
relpath = os.path.relpath(file_name, root_path)
sql_outputs[relpath] = "".join(
- x for x in f.readlines() if not x.startswith('--'))
+ x.lstrip() for x in f.readlines() if not x.lstrip().startswith('--'))
with open(args.cpp_out, 'w+') as output:
output.write(REPLACEMENT_HEADER)