diff options
Diffstat (limited to 'src/trace_processor/metrics/sql/experimental/frame_times.sql')
-rw-r--r-- | src/trace_processor/metrics/sql/experimental/frame_times.sql | 184 |
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) +); + |