1-- 2-- Copyright 2020 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/cpu_info.sql'); 18SELECT RUN_METRIC('android/process_metadata.sql'); 19 20DROP TABLE IF EXISTS android_thread_time_in_state_base; 21CREATE TABLE android_thread_time_in_state_base AS 22SELECT 23 base.*, 24 IFNULL(core_type_per_cpu.core_type, 'unknown') core_type 25FROM ( 26 SELECT 27 ts, 28 utid, 29 EXTRACT_ARG(counter.arg_set_id, 'time_in_state_cpu_id') AS 30 time_in_state_cpu, 31 EXTRACT_ARG(counter.arg_set_id, 'freq') AS freq, 32 CAST(value AS INT) AS runtime_ms_counter 33 FROM counter 34 JOIN thread_counter_track ON (counter.track_id = thread_counter_track.id) 35 WHERE thread_counter_track.name = 'time_in_state' 36) base 37LEFT JOIN core_type_per_cpu ON (cpu = time_in_state_cpu); 38 39DROP VIEW IF EXISTS android_thread_time_in_state_raw; 40CREATE VIEW android_thread_time_in_state_raw AS 41SELECT 42 utid, 43 time_in_state_cpu, 44 core_type, 45 freq, 46 MAX(runtime_ms_counter) - MIN(runtime_ms_counter) runtime_ms_diff 47FROM android_thread_time_in_state_base 48GROUP BY utid, time_in_state_cpu, core_type, freq; 49 50DROP TABLE IF EXISTS android_thread_time_in_state_counters; 51CREATE TABLE android_thread_time_in_state_counters AS 52SELECT 53 utid, 54 raw.time_in_state_cpu, 55 raw.core_type, 56 SUM(runtime_ms_diff) AS runtime_ms, 57 SUM(raw.freq * runtime_ms_diff / 1000000) AS mcycles, 58 SUM(power * runtime_ms_diff / 3600000) AS power_profile_mah 59FROM android_thread_time_in_state_raw AS raw 60 LEFT OUTER JOIN cpu_cluster_power AS power USING(core_type, freq) 61GROUP BY utid, raw.time_in_state_cpu, raw.core_type 62HAVING runtime_ms > 0; 63 64DROP VIEW IF EXISTS android_thread_time_in_state_thread_metrics; 65CREATE VIEW android_thread_time_in_state_thread_metrics AS 66SELECT 67 utid, 68 RepeatedField(AndroidThreadTimeInStateMetric_MetricsByCoreType( 69 'time_in_state_cpu', time_in_state_cpu, 70 'core_type', core_type, 71 'runtime_ms', runtime_ms, 72 'mcycles', CAST(mcycles AS INT), 73 'power_profile_mah', power_profile_mah 74 )) metrics 75FROM android_thread_time_in_state_counters 76GROUP BY utid; 77 78DROP VIEW IF EXISTS android_thread_time_in_state_threads; 79CREATE VIEW android_thread_time_in_state_threads AS 80SELECT 81 upid, 82 RepeatedField(AndroidThreadTimeInStateMetric_Thread( 83 'name', 84 thread.name, 85 'main_thread', 86 thread.is_main_thread, 87 'metrics_by_core_type', 88 android_thread_time_in_state_thread_metrics.metrics 89 )) threads 90FROM thread 91JOIN android_thread_time_in_state_thread_metrics USING (utid) 92GROUP BY upid; 93 94DROP VIEW IF EXISTS android_thread_time_in_state_process_metrics; 95CREATE VIEW android_thread_time_in_state_process_metrics AS 96WITH process_counters AS ( 97 SELECT 98 upid, 99 time_in_state_cpu, 100 core_type, 101 SUM(runtime_ms) AS runtime_ms, 102 SUM(mcycles) AS mcycles, 103 SUM(power_profile_mah) AS power_profile_mah 104 FROM android_thread_time_in_state_counters 105 JOIN thread USING (utid) 106 GROUP BY upid, time_in_state_cpu, core_type 107) 108SELECT 109 upid, 110 RepeatedField(AndroidThreadTimeInStateMetric_MetricsByCoreType( 111 'time_in_state_cpu', time_in_state_cpu, 112 'core_type', core_type, 113 'runtime_ms', runtime_ms, 114 'mcycles', CAST(mcycles AS INT), 115 'power_profile_mah', power_profile_mah 116 )) metrics 117FROM process_counters 118GROUP BY upid; 119 120DROP VIEW IF EXISTS android_thread_time_in_state_output; 121CREATE VIEW android_thread_time_in_state_output AS 122SELECT AndroidThreadTimeInStateMetric( 123 'processes', ( 124 SELECT 125 RepeatedField(AndroidThreadTimeInStateMetric_Process( 126 'metadata', metadata, 127 'metrics_by_core_type', 128 android_thread_time_in_state_process_metrics.metrics, 129 'threads', android_thread_time_in_state_threads.threads 130 )) 131 FROM process 132 JOIN process_metadata USING (upid) 133 JOIN android_thread_time_in_state_process_metrics USING (upid) 134 JOIN android_thread_time_in_state_threads USING (upid) 135 ) 136); 137 138-- Ensure we always get the previous clock tick for duration in 139-- android_thread_time_in_state_event_raw. 140DROP VIEW IF EXISTS android_thread_time_in_state_event_clock; 141CREATE VIEW android_thread_time_in_state_event_clock AS 142SELECT 143 ts, 144 LAG(ts) OVER (ORDER BY ts) AS lag_ts 145FROM ( 146 SELECT DISTINCT ts from android_thread_time_in_state_base 147); 148 149DROP VIEW IF EXISTS android_thread_time_in_state_event_raw; 150CREATE VIEW android_thread_time_in_state_event_raw AS 151SELECT 152 ts, 153 ts - lag_ts AS dur, 154 upid, 155 core_type, 156 utid, 157 -- We need globally unique track names so add the utid even when we 158 -- know the name. But when we don't, also use the tid because that's what 159 -- the rest of the UI does. 160 IFNULL(thread.name, 'Thread ' || thread.tid) || ' (' || thread.utid || ')' 161 AS thread_track_name, 162 freq, 163 runtime_ms_counter - LAG(runtime_ms_counter) 164 OVER (PARTITION BY core_type, utid, freq ORDER BY ts) AS runtime_ms 165FROM android_thread_time_in_state_base 166 -- Join to keep only utids which have non-zero runtime in the trace. 167 JOIN android_thread_time_in_state_counters USING (utid, core_type) 168 JOIN android_thread_time_in_state_event_clock USING(ts) 169 JOIN thread using (utid); 170 171DROP VIEW IF EXISTS android_thread_time_in_state_event_thread; 172CREATE VIEW android_thread_time_in_state_event_thread AS 173SELECT 174 'counter' AS track_type, 175 thread_track_name || ' (' || core_type || ' core)' as track_name, 176 ts, 177 dur, 178 upid, 179 sum(runtime_ms * freq) as ms_freq 180FROM android_thread_time_in_state_event_raw 181WHERE runtime_ms IS NOT NULL 182 AND dur != 0 183GROUP BY track_type, track_name, ts, dur, upid; 184 185DROP VIEW IF EXISTS android_thread_time_in_state_event_global; 186CREATE VIEW android_thread_time_in_state_event_global AS 187SELECT 188 'counter' AS track_type, 189 'Total ' || core_type || ' core cycles / sec' as track_name, 190 ts, 191 dur, 192 0 AS upid, 193 SUM(runtime_ms * freq) AS ms_freq 194FROM android_thread_time_in_state_event_raw 195WHERE runtime_ms IS NOT NULL 196GROUP BY ts, track_name; 197 198DROP TABLE IF EXISTS android_thread_time_in_state_event; 199CREATE TABLE android_thread_time_in_state_event AS 200SELECT track_type, track_name, ts, dur, upid, ms_freq * 1000000 / dur AS value 201FROM android_thread_time_in_state_event_thread 202UNION ALL 203SELECT track_type, track_name, ts, dur, upid, ms_freq * 1000000 / dur AS value 204FROM android_thread_time_in_state_event_global 205-- Biggest values at top of list in UI. 206ORDER BY value DESC; 207