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