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.utilization.general; 17 18INCLUDE PERFETTO MODULE time.conversion; 19 20INCLUDE PERFETTO MODULE intervals.intersect; 21 22INCLUDE PERFETTO MODULE slices.with_context; 23 24-- CPU cycles per each slice. 25CREATE PERFETTO TABLE cpu_cycles_per_thread_slice ( 26 -- Id of a slice. 27 id JOINID(slice.id), 28 -- Name of the slice. 29 name STRING, 30 -- Id of the thread the slice is running on. 31 utid JOINID(thread.id), 32 -- Name of the thread. 33 thread_name STRING, 34 -- Id of the process the slice is running on. 35 upid JOINID(process.id), 36 -- Name of the process. 37 process_name STRING, 38 -- Sum of CPU millicycles. Null if frequency couldn't be fetched for any 39 -- period during the runtime of the slice. 40 millicycles LONG, 41 -- Sum of CPU megacycles. Null if frequency couldn't be fetched for any 42 -- period during the runtime of the slice. 43 megacycles LONG 44) AS 45WITH 46 intersected AS ( 47 SELECT 48 id_0 AS slice_id, 49 ii.utid, 50 sum(ii.dur) AS dur, 51 cast_int!(SUM(ii.dur * freq / 1000)) AS millicycles, 52 cast_int!(SUM(ii.dur * freq / 1000) / 1e9) AS megacycles 53 FROM _interval_intersect!( 54 ((SELECT * FROM thread_slice WHERE dur > 0 AND utid > 0), 55 _cpu_freq_per_thread), (utid)) AS ii 56 JOIN _cpu_freq_per_thread AS f 57 ON f.id = ii.id_1 58 WHERE 59 freq IS NOT NULL 60 GROUP BY 61 slice_id 62 ) 63SELECT 64 id, 65 ts.name, 66 ts.utid, 67 ts.thread_name, 68 ts.upid, 69 ts.process_name, 70 millicycles, 71 megacycles 72FROM thread_slice AS ts 73LEFT JOIN intersected 74 ON slice_id = ts.id AND ts.dur = intersected.dur; 75 76-- CPU cycles per each slice in interval. 77CREATE PERFETTO FUNCTION cpu_cycles_per_thread_slice_in_interval( 78 -- Start of the interval. 79 ts TIMESTAMP, 80 -- Duration of the interval. 81 dur DURATION 82) 83RETURNS TABLE ( 84 -- Thread slice. 85 id JOINID(slice.id), 86 -- Name of the slice. 87 name STRING, 88 -- Thread the slice is running on. 89 utid JOINID(thread.id), 90 -- Name of the thread. 91 thread_name STRING, 92 -- Process the slice is running on. 93 upid JOINID(process.id), 94 -- Name of the process. 95 process_name STRING, 96 -- Sum of CPU millicycles. Null if frequency couldn't be fetched for any 97 -- period during the runtime of the slice. 98 millicycles LONG, 99 -- Sum of CPU megacycles. Null if frequency couldn't be fetched for any 100 -- period during the runtime of the slice. 101 megacycles LONG 102) AS 103WITH 104 cut_thread_slice AS ( 105 SELECT 106 id, 107 ii.ts, 108 ii.dur, 109 thread_slice.* 110 FROM _interval_intersect_single!( 111 $ts, $dur, 112 (SELECT * FROM thread_slice WHERE dur > 0 AND utid > 0)) AS ii 113 JOIN thread_slice 114 USING (id) 115 ), 116 intersected AS ( 117 SELECT 118 id_0 AS slice_id, 119 ii.utid, 120 sum(ii.dur) AS dur, 121 cast_int!(SUM(ii.dur * freq / 1000)) AS millicycles, 122 cast_int!(SUM(ii.dur * freq / 1000) / 1e9) AS megacycles 123 FROM _interval_intersect!( 124 (cut_thread_slice, _cpu_freq_per_thread), (utid)) AS ii 125 JOIN _cpu_freq_per_thread AS f 126 ON f.id = ii.id_1 127 WHERE 128 freq IS NOT NULL 129 GROUP BY 130 slice_id 131 ) 132SELECT 133 id, 134 ts.name, 135 ts.utid, 136 ts.thread_name, 137 ts.upid, 138 ts.process_name, 139 millicycles, 140 megacycles 141FROM cut_thread_slice AS ts 142LEFT JOIN intersected 143 ON slice_id = ts.id AND ts.dur = intersected.dur; 144