xref: /aosp_15_r20/external/perfetto/docs/data-sources/cpu-scheduling.md (revision 6dbdd20afdafa5e3ca9b8809fa73465d530080dc)
1*6dbdd20aSAndroid Build Coastguard Worker# CPU Scheduling events
2*6dbdd20aSAndroid Build Coastguard Worker
3*6dbdd20aSAndroid Build Coastguard WorkerOn Android and Linux Perfetto can gather scheduler traces via the Linux Kernel
4*6dbdd20aSAndroid Build Coastguard Worker[ftrace](https://www.kernel.org/doc/Documentation/trace/ftrace.txt)
5*6dbdd20aSAndroid Build Coastguard Workerinfrastructure.
6*6dbdd20aSAndroid Build Coastguard Worker
7*6dbdd20aSAndroid Build Coastguard WorkerThis allows to get fine grained scheduling events such as:
8*6dbdd20aSAndroid Build Coastguard Worker
9*6dbdd20aSAndroid Build Coastguard Worker* Which threads were scheduled on which CPU core at any point in time, with
10*6dbdd20aSAndroid Build Coastguard Worker  nanosecond accuracy.
11*6dbdd20aSAndroid Build Coastguard Worker* The reason why a running thread got descheduled (e.g. pre-emption, blocked on
12*6dbdd20aSAndroid Build Coastguard Worker  a mutex, blocking syscall or any other wait queue).
13*6dbdd20aSAndroid Build Coastguard Worker* The point in time when a thread became eligible to be executed, even if it was
14*6dbdd20aSAndroid Build Coastguard Worker  not put immediately on any CPU run queue, together with the source thread that
15*6dbdd20aSAndroid Build Coastguard Worker  made it executable.
16*6dbdd20aSAndroid Build Coastguard Worker
17*6dbdd20aSAndroid Build Coastguard Worker## UI
18*6dbdd20aSAndroid Build Coastguard Worker
19*6dbdd20aSAndroid Build Coastguard WorkerThe UI represents individual scheduling events as slices:
20*6dbdd20aSAndroid Build Coastguard Worker
21*6dbdd20aSAndroid Build Coastguard Worker![](/docs/images/cpu-zoomed.png "Detailed view of CPU run queues")
22*6dbdd20aSAndroid Build Coastguard Worker
23*6dbdd20aSAndroid Build Coastguard WorkerClicking on a CPU slice shows the relevant information in the details panel:
24*6dbdd20aSAndroid Build Coastguard Worker
25*6dbdd20aSAndroid Build Coastguard Worker![](/docs/images/cpu-sched-details.png "CPU scheduling details")
26*6dbdd20aSAndroid Build Coastguard Worker
27*6dbdd20aSAndroid Build Coastguard WorkerScrolling down, when expanding individual processes, the scheduling events also
28*6dbdd20aSAndroid Build Coastguard Workercreate one track for each thread, which allows to follow the evolution of the
29*6dbdd20aSAndroid Build Coastguard Workerstate of individual threads:
30*6dbdd20aSAndroid Build Coastguard Worker
31*6dbdd20aSAndroid Build Coastguard Worker![](/docs/images/thread-states.png "States of individual threads")
32*6dbdd20aSAndroid Build Coastguard Worker
33*6dbdd20aSAndroid Build Coastguard Worker## SQL
34*6dbdd20aSAndroid Build Coastguard Worker
35*6dbdd20aSAndroid Build Coastguard WorkerAt the SQL level, the scheduling data is exposed in the
36*6dbdd20aSAndroid Build Coastguard Worker[`sched_slice`](/docs/analysis/sql-tables.autogen#sched_slice) table.
37*6dbdd20aSAndroid Build Coastguard Worker
38*6dbdd20aSAndroid Build Coastguard Worker```sql
39*6dbdd20aSAndroid Build Coastguard Workerselect ts, dur, cpu, end_state, priority, process.name, thread.name
40*6dbdd20aSAndroid Build Coastguard Workerfrom sched_slice left join thread using(utid) left join process using(upid)
41*6dbdd20aSAndroid Build Coastguard Worker```
42*6dbdd20aSAndroid Build Coastguard Worker
43*6dbdd20aSAndroid Build Coastguard Workerts | dur | cpu | end_state | priority | process.name, | thread.name
44*6dbdd20aSAndroid Build Coastguard Worker---|-----|-----|-----------|----------|---------------|------------
45*6dbdd20aSAndroid Build Coastguard Worker261187012170995 | 247188 | 2 | S | 130 | /system/bin/logd | logd.klogd
46*6dbdd20aSAndroid Build Coastguard Worker261187012418183 | 12812 | 2 | D | 120 | /system/bin/traced_probes | traced_probes0
47*6dbdd20aSAndroid Build Coastguard Worker261187012421099 | 220000 | 4 | D | 120 | kthreadd | kworker/u16:2
48*6dbdd20aSAndroid Build Coastguard Worker261187012430995 | 72396 | 2 | D | 120 | /system/bin/traced_probes | traced_probes1
49*6dbdd20aSAndroid Build Coastguard Worker261187012454537 | 13958 | 0 | D | 120 | /system/bin/traced_probes | traced_probes0
50*6dbdd20aSAndroid Build Coastguard Worker261187012460318 | 46354 | 3 | S | 120 | /system/bin/traced_probes | traced_probes2
51*6dbdd20aSAndroid Build Coastguard Worker261187012468495 | 10625 | 0 | R | 120 | [NULL] | swapper/0
52*6dbdd20aSAndroid Build Coastguard Worker261187012479120 | 6459 | 0 | D | 120 | /system/bin/traced_probes | traced_probes0
53*6dbdd20aSAndroid Build Coastguard Worker261187012485579 | 7760 | 0 | R | 120 | [NULL] | swapper/0
54*6dbdd20aSAndroid Build Coastguard Worker261187012493339 | 34896 | 0 | D | 120 | /system/bin/traced_probes | traced_probes0
55*6dbdd20aSAndroid Build Coastguard Worker
56*6dbdd20aSAndroid Build Coastguard Worker## TraceConfig
57*6dbdd20aSAndroid Build Coastguard Worker
58*6dbdd20aSAndroid Build Coastguard WorkerTo collect this data, include the following data sources:
59*6dbdd20aSAndroid Build Coastguard Worker
60*6dbdd20aSAndroid Build Coastguard Worker```protobuf
61*6dbdd20aSAndroid Build Coastguard Worker# Scheduling data from the kernel.
62*6dbdd20aSAndroid Build Coastguard Workerdata_sources: {
63*6dbdd20aSAndroid Build Coastguard Worker  config {
64*6dbdd20aSAndroid Build Coastguard Worker    name: "linux.ftrace"
65*6dbdd20aSAndroid Build Coastguard Worker    ftrace_config {
66*6dbdd20aSAndroid Build Coastguard Worker      compact_sched: {
67*6dbdd20aSAndroid Build Coastguard Worker        enabled: true
68*6dbdd20aSAndroid Build Coastguard Worker      }
69*6dbdd20aSAndroid Build Coastguard Worker      ftrace_events: "sched/sched_switch"
70*6dbdd20aSAndroid Build Coastguard Worker      # optional: precise thread lifetime tracking:
71*6dbdd20aSAndroid Build Coastguard Worker      ftrace_events: "sched/sched_process_exit"
72*6dbdd20aSAndroid Build Coastguard Worker      ftrace_events: "sched/sched_process_free"
73*6dbdd20aSAndroid Build Coastguard Worker      ftrace_events: "task/task_newtask"
74*6dbdd20aSAndroid Build Coastguard Worker      ftrace_events: "task/task_rename"
75*6dbdd20aSAndroid Build Coastguard Worker    }
76*6dbdd20aSAndroid Build Coastguard Worker  }
77*6dbdd20aSAndroid Build Coastguard Worker}
78*6dbdd20aSAndroid Build Coastguard Worker
79*6dbdd20aSAndroid Build Coastguard Worker# Adds full process names and thread<>process relationships:
80*6dbdd20aSAndroid Build Coastguard Workerdata_sources: {
81*6dbdd20aSAndroid Build Coastguard Worker  config {
82*6dbdd20aSAndroid Build Coastguard Worker    name: "linux.process_stats"
83*6dbdd20aSAndroid Build Coastguard Worker  }
84*6dbdd20aSAndroid Build Coastguard Worker}
85*6dbdd20aSAndroid Build Coastguard Worker```
86*6dbdd20aSAndroid Build Coastguard Worker
87*6dbdd20aSAndroid Build Coastguard Worker## Scheduling wakeups and latency analysis
88*6dbdd20aSAndroid Build Coastguard Worker
89*6dbdd20aSAndroid Build Coastguard WorkerBy further enabling the following in the TraceConfig, the ftrace data source
90*6dbdd20aSAndroid Build Coastguard Workerwill record also scheduling wake up events:
91*6dbdd20aSAndroid Build Coastguard Worker
92*6dbdd20aSAndroid Build Coastguard Worker```protobuf
93*6dbdd20aSAndroid Build Coastguard Worker  ftrace_events: "sched/sched_wakeup_new"
94*6dbdd20aSAndroid Build Coastguard Worker  ftrace_events: "sched/sched_waking"
95*6dbdd20aSAndroid Build Coastguard Worker```
96*6dbdd20aSAndroid Build Coastguard Worker
97*6dbdd20aSAndroid Build Coastguard WorkerWhile `sched_switch` events are emitted only when a thread is in the
98*6dbdd20aSAndroid Build Coastguard Worker`R(unnable)` state AND is running on a CPU run queue, `sched_waking` events are
99*6dbdd20aSAndroid Build Coastguard Workeremitted when any event causes a thread state to change.
100*6dbdd20aSAndroid Build Coastguard Worker
101*6dbdd20aSAndroid Build Coastguard WorkerConsider the following example:
102*6dbdd20aSAndroid Build Coastguard Worker
103*6dbdd20aSAndroid Build Coastguard Worker```
104*6dbdd20aSAndroid Build Coastguard WorkerThread A
105*6dbdd20aSAndroid Build Coastguard Workercondition_variable.wait()
106*6dbdd20aSAndroid Build Coastguard Worker                                     Thread B
107*6dbdd20aSAndroid Build Coastguard Worker                                     condition_variable.notify()
108*6dbdd20aSAndroid Build Coastguard Worker```
109*6dbdd20aSAndroid Build Coastguard Worker
110*6dbdd20aSAndroid Build Coastguard WorkerWhen Thread A suspends on the wait() it will enter the state `S(sleeping)` and
111*6dbdd20aSAndroid Build Coastguard Workerget removed from the CPU run queue. When Thread B notifies the variable, the
112*6dbdd20aSAndroid Build Coastguard Workerkernel will transition Thread A into the `R(unnable)` state. Thread A at that
113*6dbdd20aSAndroid Build Coastguard Workerpoint is eligible to be put back on a run queue. However this might not happen
114*6dbdd20aSAndroid Build Coastguard Workerfor some time because, for instance:
115*6dbdd20aSAndroid Build Coastguard Worker
116*6dbdd20aSAndroid Build Coastguard Worker* All CPUs might be busy running some other thread, and Thread A needs to wait
117*6dbdd20aSAndroid Build Coastguard Worker  to get a run queue slot assigned (or the other threads have higher priority).
118*6dbdd20aSAndroid Build Coastguard Worker* Some other CPUs other than the current one, but the scheduler load balancer
119*6dbdd20aSAndroid Build Coastguard Worker  might take some time to move the thread on another CPU.
120*6dbdd20aSAndroid Build Coastguard Worker
121*6dbdd20aSAndroid Build Coastguard WorkerUnless using real-time thread priorities, most Linux Kernel scheduler
122*6dbdd20aSAndroid Build Coastguard Workerconfigurations are not strictly work-conserving. For instance the scheduler
123*6dbdd20aSAndroid Build Coastguard Workermight prefer to wait some time in the hope that the thread running on the
124*6dbdd20aSAndroid Build Coastguard Workercurrent CPU goes to idle, avoiding a cross-cpu migration which might be more
125*6dbdd20aSAndroid Build Coastguard Workercostly both in terms of overhead and power.
126*6dbdd20aSAndroid Build Coastguard Worker
127*6dbdd20aSAndroid Build Coastguard WorkerNOTE: `sched_waking` and `sched_wakeup` provide nearly the same information. The
128*6dbdd20aSAndroid Build Coastguard Worker      difference lies in wakeup events across CPUs, which involve
129*6dbdd20aSAndroid Build Coastguard Worker      inter-processor interrupts. The former is always emitted on the source (wakee)
130*6dbdd20aSAndroid Build Coastguard Worker      CPU, the latter may be executed on either the source or the destination (waked) CPU
131*6dbdd20aSAndroid Build Coastguard Worker      depending on several factors. `sched_waking` is usually sufficient for latency
132*6dbdd20aSAndroid Build Coastguard Worker      analysis, unless you are looking into breaking down latency due to
133*6dbdd20aSAndroid Build Coastguard Worker      the scheduler's wake up path, such as inter-processor signaling.
134*6dbdd20aSAndroid Build Coastguard Worker
135*6dbdd20aSAndroid Build Coastguard WorkerWhen enabling `sched_waking` events, the following will appear in the UI when
136*6dbdd20aSAndroid Build Coastguard Workerselecting a CPU slice:
137*6dbdd20aSAndroid Build Coastguard Worker
138*6dbdd20aSAndroid Build Coastguard Worker![](/docs/images/latency.png "Scheduling wake-up events in the UI")
139*6dbdd20aSAndroid Build Coastguard Worker
140*6dbdd20aSAndroid Build Coastguard Worker### Decoding `end_state`
141*6dbdd20aSAndroid Build Coastguard Worker
142*6dbdd20aSAndroid Build Coastguard WorkerThe [sched_slice](/docs/analysis/sql-tables.autogen#sched_slice) table contains
143*6dbdd20aSAndroid Build Coastguard Workerinformation on scheduling activity of the system:
144*6dbdd20aSAndroid Build Coastguard Worker
145*6dbdd20aSAndroid Build Coastguard Worker```
146*6dbdd20aSAndroid Build Coastguard Worker> select * from sched_slice limit 1
147*6dbdd20aSAndroid Build Coastguard Workerid  type        ts          dur    cpu utid end_state priority
148*6dbdd20aSAndroid Build Coastguard Worker0   sched_slice 70730062200 125364 0   1    S         130
149*6dbdd20aSAndroid Build Coastguard Worker```
150*6dbdd20aSAndroid Build Coastguard Worker
151*6dbdd20aSAndroid Build Coastguard WorkerEach row of the table shows when a given thread (`utid`) began running
152*6dbdd20aSAndroid Build Coastguard Worker(`ts`), on which core it ran (`cpu`), for how long it ran (`dur`),
153*6dbdd20aSAndroid Build Coastguard Workerand why it stopped running: `end_state`.
154*6dbdd20aSAndroid Build Coastguard Worker
155*6dbdd20aSAndroid Build Coastguard Worker`end_state` is encoded as one or more ascii characters. The UI uses
156*6dbdd20aSAndroid Build Coastguard Workerthe following translations to convert `end_state` into human readable
157*6dbdd20aSAndroid Build Coastguard Workertext:
158*6dbdd20aSAndroid Build Coastguard Worker
159*6dbdd20aSAndroid Build Coastguard Worker| end_state  | Translation            |
160*6dbdd20aSAndroid Build Coastguard Worker|------------|------------------------|
161*6dbdd20aSAndroid Build Coastguard Worker| R          | Runnable               |
162*6dbdd20aSAndroid Build Coastguard Worker| R+         | Runnable (Preempted)   |
163*6dbdd20aSAndroid Build Coastguard Worker| S          | Sleeping               |
164*6dbdd20aSAndroid Build Coastguard Worker| D          | Uninterruptible Sleep  |
165*6dbdd20aSAndroid Build Coastguard Worker| T          | Stopped                |
166*6dbdd20aSAndroid Build Coastguard Worker| t          | Traced                 |
167*6dbdd20aSAndroid Build Coastguard Worker| X          | Exit (Dead)            |
168*6dbdd20aSAndroid Build Coastguard Worker| Z          | Exit (Zombie)          |
169*6dbdd20aSAndroid Build Coastguard Worker| x          | Task Dead              |
170*6dbdd20aSAndroid Build Coastguard Worker| I          | Idle                   |
171*6dbdd20aSAndroid Build Coastguard Worker| K          | Wake Kill              |
172*6dbdd20aSAndroid Build Coastguard Worker| W          | Waking                 |
173*6dbdd20aSAndroid Build Coastguard Worker| P          | Parked                 |
174*6dbdd20aSAndroid Build Coastguard Worker| N          | No Load                |
175*6dbdd20aSAndroid Build Coastguard Worker
176*6dbdd20aSAndroid Build Coastguard WorkerNot all combinations of characters are meaningful.
177*6dbdd20aSAndroid Build Coastguard Worker
178*6dbdd20aSAndroid Build Coastguard WorkerIf we do not know when the scheduling ended (for example because the
179*6dbdd20aSAndroid Build Coastguard Workertrace ended while the thread was still running) `end_state` will be
180*6dbdd20aSAndroid Build Coastguard Worker`NULL` and `dur` will be -1.
181*6dbdd20aSAndroid Build Coastguard Worker
182