• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 graphs.hierarchy;
17
18INCLUDE PERFETTO MODULE graphs.scan;
19
20INCLUDE PERFETTO MODULE v8.jit;
21
22CREATE PERFETTO TABLE _callstack_spf_summary AS
23SELECT
24  id,
25  symbol_set_id,
26  (
27    SELECT
28      id
29    FROM stack_profile_symbol AS s
30    WHERE
31      s.symbol_set_id = f.symbol_set_id
32    ORDER BY
33      id
34    LIMIT 1
35  ) AS min_symbol_id,
36  (
37    SELECT
38      id
39    FROM stack_profile_symbol AS s
40    WHERE
41      s.symbol_set_id = f.symbol_set_id
42    ORDER BY
43      id DESC
44    LIMIT 1
45  ) AS max_symbol_id
46FROM stack_profile_frame AS f
47ORDER BY
48  id;
49
50CREATE PERFETTO TABLE _callstack_spc_raw_forest AS
51SELECT
52  c.id AS callsite_id,
53  s.id AS symbol_id,
54  iif(s.id IS f.max_symbol_id, c.parent_id, c.id) AS parent_callsite_id,
55  iif(s.id IS f.max_symbol_id, pf.min_symbol_id, s.id + 1) AS parent_symbol_id,
56  f.id AS frame_id,
57  jf.jit_code_id AS jit_code_id,
58  s.id IS f.min_symbol_id AS is_leaf
59FROM stack_profile_callsite AS c
60JOIN _callstack_spf_summary AS f
61  ON c.frame_id = f.id
62LEFT JOIN __intrinsic_jit_frame AS jf
63  ON jf.frame_id = f.id
64LEFT JOIN stack_profile_symbol AS s
65  USING (symbol_set_id)
66LEFT JOIN stack_profile_callsite AS p
67  ON c.parent_id = p.id
68LEFT JOIN _callstack_spf_summary AS pf
69  ON p.frame_id = pf.id
70ORDER BY
71  c.id;
72
73CREATE PERFETTO TABLE _callstack_spc_forest AS
74SELECT
75  c._auto_id AS id,
76  p._auto_id AS parent_id,
77  -- TODO(lalitm): consider demangling in a separate table as
78  -- demangling is suprisingly inefficient and is taking a
79  -- significant fraction of the runtime on big traces.
80  coalesce(
81    'JS: ' || iif(jsf.name = "", "(anonymous)", jsf.name) || ':' || jsf.line || ':' || jsf.col || ' [' || lower(jsc.tier) || ']',
82    'WASM: ' || wc.function_name || ' [' || lower(wc.tier) || ']',
83    'REGEXP: ' || rc.pattern,
84    'V8: ' || v8c.function_name,
85    'JIT: ' || jc.function_name,
86    demangle(coalesce(s.name, f.deobfuscated_name, f.name)),
87    coalesce(s.name, f.deobfuscated_name, f.name, '[Unknown]')
88  ) AS name,
89  f.mapping AS mapping_id,
90  s.source_file,
91  coalesce(jsf.line, s.line_number) AS line_number,
92  coalesce(jsf.col, 0) AS column_number,
93  c.callsite_id,
94  c.is_leaf AS is_leaf_function_in_callsite_frame
95FROM _callstack_spc_raw_forest AS c
96JOIN stack_profile_frame AS f
97  ON c.frame_id = f.id
98LEFT JOIN _v8_js_code AS jsc
99  USING (jit_code_id)
100LEFT JOIN v8_js_function AS jsf
101  USING (v8_js_function_id)
102LEFT JOIN _v8_internal_code AS v8c
103  USING (jit_code_id)
104LEFT JOIN _v8_wasm_code AS wc
105  USING (jit_code_id)
106LEFT JOIN _v8_regexp_code AS rc
107  USING (jit_code_id)
108LEFT JOIN __intrinsic_jit_code AS jc
109  ON c.jit_code_id = jc.id
110LEFT JOIN stack_profile_symbol AS s
111  ON c.symbol_id = s.id
112LEFT JOIN _callstack_spc_raw_forest AS p
113  ON p.callsite_id = c.parent_callsite_id AND p.symbol_id IS c.parent_symbol_id
114ORDER BY
115  c._auto_id;
116
117CREATE PERFETTO INDEX _callstack_spc_index ON _callstack_spc_forest(callsite_id);
118
119CREATE PERFETTO MACRO _callstacks_for_stack_profile_samples(
120    spc_samples TableOrSubquery
121)
122RETURNS TableOrSubquery AS
123(
124  SELECT
125    f.id,
126    f.parent_id,
127    f.callsite_id,
128    f.name,
129    m.name AS mapping_name,
130    f.source_file,
131    f.line_number,
132    f.is_leaf_function_in_callsite_frame
133  FROM _tree_reachable_ancestors_or_self!(
134    _callstack_spc_forest,
135    (
136      SELECT f.id
137      FROM $spc_samples s
138      JOIN _callstack_spc_forest f USING (callsite_id)
139      WHERE f.is_leaf_function_in_callsite_frame
140    )
141  ) AS g
142  JOIN _callstack_spc_forest AS f
143    USING (id)
144  JOIN stack_profile_mapping AS m
145    ON f.mapping_id = m.id
146);
147
148CREATE PERFETTO MACRO _callstacks_for_callsites(
149    samples TableOrSubquery
150)
151RETURNS TableOrSubquery AS
152(
153  WITH
154    metrics AS MATERIALIZED (
155      SELECT
156        callsite_id,
157        count() AS self_count
158      FROM $samples
159      GROUP BY
160        callsite_id
161    )
162  SELECT
163    c.id,
164    c.parent_id,
165    c.name,
166    c.mapping_name,
167    c.source_file,
168    c.line_number,
169    iif(c.is_leaf_function_in_callsite_frame, coalesce(m.self_count, 0), 0) AS self_count
170  FROM _callstacks_for_stack_profile_samples!(metrics) AS c
171  LEFT JOIN metrics AS m
172    USING (callsite_id)
173);
174
175CREATE PERFETTO MACRO _callstacks_self_to_cumulative(
176    callstacks TableOrSubquery
177)
178RETURNS TableOrSubquery AS
179(
180  SELECT
181    a.*
182  FROM _graph_aggregating_scan!(
183    (
184      SELECT id AS source_node_id, parent_id AS dest_node_id
185      FROM $callstacks
186      WHERE parent_id IS NOT NULL
187    ),
188    (
189      SELECT p.id, p.self_count AS cumulative_count
190      FROM $callstacks p
191      LEFT JOIN $callstacks c ON c.parent_id = p.id
192      WHERE c.id IS NULL
193    ),
194    (cumulative_count),
195    (
196      WITH agg AS (
197        SELECT t.id, SUM(t.cumulative_count) AS child_count
198        FROM $table t
199        GROUP BY t.id
200      )
201      SELECT
202        a.id,
203        a.child_count + r.self_count as cumulative_count
204      FROM agg a
205      JOIN $callstacks r USING (id)
206    )
207  ) AS a
208);
209