1-- 2-- Copyright 2022 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 17-- Params: 18-- @target_duration_ms: find stack samples on tasks that are longer than 19-- this value 20 21-- @thread_name: thread name to look for stack samples on 22 23-- @task_name: a task name following chrome_tasks.sql naming convention to 24-- find stack samples on. 25 26INCLUDE PERFETTO MODULE chrome.tasks; 27 28CREATE OR REPLACE PERFETTO FUNCTION describe_symbol(symbol STRING, frame_name STRING) 29RETURNS STRING AS 30SELECT COALESCE($symbol, 31 CASE WHEN demangle($frame_name) IS NULL 32 THEN $frame_name 33 ELSE demangle($frame_name) 34 END); 35 36-- Get all Chrome tasks that match a specific name on a specific thread. 37-- The timestamps for those tasks are going to be used later on to gather 38-- information about stack traces that were collected during running them. 39DROP VIEW IF EXISTS chrome_targeted_task; 40CREATE PERFETTO VIEW chrome_targeted_task AS 41SELECT 42 chrome_tasks.full_name AS full_name, 43 chrome_tasks.dur AS dur, 44 chrome_tasks.ts AS ts, 45 chrome_tasks.id AS id, 46 utid AS utid 47FROM 48 chrome_tasks 49WHERE 50 chrome_tasks.dur >= {{target_duration_ms}} * 1e6 51 AND chrome_tasks.thread_name = {{thread_name}} 52 AND chrome_tasks.full_name = {{task_name}}; 53 54 55-- Get all frames attached to callsite ids, as frames can be 56-- reused between stack frames, callsite ids are unique per 57-- stack sample. 58DROP VIEW IF EXISTS chrome_non_symbolized_frames; 59CREATE PERFETTO VIEW chrome_non_symbolized_frames AS 60SELECT 61 frames.name AS frame_name, 62 callsite.id AS callsite_id, 63 * 64FROM 65 stack_profile_frame frames 66JOIN stack_profile_callsite callsite 67 ON callsite.frame_id = frames.id; 68 69-- Only lowest child frames are join-able with chrome_non_symbolized_frames 70-- which we need for the time at which the callstack was taken. 71DROP VIEW IF EXISTS chrome_symbolized_child_frames; 72CREATE PERFETTO VIEW chrome_symbolized_child_frames AS 73SELECT 74 thread.name AS thread_name, 75 sample.utid AS sample_utid, 76 * 77FROM 78 chrome_non_symbolized_frames frames 79JOIN cpu_profile_stack_sample sample USING(callsite_id) 80JOIN thread USING(utid) 81JOIN process USING(upid); 82 83-- Not all frames are symbolized, in cases where those frames 84-- are not symbolized, use the file name as it is usually descriptive 85-- of the function. 86DROP VIEW IF EXISTS chrome_thread_symbolized_child_frames; 87CREATE PERFETTO VIEW chrome_thread_symbolized_child_frames AS 88SELECT 89 describe_symbol(symbol.name, frame_name) AS description, 90 depth, 91 ts, 92 callsite_id, 93 sample_utid 94FROM chrome_symbolized_child_frames 95LEFT JOIN stack_profile_symbol symbol USING(symbol_set_id) 96WHERE thread_name = {{thread_name}} ORDER BY ts DESC; 97 98-- Since only leaf stack frames have a timestamp, let's export this 99-- timestamp to all it's ancestor frames to use it later on for 100-- filtering frames within specific windows 101DROP VIEW IF EXISTS chrome_non_symbolized_frames_timed; 102CREATE PERFETTO VIEW chrome_non_symbolized_frames_timed AS 103SELECT 104 chrome_non_symbolized_frames.frame_name, 105 chrome_non_symbolized_frames.depth, 106 chrome_thread_symbolized_child_frames.ts, 107 chrome_thread_symbolized_child_frames.sample_utid, 108 chrome_non_symbolized_frames.callsite_id, 109 symbol_set_id, 110 chrome_non_symbolized_frames.frame_id 111FROM chrome_thread_symbolized_child_frames 112JOIN experimental_ancestor_stack_profile_callsite( 113 chrome_thread_symbolized_child_frames.callsite_id) child 114JOIN chrome_non_symbolized_frames 115 ON chrome_non_symbolized_frames.callsite_id = child.id; 116 117DROP VIEW IF EXISTS chrome_frames_timed_and_symbolized; 118CREATE PERFETTO VIEW chrome_frames_timed_and_symbolized AS 119SELECT 120 describe_symbol(symbol.name, frame_name) AS description, 121 ts, 122 depth, 123 callsite_id, 124 sample_utid 125FROM chrome_non_symbolized_frames_timed 126LEFT JOIN stack_profile_symbol symbol 127 USING(symbol_set_id) 128ORDER BY DEPTH ASC; 129 130-- Union leaf stack frames with all stack frames after the timestamp 131-- is attached to get a view of all frames timestamped. 132DROP VIEW IF EXISTS all_frames; 133CREATE PERFETTO VIEW all_frames AS 134SELECT 135 * 136FROM 137 (SELECT 138 * FROM 139 chrome_frames_timed_and_symbolized 140 UNION 141 SELECT 142 description, 143 ts, 144 depth, 145 callsite_id, 146 sample_utid 147 FROM chrome_thread_symbolized_child_frames) 148ORDER BY depth ASC; 149 150-- Filter stack samples that happened only during the specified 151-- task on the specified thread. 152DROP VIEW IF EXISTS chrome_stack_samples_for_task; 153CREATE PERFETTO VIEW chrome_stack_samples_for_task AS 154SELECT 155 all_frames.* 156FROM 157 all_frames JOIN 158 chrome_targeted_task ON 159 all_frames.sample_utid = chrome_targeted_task.utid 160 AND all_frames.ts >= chrome_targeted_task.ts 161 AND all_frames.ts <= chrome_targeted_task.ts + chrome_targeted_task.dur; 162