1-- 2-- Copyright 2024 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 16INCLUDE PERFETTO MODULE linux.cpu.frequency; 17 18-- Returns the timestamp of the start of the partition that contains the |ts|. 19CREATE PERFETTO FUNCTION _partition_start( 20 ts TIMESTAMP, 21 size LONG 22) 23RETURNS LONG AS 24-- Division of two ints would result in floor(ts/size). 25SELECT 26 ( 27 $ts / $size 28 ) * $size; 29 30-- Returns the number of partitions required to cover all of the trace 31-- timestamps. 32CREATE PERFETTO FUNCTION _partition_count( 33 size LONG 34) 35RETURNS LONG AS 36SELECT 37 ( 38 _partition_start(trace_end(), $size) - _partition_start(trace_start(), $size) 39 ) / $size + 1; 40 41-- Returns a table of partitions with first partition containing the 42-- TRACE_START() and last one containing TRACE_END(). 43CREATE PERFETTO FUNCTION _partitions( 44 size LONG 45) 46RETURNS TABLE ( 47 ts TIMESTAMP, 48 ts_end LONG 49) AS 50WITH 51 no_ends AS ( 52 SELECT 53 _partition_start(trace_start(), $size) + ( 54 id * $size 55 ) AS ts 56 -- We are using the sched table for source of ids. If the table is too small 57 -- for specified size, the results would be invalid none the less. 58 FROM sched 59 LIMIT _partition_count($size) 60 ) 61SELECT 62 ts, 63 ts + $size AS ts_end 64FROM no_ends; 65 66-- Partitions any |intervals| table with partitions defined in the |partitions| 67-- table. 68CREATE PERFETTO MACRO _interval_partitions( 69 -- Requires |ts| and |ts_end| columns. 70 partitions TableOrSubquery, 71 -- Requires |ts| and |ts_end| column. 72 intervals TableOrSubquery 73) 74RETURNS TableOrSubquery AS 75( 76 SELECT 77 p.ts AS partition_ts, 78 iif(i.ts_end < p.ts_end, i.ts_end, p.ts_end) AS ts_end, 79 iif(i.ts < p.ts, p.ts, i.ts) AS ts 80 FROM $intervals AS i 81 JOIN $partitions AS p 82 ON ( 83 p.ts <= i.ts AND i.ts < p.ts_end 84 ) 85); 86 87-- Returns a table of utilization per given period. 88-- Utilization is calculated as sum of average utilization of each CPU in each 89-- period, which is defined as a multiply of |interval|. For this reason 90-- first and last period might have lower then real utilization. 91CREATE PERFETTO MACRO _cpu_avg_utilization_per_period( 92 -- Length of the period on which utilization should be averaged. 93 interval Expr, 94 -- Either sched table or its filtered down version. 95 sched_table TableOrSubquery 96) 97-- The returned table has the schema (ts TIMESTAMP, utilization DOUBLE, 98-- unnormalized_utilization DOUBLE). 99RETURNS TableOrSubquery AS 100( 101 SELECT 102 partition_ts AS ts, 103 sum(ts_end - ts) / ( 104 cast_double!($interval) * ( 105 SELECT 106 max(cpu) + 1 107 FROM sched 108 ) 109 ) AS utilization, 110 sum(ts_end - ts) / cast_double!($interval) AS unnormalized_utilization 111 FROM _interval_partitions!(_partitions($interval), $sched_table) 112 GROUP BY 113 1 114); 115 116CREATE PERFETTO VIEW _cpu_freq_for_metrics AS 117SELECT 118 id, 119 ts, 120 dur, 121 cpu, 122 ucpu, 123 freq 124FROM cpu_frequency_counters 125WHERE 126 freq IS NOT NULL; 127 128CREATE PERFETTO VIEW _sched_without_id AS 129SELECT 130 ts, 131 dur, 132 utid, 133 ucpu 134FROM sched 135WHERE 136 NOT utid IN ( 137 SELECT 138 utid 139 FROM thread 140 WHERE 141 is_idle 142 ) AND dur != -1; 143 144CREATE VIRTUAL TABLE _cpu_freq_per_thread_span_join USING SPAN_LEFT_JOIN ( 145 _sched_without_id PARTITIONED ucpu, 146 _cpu_freq_for_metrics PARTITIONED ucpu); 147 148CREATE PERFETTO TABLE _cpu_freq_per_thread_no_id AS 149SELECT 150 * 151FROM _cpu_freq_per_thread_span_join; 152 153CREATE PERFETTO VIEW _cpu_freq_per_thread AS 154SELECT 155 _auto_id AS id, 156 ts, 157 dur, 158 ucpu, 159 cpu, 160 utid, 161 freq, 162 id AS counter_id 163FROM _cpu_freq_per_thread_no_id; 164