aboutsummaryrefslogtreecommitdiff
path: root/src/trace_processor/metrics/sql/experimental/frame_times.sql
blob: 488963f3c33aafe0d92ac941e302820588eb6af2 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
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)
);