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 cpu.utilization.general; 17INCLUDE PERFETTO MODULE cpu.size; 18 19INCLUDE PERFETTO MODULE time.conversion; 20 21-- The purpose of this module is to provide high level aggregates of system 22-- utilization, akin to /proc/stat results. 23 24-- Returns a table of system utilization per given period. 25-- Utilization is calculated as sum of average utilization of each CPU in each 26-- period, which is defined as a multiply of |interval|. For this reason 27-- first and last period might have lower then real utilization. 28CREATE PERFETTO FUNCTION cpu_utilization_per_period( 29 -- Length of the period on which utilization should be averaged. 30 interval INT) 31RETURNS TABLE ( 32 -- Timestamp of start of a second. 33 ts INT, 34 -- Sum of average utilization over period. 35 -- Note: as the data is normalized, the values will be in the 36 -- [0, 1] range. 37 utilization DOUBLE, 38 -- Sum of average utilization over all CPUs over period. 39 -- Note: as the data is unnormalized, the values will be in the 40 -- [0, cpu_count] range. 41 unnormalized_utilization DOUBLE 42) AS 43SELECT * 44FROM _cpu_avg_utilization_per_period!( 45 $interval, 46 (SELECT * FROM sched WHERE utid != 0) 47); 48 49-- Table with system utilization per second. 50-- Utilization is calculated by sum of average utilization of each CPU every 51-- second. For this reason first and last second might have lower then real 52-- utilization. 53CREATE PERFETTO TABLE cpu_utilization_per_second( 54 -- Timestamp of start of a second. 55 ts INT, 56 -- Sum of average utilization over period. 57 -- Note: as the data is normalized, the values will be in the 58 -- [0, 1] range. 59 utilization DOUBLE, 60 -- Sum of average utilization over all CPUs over period. 61 -- Note: as the data is unnormalized, the values will be in the 62 -- [0, cpu_count] range. 63 unnormalized_utilization DOUBLE 64) AS 65SELECT 66 ts, 67 utilization, 68 unnormalized_utilization 69FROM cpu_utilization_per_period(time_from_s(1)); 70 71-- Aggregated CPU statistics for runtime of each thread on a CPU. 72CREATE PERFETTO TABLE _cpu_cycles_raw( 73 -- The id of CPU 74 cpu INT, 75 -- Unique thread id 76 utid INT, 77 -- Sum of CPU millicycles 78 millicycles INT, 79 -- Sum of CPU megacycles 80 megacycles INT, 81 -- Total runtime duration 82 runtime INT, 83 -- Minimum CPU frequency in kHz 84 min_freq INT, 85 -- Maximum CPU frequency in kHz 86 max_freq INT, 87 -- Average CPU frequency in kHz 88 avg_freq INT 89) AS 90SELECT 91 cpu, 92 utid, 93 -- We divide by 1e3 here as dur is in ns and freq in khz. In total 94 -- this means we need to divide the duration by 1e9 and multiply the 95 -- frequency by 1e3 then multiply again by 1e3 to get millicycles 96 -- i.e. divide by 1e3 in total. 97 -- We use millicycles as we want to preserve this level of precision 98 -- for future calculations. 99 cast_int!(SUM(dur * freq) / 1000) AS millicycles, 100 cast_int!(SUM(dur * freq) / 1000 / 1e9) AS megacycles, 101 SUM(dur) AS runtime, 102 MIN(freq) AS min_freq, 103 MAX(freq) AS max_freq, 104 -- We choose to work in micros space in both the numerator and 105 -- denominator as this gives us good enough precision without risking 106 -- overflows. 107 cast_int!(SUM((dur * freq) / 1000) / SUM(dur / 1000)) AS avg_freq 108FROM _cpu_freq_per_thread 109GROUP BY utid, cpu; 110 111-- Aggregated CPU statistics for each CPU. 112CREATE PERFETTO TABLE cpu_cycles_per_cpu( 113 -- The id of CPU 114 cpu INT, 115 -- CPU type 116 cpu_type STRING, 117 -- Sum of CPU millicycles 118 millicycles INT, 119 -- Sum of CPU megacycles 120 megacycles INT, 121 -- Total runtime of all threads running on CPU 122 runtime INT, 123 -- Minimum CPU frequency in kHz 124 min_freq INT, 125 -- Maximum CPU frequency in kHz 126 max_freq INT, 127 -- Average CPU frequency in kHz 128 avg_freq INT 129) AS 130SELECT 131 cpu, 132 cpu_guess_core_type(cpu) AS cpu_type, 133 cast_int!(SUM(dur * freq) / 1000) AS millicycles, 134 cast_int!(SUM(dur * freq) / 1000 / 1e9) AS megacycles, 135 SUM(dur) AS runtime, 136 MIN(freq) AS min_freq, 137 MAX(freq) AS max_freq, 138 cast_int!(SUM((dur * freq) / 1000) / SUM(dur / 1000)) AS avg_freq 139FROM _cpu_freq_per_thread 140GROUP BY cpu;