aboutsummaryrefslogtreecommitdiff
path: root/src/trace_processor/metrics/sql/experimental/frame_times.sql
diff options
context:
space:
mode:
Diffstat (limited to 'src/trace_processor/metrics/sql/experimental/frame_times.sql')
-rw-r--r--src/trace_processor/metrics/sql/experimental/frame_times.sql184
1 files changed, 184 insertions, 0 deletions
diff --git a/src/trace_processor/metrics/sql/experimental/frame_times.sql b/src/trace_processor/metrics/sql/experimental/frame_times.sql
new file mode 100644
index 000000000..488963f3c
--- /dev/null
+++ b/src/trace_processor/metrics/sql/experimental/frame_times.sql
@@ -0,0 +1,184 @@
+--
+-- 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.
+
+DROP VIEW IF EXISTS InteractionEvents;
+CREATE VIEW InteractionEvents AS
+SELECT
+ ts, dur, ts AS ts_ir, dur AS dur_ir
+FROM slice WHERE name GLOB 'Interaction.*';
+
+DROP VIEW IF EXISTS GestureLegacyEvents;
+CREATE VIEW GestureLegacyEvents AS
+SELECT
+ ts,
+ EXTRACT_ARG(arg_set_id, 'legacy_event.phase') AS phase
+FROM raw
+WHERE EXTRACT_ARG(arg_set_id, 'legacy_event.name') = 'SyntheticGestureController::running';
+
+-- Convert pairs of 'S' and 'F' events into slices with ts and dur.
+DROP VIEW IF EXISTS GestureEvents;
+CREATE VIEW GestureEvents AS
+SELECT
+ ts, dur, ts AS ts_ge, dur AS dur_ge
+FROM (
+ SELECT
+ ts,
+ phase,
+ LEAD(ts) OVER (ORDER BY ts) - ts as dur
+ FROM GestureLegacyEvents
+)
+WHERE phase = 'S';
+
+DROP TABLE IF EXISTS InteractionEventsJoinGestureEvents;
+CREATE VIRTUAL TABLE InteractionEventsJoinGestureEvents
+USING SPAN_LEFT_JOIN(InteractionEvents, GestureEvents);
+
+--------------------------------------------------------------------------------
+-- Interesting segments are:
+-- 1) If there's a gesture overlapping with interaction, then gesture's range.
+-- 2) Else, interaction's range.
+
+DROP VIEW IF EXISTS InterestingSegments;
+CREATE VIEW InterestingSegments AS
+SELECT -- 1) Gestures overlapping interactions.
+ ts_ge AS ts,
+ dur_ge AS dur
+FROM InteractionEventsJoinGestureEvents
+WHERE ts_ge IS NOT NULL
+GROUP BY ts_ge
+UNION ALL
+SELECT -- 2) Interactions without gestures.
+ ts_ir AS ts,
+ dur_ir AS dur
+FROM InteractionEventsJoinGestureEvents
+WHERE ts_ge IS NULL
+GROUP BY ts_ir
+HAVING COUNT(*) = 1;
+
+--------------------------------------------------------------------------------
+-- On ChromeOS, DRM events, if they exist, are the source of truth. Otherwise,
+-- look for display rendering stats.
+-- On Android, the TBMv2 version relied on Surface Flinger events that are
+-- currently unavailable in proto traces. So results may be different from
+-- the TBMv2 version on this platform.
+
+DROP TABLE IF EXISTS DisplayCompositorPresentationEvents;
+CREATE TABLE DisplayCompositorPresentationEvents AS
+SELECT ts, FALSE AS exp
+FROM slice
+WHERE name = 'DrmEventFlipComplete'
+GROUP BY ts;
+
+INSERT INTO DisplayCompositorPresentationEvents
+SELECT ts, FALSE AS exp
+FROM slice
+WHERE
+ name = 'vsync_before'
+ AND NOT EXISTS (SELECT * FROM DisplayCompositorPresentationEvents)
+GROUP BY ts;
+
+INSERT INTO DisplayCompositorPresentationEvents
+SELECT ts, FALSE AS exp
+FROM slice
+WHERE
+ name = 'BenchmarkInstrumentation::DisplayRenderingStats'
+ AND NOT EXISTS (SELECT * FROM DisplayCompositorPresentationEvents)
+GROUP BY ts;
+
+INSERT INTO DisplayCompositorPresentationEvents
+SELECT ts, TRUE AS exp
+FROM slice
+WHERE name = 'Display::FrameDisplayed'
+GROUP BY ts;
+
+DROP VIEW IF EXISTS FrameSegments;
+CREATE VIEW FrameSegments AS
+SELECT
+ ts,
+ LEAD(ts) OVER wnd - ts as dur,
+ ts as ts_fs,
+ LEAD(ts) OVER wnd - ts as dur_fs,
+ exp
+FROM DisplayCompositorPresentationEvents
+WINDOW wnd AS (PARTITION BY exp ORDER BY ts);
+
+DROP TABLE IF EXISTS FrameSegmentsJoinInterestingSegments;
+CREATE VIRTUAL TABLE FrameSegmentsJoinInterestingSegments USING
+SPAN_JOIN(FrameSegments, InterestingSegments);
+
+DROP VIEW IF EXISTS FrameTimes;
+CREATE VIEW FrameTimes AS
+SELECT dur / 1e6 AS dur_ms, exp
+FROM FrameSegmentsJoinInterestingSegments
+WHERE ts = ts_fs AND dur = dur_fs;
+
+--------------------------------------------------------------------------------
+-- Determine frame rate
+
+DROP VIEW IF EXISTS RefreshPeriodAndroid;
+CREATE VIEW RefreshPeriodAndroid AS
+-- Not implemented yet.
+SELECT NULL AS interval_ms
+;
+
+DROP VIEW IF EXISTS RefreshPeriodNonAndroid;
+CREATE VIEW RefreshPeriodNonAndroid AS
+SELECT EXTRACT_ARG(arg_set_id, 'debug.args.interval_us') / 1e3 AS interval_ms
+FROM slice
+JOIN thread_track ON (slice.track_id = thread_track.id)
+JOIN thread ON (thread_track.utid = thread.utid)
+WHERE thread.name = 'Compositor' AND slice.name = 'Scheduler::BeginFrame'
+LIMIT 1;
+
+DROP VIEW IF EXISTS RefreshPeriodDefault;
+CREATE VIEW RefreshPeriodDefault AS
+SELECT 1000.0 / 60 AS interval_ms;
+
+DROP TABLE IF EXISTS RefreshPeriod;
+CREATE TABLE RefreshPeriod AS
+SELECT COALESCE(
+ (SELECT interval_ms FROM RefreshPeriodAndroid),
+ (SELECT interval_ms FROM RefreshPeriodNonAndroid),
+ (SELECT interval_ms FROM RefreshPeriodDefault)
+) AS interval_ms;
+
+--------------------------------------------------------------------------------
+-- Compute average FPS
+
+DROP VIEW IF EXISTS ValidFrameTimes;
+CREATE VIEW ValidFrameTimes AS
+SELECT
+ dur_ms / (SELECT interval_ms FROM RefreshPeriod) AS length,
+ exp
+FROM FrameTimes
+WHERE dur_ms / (SELECT interval_ms FROM RefreshPeriod) >= 0.5;
+
+DROP VIEW IF EXISTS AvgSurfaceFps;
+CREATE VIEW AvgSurfaceFps AS
+SELECT
+ exp,
+ 1e3 * COUNT(*) / (SELECT SUM(dur_ms) FROM FrameTimes WHERE exp = valid.exp) AS fps
+FROM ValidFrameTimes valid
+GROUP BY exp;
+
+DROP VIEW IF EXISTS frame_times_output;
+CREATE VIEW frame_times_output AS
+SELECT FrameTimes(
+ 'frame_time', (SELECT RepeatedField(dur_ms) FROM FrameTimes WHERE NOT exp),
+ 'exp_frame_time', (SELECT RepeatedField(dur_ms) FROM FrameTimes WHERE exp),
+ 'avg_surface_fps', (SELECT fps FROM AvgSurfaceFps WHERE NOT exp),
+ 'exp_avg_surface_fps', (SELECT fps FROM AvgSurfaceFps WHERE exp)
+);
+