• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1--
2-- Copyright 2023 The Android Open Source Project
3--
4-- Licensed under the Apache License, Version 2.0 (the "License");
5-- you may not use this file except in compliance with the License.
6-- You may obtain a copy of the License at
7--
8--     https://www.apache.org/licenses/LICENSE-2.0
9--
10-- Unless required by applicable law or agreed to in writing, software
11-- distributed under the License is distributed on an "AS IS" BASIS,
12-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13-- See the License for the specific language governing permissions and
14-- limitations under the License.
15
16-- Create the base table (`android_jank_cuj`) containing all completed CUJs
17-- found in the trace.
18-- This script will use the `android_jank_cuj_main_thread_cuj_boundary`,
19-- containing bounds of jank CUJs.
20SELECT RUN_METRIC('android/android_jank_cuj.sql');
21
22SELECT IMPORT('android.slices');
23SELECT IMPORT('android.binder');
24
25-- Jank "J<*>" and latency "L<*>" cujs are put together in android_cujs table.
26-- They are computed separately as latency ones are slightly different, don't
27-- currently have the same way to be cancelled, and are not anchored to vsyncs.
28DROP TABLE IF EXISTS android_cujs;
29CREATE TABLE android_cujs AS
30WITH latency_cujs AS (
31    SELECT
32        ROW_NUMBER() OVER (ORDER BY ts) AS cuj_id,
33        process.upid AS upid,
34        process.name AS process_name,
35        process_metadata.metadata AS process_metadata,
36        -- Extracts "CUJ_NAME" from "L<CUJ_NAME>"
37        SUBSTR(slice.name, 3, LENGTH(slice.name) - 3) AS cuj_name,
38        ts,
39        dur,
40        ts + dur AS ts_end,
41        'completed' AS state
42    FROM slice
43        JOIN process_track
44          ON slice.track_id = process_track.id
45        JOIN process USING (upid)
46        JOIN process_metadata USING (upid)
47    WHERE
48        slice.name GLOB 'L<*>'
49    AND dur > 0
50),
51all_cujs AS (
52    SELECT
53        cuj_id,
54        upid,
55        process_name,
56        process_metadata,
57        cuj_name,
58        tb.ts,
59        tb.dur,
60        tb.ts_end
61    FROM android_jank_cuj_main_thread_cuj_boundary tb
62        JOIN android_jank_cuj using (cuj_id)
63UNION
64    SELECT
65        cuj_id,
66        upid,
67        process_name,
68        process_metadata,
69        cuj_name,
70        ts,
71        dur,
72        ts_end
73    FROM latency_cujs
74)
75SELECT ROW_NUMBER() OVER (ORDER BY ts) AS cuj_id, *
76FROM all_cujs;
77
78
79DROP TABLE IF EXISTS relevant_binder_calls_with_names;
80CREATE TABLE relevant_binder_calls_with_names AS
81SELECT DISTINCT
82    tx.aidl_name AS name,
83    tx.client_ts AS ts,
84    s.track_id,
85    tx.client_dur AS dur,
86    s.id,
87    tx.client_process as process_name,
88    tx.client_utid as utid,
89    tx.client_upid as upid
90FROM android_sync_binder_metrics_by_txn AS tx
91         JOIN slice AS s ON s.id = tx.binder_txn_id
92        -- Keeps only slices in cuj processes.
93         JOIN android_cujs ON tx.client_upid = android_cujs.upid
94WHERE is_main_thread AND aidl_name IS NOT NULL;
95
96
97DROP TABLE IF EXISTS android_blocking_calls_cuj_calls;
98CREATE TABLE android_blocking_calls_cuj_calls AS
99WITH all_main_thread_relevant_slices AS (
100    SELECT DISTINCT
101        ANDROID_STANDARDIZE_SLICE_NAME(s.name) AS name,
102        s.ts,
103        s.track_id,
104        s.dur,
105        s.id,
106        process.name AS process_name,
107        thread.utid,
108        process.upid
109    FROM slice s
110        JOIN thread_track ON s.track_id = thread_track.id
111        JOIN thread USING (utid)
112        JOIN process USING (upid)
113        JOIN android_cujs USING (upid) -- Keeps only slices in cuj processes.
114    WHERE
115        thread.is_main_thread AND (
116               s.name = 'measure'
117            OR s.name = 'layout'
118            OR s.name = 'configChanged'
119            OR s.name = 'Contending for pthread mutex'
120            OR s.name GLOB 'monitor contention with*'
121            OR s.name GLOB 'SuspendThreadByThreadId*'
122            OR s.name GLOB 'LoadApkAssetsFd*'
123            OR s.name GLOB '*binder transaction*'
124            OR s.name GLOB 'inflate*'
125            OR s.name GLOB 'Lock contention on*'
126            OR s.name GLOB '*CancellableContinuationImpl*'
127            OR s.name GLOB 'relayoutWindow*'
128            OR s.name GLOB 'ImageDecoder#decode*'
129        )
130    UNION ALL
131    SELECT
132        name,
133        ts,
134        track_id,
135        dur,
136        id,
137        process_name,
138        utid,
139        upid
140    FROM relevant_binder_calls_with_names
141),
142-- Now we have:
143--  (1) a list of slices from the main thread of each process
144--  (2) a list of android cuj with beginning, end, and process
145-- It's needed to:
146--  (1) assign a cuj to each slice. If there are multiple cujs going on during a
147--      slice, there needs to be 2 entries for that slice, one for each cuj id.
148--  (2) each slice needs to be trimmed to be fully inside the cuj associated
149--      (as we don't care about what's outside cujs)
150main_thread_slices_scoped_to_cujs AS (
151SELECT
152    s.id,
153    s.id AS slice_id,
154    s.track_id,
155    s.name,
156    max(s.ts, cuj.ts) AS ts,
157    min(s.ts + s.dur, cuj.ts_end) as ts_end,
158    min(s.ts + s.dur, cuj.ts_end) - max(s.ts, cuj.ts) AS dur,
159    cuj.cuj_id,
160    cuj.cuj_name,
161    s.process_name,
162    s.upid,
163    s.utid
164FROM all_main_thread_relevant_slices s
165    JOIN  android_cujs cuj
166    -- only when there is an overlap
167    ON s.ts + s.dur > cuj.ts AND s.ts < cuj.ts_end
168        -- and are from the same process
169        AND s.upid = cuj.upid
170)
171SELECT
172    name,
173    COUNT(*) AS occurrences,
174    CAST(MAX(dur) / 1e6 AS INT) AS max_dur_ms,
175    CAST(MIN(dur) / 1e6 AS INT) AS min_dur_ms,
176    CAST(SUM(dur) / 1e6 AS INT) AS total_dur_ms,
177    upid,
178    cuj_id,
179    cuj_name,
180    process_name
181FROM
182    main_thread_slices_scoped_to_cujs
183GROUP BY name, upid, cuj_id, cuj_name, process_name
184ORDER BY cuj_id;
185
186
187DROP VIEW IF EXISTS android_blocking_calls_cuj_metric_output;
188CREATE VIEW android_blocking_calls_cuj_metric_output AS
189SELECT AndroidBlockingCallsCujMetric('cuj', (
190    SELECT RepeatedField(
191        AndroidBlockingCallsCujMetric_Cuj(
192            'id', cuj_id,
193            'name', cuj_name,
194            'process', process_metadata,
195            'ts',  cuj.ts,
196            'dur', cuj.dur,
197            'blocking_calls', (
198                SELECT RepeatedField(
199                     AndroidBlockingCallsCujMetric_BlockingCall(
200                        'name', b.name,
201                        'cnt', b.occurrences,
202                        'total_dur_ms', b.total_dur_ms,
203                        'max_dur_ms', b.max_dur_ms,
204                        'min_dur_ms', b.min_dur_ms
205                    )
206                )
207                FROM android_blocking_calls_cuj_calls b
208                WHERE b.cuj_id = cuj.cuj_id and b.upid = cuj.upid
209                ORDER BY total_dur_ms DESC
210            )
211        )
212    )
213    FROM android_cujs cuj
214    ORDER BY cuj.cuj_id ASC
215));
216