• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1-- Copyright 2023 The Chromium Authors
2-- Use of this source code is governed by a BSD-style license that can be
3-- found in the LICENSE file.
4
5-- Find causes for CPUs powering up.
6--
7-- The scripts below analyse traces with the following tracing options
8-- enabled:
9--
10--  - Linux kernel:
11---    "power/*", "sched/*", "task/*",
12--  - Chromium:
13--      "toplevel", "toplevel.flow".
14
15-- Noteworthy tables:
16--
17--   chrome_cpu_power_first_toplevel_slice_after_powerup :: The top-level
18--      slices that ran after a CPU power-up.
19
20-- The CPU power transitions in the trace.
21-- Power states are encoded as non-negative integers, with zero representing
22-- full-power operation and positive values representing increasingly deep
23-- sleep states.
24--
25-- On ARM systems, power state 1 represents the WFI (Wait For Interrupt) sleep
26-- state that the CPU enters while idle.
27CREATE PERFETTO VIEW chrome_cpu_power_slice(
28  -- The timestamp at the start of the slice.
29  ts INT,
30  -- The duration of the slice.
31  dur INT,
32  -- The CPU on which the transition occurred
33  cpu INT,
34  -- The power state that the CPU was in at time 'ts' for duration 'dur'.
35  power_state INT,
36  -- The power state that the CPU was previously in.
37  previous_power_state INT,
38  -- A unique ID for the CPU power-up.
39  powerup_id INT
40) AS
41  WITH cpu_power_states AS (
42    SELECT
43      c.id AS id,
44      cct.cpu AS cpu,
45      c.ts,
46      -- Encode the 'value' field as a power state.
47      CAST((CASE c.value WHEN 4294967295 THEN 0 ELSE c.value + 1 END)
48        AS INT) AS power_state
49    FROM counter AS c
50    JOIN cpu_counter_track AS cct
51      ON c.track_id = cct.id
52    WHERE cct.name = 'cpuidle'
53  )
54  SELECT *
55  FROM (
56    SELECT
57      ts,
58      LEAD(ts) OVER (PARTITION BY cpu ORDER BY ts ASC) - ts
59        AS dur,
60      cpu,
61      power_state,
62      LAG(power_state) OVER (PARTITION BY cpu ORDER BY ts ASC)
63        AS previous_power_state,
64      id AS powerup_id
65    FROM cpu_power_states
66  )
67  WHERE dur IS NOT NULL
68    AND previous_power_state IS NOT NULL
69    AND power_state = 0                      -- Track full-power states.
70    AND power_state != previous_power_state  -- Skip missing spans.
71    ORDER BY ts ASC;
72
73-- We do not want scheduler slices with utid = 0 (the 'swapper' kernel thread).
74CREATE PERFETTO VIEW internal_cpu_power_valid_sched_slice AS
75  SELECT *
76  FROM sched_slice
77  WHERE utid != 0;
78
79-- Join scheduler slices with the spans with CPU power slices.
80--
81-- There multiple scheduler slices could fall into one CPU power slice.
82--
83---  CPU Power:
84--   |----------------------------|....................|---------|
85--   A       <cpu active>         B     <cpu idling>   C         D
86
87--   Scheduler slices on that CPU:
88--     |-----T1-----| |....T2....|                      |---T3--|
89--     E            F G          H                      I       J
90--
91-- Here threads T1 and T2 executed in CPU power slice [A,B].  The
92-- time between F and G represents time between threads in the kernel.
93CREATE VIRTUAL TABLE internal_cpu_power_and_sched_slice
94USING
95  SPAN_JOIN(chrome_cpu_power_slice PARTITIONED cpu,
96            internal_cpu_power_valid_sched_slice PARTITIONED cpu);
97
98-- The Linux scheduler slices that executed immediately after a
99-- CPU power up.
100CREATE PERFETTO TABLE chrome_cpu_power_first_sched_slice_after_powerup(
101  -- The timestamp at the start of the slice.
102  ts INT,
103  -- The duration of the slice.
104  dur INT,
105  -- The cpu on which the slice executed.
106  cpu INT,
107  -- Id for the sched_slice table.
108  sched_id INT,
109  -- Unique id for the thread that ran within the slice.
110  utid INT,
111  -- The CPU's power state before this slice.
112  previous_power_state INT,
113  -- A unique ID for the CPU power-up.
114  powerup_id INT
115) AS
116SELECT
117  ts,
118  dur,
119  cpu,
120  id AS sched_id,
121  utid,
122  previous_power_state,
123  powerup_id
124FROM internal_cpu_power_and_sched_slice
125WHERE power_state = 0     -- Power-ups only.
126GROUP BY cpu, powerup_id
127HAVING ts = MIN(ts)       -- There will only be one MIN sched slice
128                          -- per CPU power up.
129ORDER BY ts ASC;
130
131-- A view joining thread tracks and top-level slices.
132--
133-- This view is intended to be intersected by time with the scheduler
134-- slices scheduled after a CPU power up.
135--
136--   utid      Thread unique id.
137--   slice_id  The slice_id for the top-level slice.
138--   ts        Starting timestamp for the slice.
139--   dur       The duration for the slice.
140CREATE PERFETTO VIEW internal_cpu_power_thread_and_toplevel_slice AS
141  SELECT
142    t.utid AS utid,
143    s.id AS slice_id,
144    s.ts,
145    s.dur
146  FROM slice AS s
147  JOIN thread_track AS t
148    ON s.track_id = t.id
149  WHERE s.depth = 0   -- Top-level slices only.
150  ORDER BY ts ASC;
151
152-- A table holding the slices that executed within the scheduler
153-- slice that ran on a CPU immediately after power-up.
154--
155-- @column  ts        Timestamp of the resulting slice
156-- @column dur        Duration of the slice.
157-- @column cpu        The CPU the sched slice ran on.
158-- @column utid       Unique thread id for the slice.
159-- @column sched_id   'id' field from the sched_slice table.
160-- @column type       From the sched_slice table, always 'sched_slice'.
161-- @column end_state  The ending state for the sched_slice
162-- @column priority   The kernel thread priority
163-- @column slice_id   Id of the top-level slice for this (sched) slice.
164CREATE VIRTUAL TABLE chrome_cpu_power_post_powerup_slice
165USING
166  SPAN_JOIN(chrome_cpu_power_first_sched_slice_after_powerup PARTITIONED utid,
167            internal_cpu_power_thread_and_toplevel_slice PARTITIONED utid);
168
169-- The first top-level slice that ran after a CPU power-up.
170CREATE PERFETTO VIEW chrome_cpu_power_first_toplevel_slice_after_powerup(
171  -- ID of the slice in the slice table.
172  slice_id INT,
173  -- The power state of the CPU prior to power-up.
174  previous_power_state INT
175) AS
176  SELECT slice_id, previous_power_state
177  FROM chrome_cpu_power_post_powerup_slice
178  GROUP BY cpu, powerup_id
179  HAVING ts = MIN(ts)
180  ORDER BY ts ASC;
181