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 17SELECT RUN_METRIC('android/android_cpu.sql'); 18 19-- Attaching thread proto with media thread name 20DROP VIEW IF EXISTS core_type_proto_per_thread_name; 21CREATE PERFETTO VIEW core_type_proto_per_thread_name AS 22SELECT 23thread.name as thread_name, 24core_type_proto_per_thread.proto AS proto 25FROM core_type_proto_per_thread 26JOIN thread using(utid) 27WHERE thread.name = 'MediaCodec_loop' OR 28 thread.name = 'CodecLooper' 29GROUP BY thread.name; 30 31-- aggregate all cpu the codec threads 32DROP VIEW IF EXISTS codec_per_thread_cpu_use; 33CREATE PERFETTO VIEW codec_per_thread_cpu_use AS 34SELECT 35 upid, 36 process.name AS process_name, 37 thread.name AS thread_name, 38 CAST(SUM(sched.dur) as INT64) AS cpu_time_ns, 39 COUNT(DISTINCT utid) AS num_threads 40FROM sched 41JOIN thread USING(utid) 42JOIN process USING(upid) 43WHERE thread.name = 'MediaCodec_loop' OR 44 thread.name = 'CodecLooper' 45GROUP BY process.name, thread.name; 46 47-- All process that has codec thread 48DROP VIEW IF EXISTS android_codec_process; 49CREATE PERFETTO VIEW android_codec_process AS 50SELECT 51 upid, 52 process.name as process_name 53FROM sched 54JOIN thread using(utid) 55JOIN process using(upid) 56WHERE thread.name = 'MediaCodec_loop' OR 57 thread.name = 'CodecLooper' 58GROUP BY process_name; 59 60-- Total cpu for a process 61DROP VIEW IF EXISTS codec_total_per_process_cpu_use; 62CREATE PERFETTO VIEW codec_total_per_process_cpu_use AS 63SELECT 64 upid, 65 process_name, 66 CAST(SUM(sched.dur) as INT64) AS media_process_cpu_time_ns 67FROM sched 68JOIN thread using(utid) 69JOIN android_codec_process using(upid) 70GROUP BY process_name; 71 72-- Joining total process with media thread table 73DROP VIEW IF EXISTS codec_per_process_thread_cpu_use; 74CREATE PERFETTO VIEW codec_per_process_thread_cpu_use AS 75SELECT 76 * 77FROM codec_total_per_process_cpu_use 78JOIN codec_per_thread_cpu_use using(process_name); 79 80-- Traces are collected using specific traits in codec framework. These traits 81-- are mapped to actual names of slices and then combined with other tables to 82-- give out the total_cpu and cpu_running time. 83 84-- Utility function to trim codec trace string: extract the string demilited 85-- by the limiter. 86CREATE OR REPLACE PERFETTO FUNCTION extract_codec_string(slice_name STRING, limiter STRING) 87RETURNS STRING AS 88SELECT CASE 89 -- Delimit with the first occurrence 90 WHEN instr($slice_name, $limiter) > 0 91 THEN substr($slice_name, 1, instr($slice_name, $limiter) - 1) 92 ELSE $slice_name 93END; 94 95-- traits strings from codec framework 96DROP TABLE IF EXISTS trace_trait_table; 97CREATE TABLE trace_trait_table( 98 trace_trait varchar(100)); 99insert into trace_trait_table (trace_trait) values 100 ('MediaCodec'), 101 ('CCodec'), 102 ('C2PooledBlockPool'), 103 ('C2BufferQueueBlockPool'), 104 ('Codec2'), 105 ('ACodec'), 106 ('FrameDecoder'); 107 108-- Maps traits to slice strings. Any string with '@' is considered to indicate 109-- the same trace with different information.Hence those strings are delimited 110-- using '@' and considered as part of single trace. 111DROP VIEW IF EXISTS codec_slices; 112CREATE PERFETTO VIEW codec_slices AS 113SELECT 114 DISTINCT extract_codec_string(slice.name, '@') as codec_slice_string 115FROM slice 116JOIN trace_trait_table ON slice.name glob '*' || trace_trait || '*'; 117 118-- combine slice and thread info 119DROP VIEW IF EXISTS slice_with_utid; 120CREATE PERFETTO VIEW slice_with_utid AS 121SELECT 122 extract_codec_string(slice.name, '@') as codec_string, 123 ts, 124 dur, 125 upid, 126 slice.name as slice_name, 127 slice.id as slice_id, utid, 128 thread.name as thread_name 129FROM slice 130JOIN thread_track ON thread_track.id = slice.track_id 131JOIN thread USING (utid); 132 133-- Combine with thread_state info 134DROP TABLE IF EXISTS slice_thread_state_breakdown; 135CREATE VIRTUAL TABLE slice_thread_state_breakdown 136USING SPAN_LEFT_JOIN( 137 slice_with_utid PARTITIONED utid, 138 thread_state PARTITIONED utid 139); 140 141-- Get cpu_running_time for all the slices of interest 142DROP VIEW IF EXISTS slice_cpu_running; 143CREATE PERFETTO VIEW slice_cpu_running AS 144SELECT 145 codec_string, 146 sum(dur) as cpu_time, 147 sum(case when state = 'Running' then dur else 0 end) as cpu_run_ns, 148 thread_name, 149 process.name as process_name, 150 slice_id, 151 slice_name 152FROM slice_thread_state_breakdown 153LEFT JOIN process using(upid) 154where codec_string in (select codec_slice_string from codec_slices) 155GROUP BY codec_string, thread_name, process_name; 156 157 158-- Generate proto for the trace 159DROP VIEW IF EXISTS metrics_per_slice_type; 160CREATE PERFETTO VIEW metrics_per_slice_type AS 161SELECT 162 process_name, 163 codec_string, 164 AndroidCodecMetrics_Detail( 165 'thread_name', thread_name, 166 'total_cpu_ns', CAST(cpu_time as INT64), 167 'running_cpu_ns', CAST(cpu_run_ns as INT64) 168 ) AS proto 169FROM slice_cpu_running; 170 171-- Generating codec framework cpu metric 172DROP VIEW IF EXISTS codec_metrics_output; 173CREATE PERFETTO VIEW codec_metrics_output AS 174SELECT AndroidCodecMetrics( 175 'cpu_usage', ( 176 SELECT RepeatedField( 177 AndroidCodecMetrics_CpuUsage( 178 'process_name', process_name, 179 'thread_name', thread_name, 180 'thread_cpu_ns', CAST((cpu_time_ns) as INT64), 181 'num_threads', num_threads, 182 'core_data', core_type_proto_per_thread_name.proto 183 ) 184 ) FROM codec_per_process_thread_cpu_use 185 JOIN core_type_proto_per_thread_name using(thread_name) 186 ), 187 'codec_function', ( 188 SELECT RepeatedField ( 189 AndroidCodecMetrics_CodecFunction( 190 'codec_string', codec_string, 191 'process_name', process_name, 192 'detail', metrics_per_slice_type.proto 193 ) 194 ) FROM metrics_per_slice_type 195 ) 196); 197