• 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
17INCLUDE PERFETTO MODULE android.binder_breakdown;
18INCLUDE PERFETTO MODULE linux.cpu.utilization.thread;
19INCLUDE PERFETTO MODULE linux.cpu.utilization.slice;
20INCLUDE PERFETTO MODULE slices.with_context;
21INCLUDE PERFETTO MODULE slices.cpu_time;
22INCLUDE PERFETTO MODULE slices.flat_slices;
23
24SELECT RUN_METRIC('android/android_cpu.sql');
25SELECT RUN_METRIC('android/android_powrails.sql');
26
27-- Attaching thread proto with media thread name
28DROP VIEW IF EXISTS core_type_proto_per_thread_name;
29CREATE PERFETTO VIEW core_type_proto_per_thread_name AS
30SELECT
31utid,
32thread.name AS thread_name,
33core_type_proto_per_thread.proto AS proto
34FROM core_type_proto_per_thread
35JOIN thread using(utid)
36WHERE thread.name = 'MediaCodec_loop' OR
37      thread.name = 'CodecLooper'
38GROUP BY thread.name;
39
40-- All process that has codec thread
41DROP TABLE IF EXISTS android_codec_process;
42CREATE PERFETTO TABLE android_codec_process AS
43SELECT
44  utid,
45  upid,
46  process.name AS process_name
47FROM thread
48JOIN process using(upid)
49WHERE thread.name = 'MediaCodec_loop' OR
50      thread.name = 'CodecLooper'
51GROUP BY process_name, thread.name;
52
53-- Getting cpu cycles for the threads
54DROP VIEW IF EXISTS cpu_cycles_runtime;
55CREATE PERFETTO VIEW cpu_cycles_runtime AS
56SELECT
57  utid,
58  megacycles,
59  runtime,
60  proto,
61  process_name,
62  thread_name
63FROM android_codec_process
64JOIN cpu_cycles_per_thread using(utid)
65JOIN core_type_proto_per_thread_name using(utid);
66
67-- Traces are collected using specific traits in codec framework. These traits
68-- are mapped to actual names of slices and then combined with other tables to
69-- give out the total_cpu and cpu_running time.
70
71-- Utility function to trim codec trace string: extract the string demilited
72-- by the limiter.
73CREATE OR REPLACE PERFETTO FUNCTION extract_codec_string(slice_name STRING, limiter STRING)
74RETURNS STRING AS
75SELECT CASE
76  -- Delimit with the first occurrence
77  WHEN instr($slice_name, $limiter) > 0
78  THEN substr($slice_name, 1, instr($slice_name, $limiter) - 1)
79  ELSE $slice_name
80END;
81
82CREATE OR REPLACE PERFETTO FUNCTION extract_codec_string_after(slice_name STRING, limiter STRING)
83RETURNS STRING AS
84SELECT CASE
85  -- Delimit with the first occurrence
86  WHEN instr($slice_name, $limiter) > 0
87  THEN substr($slice_name, instr($slice_name, $limiter) + length($limiter), length($slice_name))
88  ELSE $slice_name
89END;
90
91-- Traits strings from codec framework
92DROP TABLE IF EXISTS trace_trait_table;
93CREATE TABLE trace_trait_table(trace_trait TEXT UNIQUE);
94INSERT INTO trace_trait_table VALUES
95  ('MediaCodec::*'),
96  ('CCodec::*'),
97  ('CCodecBufferChannel::*'),
98  ('C2PooledBlockPool::*'),
99  ('C2hal::*'),
100  ('ACodec::*'),
101  ('FrameDecoder::*'),
102  ('*android.hardware.media.c2.*'),
103  ('*android.hardware.drm.ICryptoPlugin*');
104
105-- Maps traits to slice strings. Any string with '@' is considered to indicate
106-- the same trace with different information.Hence those strings are delimited
107-- using '@' and considered as part of single slice.
108
109-- View to hold slice ids(sid) and the assigned slice ids for codec slices.
110DROP TABLE IF EXISTS codec_slices;
111CREATE PERFETTO TABLE codec_slices AS
112WITH
113  __codec_slices AS (
114    SELECT DISTINCT
115      IIF(instr(name, 'android.hardware.') > 0,
116        extract_codec_string_after(name, 'android.hardware.'),
117        extract_codec_string(name, '(')) AS codec_string,
118      slice.id AS sid,
119      slice.name AS sname
120    FROM slice
121    JOIN trace_trait_table ON slice.name GLOB trace_trait
122  ),
123  _codec_slices AS (
124    SELECT DISTINCT codec_string,
125      ROW_NUMBER() OVER() AS codec_slice_idx
126    FROM __codec_slices
127    GROUP BY codec_string
128  )
129SELECT
130  codec_slice_idx,
131  a.codec_string,
132  sid
133FROM __codec_slices a
134JOIN _codec_slices b USING(codec_string);
135
136-- Combine slice and and cpu dur and cycles info
137DROP TABLE IF EXISTS codec_slice_cpu_running;
138CREATE PERFETTO TABLE codec_slice_cpu_running AS
139SELECT
140  codec_string,
141  MIN(ts) AS min_ts,
142  MAX(ts + t.dur) AS max_ts,
143  SUM(t.dur) AS sum_dur_ns,
144  SUM(ct.cpu_time) AS cpu_run_ns,
145  AVG(t.dur) AS avg_dur_ns,
146  CAST(SUM(millicycles) AS INT64) AS cpu_cycles,
147  CAST(SUM(megacycles) AS INT64) AS cpu_mega_cycles,
148  IIF(INSTR(cc.thread_name, 'binder') > 0,
149    'binder', cc.thread_name) as thread_name_mod,
150  cc.process_name as process_name,
151  COUNT (*) as count
152FROM codec_slices
153JOIN thread_slice t ON(sid = t.id)
154JOIN thread_slice_cpu_cycles cc ON(sid = cc.id)
155JOIN thread_slice_cpu_time ct ON(sid = ct.id)
156GROUP BY codec_slice_idx, thread_name_mod, cc.process_name;
157
158-- Codec framework message latencies
159DROP TABLE IF EXISTS  fwk_looper_msg_latency;
160CREATE PERFETTO TABLE fwk_looper_msg_latency AS
161SELECT
162  slice.name AS normalized_name,
163  NULL AS process_name,
164  extract_codec_string(slice.name,'::') AS thread_name,
165  COUNT(*) AS count,
166  MAX(slice.dur/1e3) AS max_us,
167  MIN(slice.dur/1e3) AS min_us,
168  AVG(slice.dur)/1e3 AS avg_us,
169  SUM(slice.dur)/1e3 AS agg_us
170FROM slice
171WHERE slice.name GLOB '*::Looper_msg*'
172GROUP BY slice.name, thread_name, process_name;
173
174-- Qualifying individual slice latency
175DROP TABLE IF EXISTS latency_codec_slices;
176CREATE PERFETTO TABLE latency_codec_slices AS
177WITH
178  _filtered_raw_codec_flattened_slices AS(
179    SELECT
180      IIF(instr(name, 'android.hardware.') > 0,
181        extract_codec_string_after(name, 'android.hardware.'),
182        extract_codec_string(name, '(')) AS normalized_name,
183    slice_id,
184    root_id,
185    dur,
186    IIF(INSTR(thread_name, 'binder') > 0,
187    'binder', thread_name) as thread_name,
188    process_name,
189    depth
190    FROM _slice_flattened
191    JOIN trace_trait_table ON name GLOB trace_trait
192  ),
193  _filtered_agg_codec_flattened_slices AS(
194    SELECT
195      root_id,
196      normalized_name,
197      process_name,
198      thread_name,
199      SUM(dur)/1e3 AS _agg_us
200    FROM _filtered_raw_codec_flattened_slices
201    GROUP BY slice_id, root_id
202    ORDER BY depth)
203SELECT
204  normalized_name,
205  process_name,
206  thread_name,
207  COUNT(*) as count,
208  MAX(_agg_us) as max_us,
209  MIN(_agg_us) as min_us,
210  AVG(_agg_us) as avg_us,
211  SUM(_agg_us) as agg_us
212  FROM _filtered_agg_codec_flattened_slices
213  GROUP BY normalized_name, thread_name, process_name
214UNION ALL
215SELECT
216  normalized_name as codec_string,
217  process_name,
218  thread_name,
219  count,
220  max_us,
221  min_us,
222  avg_us,
223  agg_us
224  FROM fwk_looper_msg_latency;
225
226-- POWER consumed during codec use.
227DROP VIEW IF EXISTS codec_power_mw;
228CREATE PERFETTO VIEW codec_power_mw AS
229SELECT
230  AndroidCodecMetrics_Rail_Info (
231    'energy', tot_used_power,
232    'power_mw', tot_used_power / (powrail_end_ts - powrail_start_ts)
233  ) AS proto,
234  name
235FROM avg_used_powers;
236
237-- Generate proto for the trace
238DROP VIEW IF EXISTS metrics_per_slice_type;
239CREATE PERFETTO VIEW metrics_per_slice_type AS
240SELECT
241  COALESCE(codec_string, normalized_name) as codec_string,
242  COALESCE(rslice.process_name, lat.process_name) as process_name,
243  COALESCE(lat.thread_name, rslice.thread_name_mod) as thread_name,
244  max_us,
245  min_us,
246  avg_us,
247  agg_us,
248  lat.count AS count,
249  AndroidCodecMetrics_Detail(
250    'total_cpu_ns', CAST(sum_dur_ns AS INT64),
251    'running_cpu_ns', CAST(cpu_run_ns AS INT64),
252    'avg_running_cpu_ns', CAST((cpu_run_ns/rslice.count) AS INT64),
253    'avg_time_ns', CAST(avg_dur_ns AS INT64),
254    'total_cpu_cycles', CAST(cpu_cycles AS INT64),
255    'avg_cpu_cycles', CAST((cpu_cycles/rslice.count) AS INT64),
256    'count', rslice.count,
257    'self', AndroidCodecMetrics_Detail_Latency (
258      'max_us', CAST(max_us AS INT64),
259      'min_us', CAST(min_us AS INT64),
260      'avg_us', CAST(avg_us AS INT64),
261      'agg_us', CAST(agg_us AS INT64),
262      'count', lat.count
263    )
264  ) AS proto
265FROM latency_codec_slices lat
266FULL JOIN codec_slice_cpu_running  rslice
267ON codec_string = lat.normalized_name
268AND lat.thread_name = rslice.thread_name_mod
269AND lat.process_name = rslice.process_name;
270
271-- Generating codec framework cpu metric
272DROP VIEW IF EXISTS codec_metrics_output;
273CREATE PERFETTO VIEW codec_metrics_output AS
274SELECT AndroidCodecMetrics (
275  'cpu_usage', (
276    SELECT RepeatedField(
277      AndroidCodecMetrics_CpuUsage(
278        'process_name', process_name,
279        'thread', AndroidCodecMetrics_CpuUsage_ThreadInfo(
280          'name', thread_name,
281          'info', AndroidCodecMetrics_CpuUsage_ThreadInfo_Details(
282            'thread_cpu_ns', CAST((runtime) AS INT64),
283            'core_data', proto
284          )
285        )
286      )
287    ) FROM cpu_cycles_runtime
288  ),
289  'codec_function', (
290    SELECT RepeatedField (
291      AndroidCodecMetrics_CodecFunction(
292        'codec_string', codec_string,
293        'process', AndroidCodecMetrics_CodecFunction_Process(
294          'name', process_name,
295          'thread', AndroidCodecMetrics_CodecFunction_Process_Thread(
296            'name', thread_name,
297            'detail', metrics_per_slice_type.proto
298          )
299        )
300      )
301    ) FROM metrics_per_slice_type
302  ),
303  'energy', (
304    AndroidCodecMetrics_Energy(
305      'total_energy', (SELECT SUM(tot_used_power) FROM avg_used_powers),
306      'duration', (SELECT MAX(powrail_end_ts) - MIN(powrail_start_ts)  FROM avg_used_powers),
307      'power_mw', (SELECT SUM(tot_used_power) /  (MAX(powrail_end_ts) - MIN(powrail_start_ts)) FROM avg_used_powers),
308      'rail', (
309        SELECT RepeatedField (
310          AndroidCodecMetrics_Rail (
311            'name', name,
312            'info', codec_power_mw.proto
313          )
314        ) FROM codec_power_mw
315      )
316    )
317  )
318);
319