Home | History | Annotate | Download | only in debug
      1 <html devsite>
      2   <head>
      3     <title>Using ftrace</title>
      4     <meta name="project_path" value="/_project.yaml" />
      5     <meta name="book_path" value="/_book.yaml" />
      6   </head>
      7   <body>
      8   <!--
      9       Copyright 2017 The Android Open Source Project
     10 
     11       Licensed under the Apache License, Version 2.0 (the "License");
     12       you may not use this file except in compliance with the License.
     13       You may obtain a copy of the License at
     14 
     15           http://www.apache.org/licenses/LICENSE-2.0
     16 
     17       Unless required by applicable law or agreed to in writing, software
     18       distributed under the License is distributed on an "AS IS" BASIS,
     19       WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     20       See the License for the specific language governing permissions and
     21       limitations under the License.
     22   -->
     23 
     24 
     25 <p>ftrace is a debugging tool for understanding what is going on inside the
     26 Linux kernel. The following sections detail basic ftrace functionality, ftrace
     27 usage with atrace (which captures kernel events), and dynamic ftrace.</p>
     28 
     29 <p>For details on advanced ftrace functionality that is not available from
     30 systrace, refer to the ftrace documentation at
     31 <a href="https://www.kernel.org/doc/Documentation/trace/ftrace.txt"><code>&lt;kernel
     32 tree&gt;/Documentation/trace/ftrace.txt</code></a>.</p>
     33 
     34 <h2 id="atrace">Capturing kernel events with atrace</h2>
     35 <p>atrace (<code>frameworks/native/cmds/atrace</code>) uses ftrace to capture
     36 kernel events. In turn, systrace.py (or run_systrace.py in later versions of
     37 <a href="https://github.com/catapult-project/catapult">Catapult</a>) uses adb
     38 to run atrace on the device. atrace does the following:</p>
     39 <ul>
     40 <li>Sets up user-mode tracing by setting a property
     41 (<code>debug.atrace.tags.enableflags</code>).</li>
     42 <li>Enables the desired ftrace functionality by writing to the appropriate
     43 ftrace sysfs nodes. However, as ftrace supports more features, you might set
     44 some sysfs nodes yourself then use atrace. </li>
     45 </ul>
     46 
     47 <p>With the exception of boot-time tracing, rely on using atrace to set the
     48 property to the appropriate value. The property is a bitmask and there's no good
     49 way to determine the correct values other than looking at the appropriate header
     50 (which could change between Android releases).</p>
     51 
     52 <h2 id="enabling_events">Enabling ftrace events</h2>
     53 
     54 <p>The ftrace sysfs nodes are in <code>/d/tracing</code> and trace events are
     55 divided into categories in <code>/d/tracing/events</code>.
     56 
     57 <p>To enable events on a per-category basis, use:
     58 <pre class="devsite-terminal devsite-click-to-copy">
     59 echo 1 &gt; /d/tracing/events/irq/enable
     60 </pre>
     61 
     62 <p>To enable events on per-event basis, use:
     63 <pre class="devsite-terminal devsite-click-to-copy">
     64 echo 1 &gt; /d/tracing/events/sched/sched_wakeup/enable
     65 </pre>
     66 
     67 <p>If extra events have been enabled by writing to sysfs nodes, they will
     68 <strong>not</strong> be reset by atrace. A common pattern
     69 for Qualcomm device bringup is to enable <code>kgsl</code> (GPU) and
     70 <code>mdss</code> (display pipeline) tracepoints and then use atrace or
     71 <a href="/devices/tech/debug/systrace.html">systrace</a>:</p>
     72 
     73 <pre class="devsite-click-to-copy">
     74 <code class="devsite-terminal">adb shell "echo 1 &gt; /d/tracing/events/mdss/enable"</code>
     75 <code class="devsite-terminal">adb shell "echo 1 &gt; /d/tracing/events/kgsl/enable"</code>
     76 <code class="devsite-terminal">./systrace.py sched freq idle am wm gfx view binder_driver irq workq ss sync -t 10 -b 96000 -o full_trace.html</code>
     77 </pre>
     78 
     79 <p>You can also use ftrace without atrace or systrace, which is
     80 useful when you want kernel-only traces (or if you've taken the time to write
     81 the user-mode tracing property by hand). To run just ftrace:</p>
     82 
     83 <ol>
     84 <li>Set the buffer size to a value large enough for your trace:
     85 <pre class="devsite-terminal devsite-click-to-copy">
     86 echo 96000 &gt; /d/tracing/buffer_size_kb
     87 </pre>
     88 </li>
     89 <li>Enable tracing:
     90 <pre class="devsite-terminal devsite-click-to-copy">
     91 echo 1 &gt; /d/tracing/tracing_on
     92 </pre>
     93 </li>
     94 <li>Run your test, then disable tracing:
     95 <pre class="devsite-terminal devsite-click-to-copy">
     96 echo 0 &gt; /d/tracing/tracing_on
     97 </pre>
     98 </li>
     99 <li>Dump the trace:
    100 <pre class="devsite-terminal devsite-click-to-copy">
    101 cat /d/tracing/trace &gt; /data/local/tmp/trace_output
    102 </pre>
    103 </li>
    104 </ol>
    105 
    106 <p>The trace_output gives the trace in text form. To visualize it using
    107 Catapult, get the
    108 <a href="https://github.com/catapult-project/catapult/tree/master/">Catapult
    109 repository</a> from Github and run trace2html:</p>
    110 
    111 <pre class="devsite-terminal devsite-click-to-copy">
    112 catapult/tracing/bin/trace2html ~/path/to/trace_file
    113 </pre>
    114 
    115 <p>By default, this writes <code>trace_file.html</code> in the same
    116 directory.</p>
    117 
    118 <h2 id="correlate">Correlating events</h2>
    119 <p>It is often useful to look at the Catapult visualization and the ftrace
    120 log simultaneously; for example, some ftrace events (especially vendor-specific
    121 ones) are not visualized by Catapult. However, Catapult's timestamps are
    122 relative either to the first event in the trace or to a specific timestamp
    123 dumped by atrace, while the raw ftrace timestamps are based on a particular
    124 absolute clock source in the Linux kernel.</p>
    125 
    126 <p>To find a given ftrace event from a Catapult event:</p>
    127 
    128 <ol>
    129 <li>Open the raw ftrace log. Traces in recent versions of systrace are
    130 compressed by default:
    131 <ul>
    132 <li>If you captured your systrace with <code>--no-compress</code>, this is in
    133 the html file in the section beginning with BEGIN TRACE.</li>
    134 <li>If not, run html2trace from the
    135 <a href="https://github.com/catapult-project/catapult/tree/master/">Catapult
    136 tree</a> (<code>tracing/bin/html2trace</code>) to uncompress the trace.</li>
    137 </ul>
    138 </li>
    139 <li>Find the relative timestamp in the Catapult visualization.</li>
    140 
    141 <li>Find a line at the beginning of the trace containing
    142 <code>tracing_mark_sync</code>. It should look something like this:
    143 <pre class="devsite-click-to-copy">
    144 &lt;5134&gt;-5134  (-----) [003] ...1    68.104349: tracing_mark_write: trace_event_clock_sync: parent_ts=68.104286
    145 </pre>
    146 
    147 <br>If this line does not exist (or if you used ftrace without atrace), then
    148 timings will be relative from the first event in the ftrace log.
    149 <ol style="list-style-type: lower-alpha">
    150 <li>Add the relative timestamp (in milliseconds) to the value in
    151 <code>parent_ts</code> (in seconds).</li>
    152 <li>Search for the new timestamp.</li>
    153 </ol>
    154 </li>
    155 </ol>
    156 <p>These steps should put you at (or at least very close to) the event.</p>
    157 
    158 <h2 id="dftrace">Using dynamic ftrace</h2>
    159 <p>When systrace and standard ftrace are insufficient, there is one last
    160 recourse available: <em>dynamic ftrace</em>. Dynamic ftrace involves rewriting
    161 of kernel code after boot, and as a result it is not available in production
    162 kernels for security reasons. However, every single difficult performance bug in
    163 2015 and 2016 was ultimately root-caused using dynamic ftrace. It is especially
    164 powerful for debugging uninterruptible sleeps because you can get a stack trace
    165 in the kernel every time you hit the function triggering uninterruptible sleep.
    166 You can also debug sections with interrupts and preemptions disabled, which can
    167 be very useful for proving issues.</p>
    168 
    169 <p>To turn on dynamic ftrace, edit your kernel's defconfig:</p>
    170 
    171 <ol>
    172 <li>Remove CONFIG_STRICT_MEMORY_RWX (if it's present). If you're on 3.18 or
    173 newer and arm64, it's not there.</li>
    174 <li>Add the following: CONFIG_DYNAMIC_FTRACE=y, CONFIG_FUNCTION_TRACER=y,
    175 CONFIG_IRQSOFF_TRACER=y, CONFIG_FUNCTION_PROFILER=y, and CONFIG_PREEMPT_TRACER=y
    176 </li>
    177 <li>Rebuild and boot the new kernel.</li>
    178 <li>Run the following to check for available tracers:
    179 <pre class="devsite-terminal devsite-click-to-copy">
    180 cat /d/tracing/available_tracers
    181 </pre>
    182 </li>
    183 <li>Confirm the command returns <code>function</code>, <code>irqsoff</code>,
    184 <code>preemptoff</code>, and <code>preemptirqsoff</code>.</li>
    185 <li>Run the following to ensure dynamic ftrace is working:
    186 <pre class="devsite-terminal devsite-click-to-copy">
    187 cat /d/tracing/available_filter_functions | grep &lt;a function you care about&gt;
    188 </pre>
    189 </li>
    190 </ol>
    191 
    192 <p>After completing these steps, you have dynamic ftrace, the function profiler,
    193 the irqsoff profiler, and the preemptoff profiler available. We <strong>strongly
    194 recommend</strong> reading ftrace documentation on these topics before using
    195 them as they are powerful but complex. irqsoff and preemptoff are primarily
    196 useful for confirming that drivers may be leaving interrupts or preemption
    197 turned off for too long.</p>
    198 <p>The function profiler is the best option for performance issues and is often
    199 used to find out where a function is being called.</p>
    200 
    201 <section class="expandable">
    202 <h4 class="showalways">Show Issue: HDR photo + rotating viewfinder</h4>
    203 
    204 <p>In this issue, using a Pixel XL to take an HDR+ photo then immediately
    205 rotating the viewfinder caused jank every time. We used the function profiler to
    206 debug the issue in less than one hour. To follow along with the example,
    207 <a href="perf_traces.zip">download the zip file</a> of traces (which also
    208 includes other traces referred to in this section), unzip the file, and open the
    209 trace_30898724.html file in your browser.</p>
    210 
    211 <p>The trace shows several threads in the cameraserver process blocked in
    212 uninterruptible sleep on <code>ion_client_destroy</code>. That's an expensive
    213 function, but it should be called very infrequently because ion clients should
    214 encompass many allocations. Initially, the blame fell on the Hexagon code in
    215 Halide, which was indeed one of the culprits (it created a new client for every
    216 ion allocation and destroyed that client when the allocation was freed, which
    217 was way too expensive). Moving to a single ion client for all Hexagon
    218 allocations improved the situation, but the jank wasn't fixed.</p>
    219 <p>At this point we need to know who is calling <code>ion_client_destroy</code>,
    220 so it's time to use the function profiler:</p>
    221 <p></p>
    222 <ol>
    223 <li>As functions are sometimes renamed by the compiler, confirm
    224 <code>ion_client_destroy</code> is there by using:
    225 <pre class="devsite-terminal devsite-click-to-copy">
    226 cat /d/tracing/available_filter_functions | grep ion_client_destroy
    227 </pre>
    228 </li>
    229 <li>After confirming it is there, use it as the ftrace filter:
    230 <pre class="devsite-terminal devsite-click-to-copy">
    231 echo ion_client_destroy &gt; /d/tracing/set_ftrace_filter
    232 </pre>
    233 </li>
    234 <li>Turn on the function profiler:
    235 <pre class="devsite-terminal devsite-click-to-copy">
    236 echo function &gt; /d/tracing/current_tracer
    237 </pre>
    238 </li>
    239 <li>Turn on stack traces whenever a filter function is called:
    240 <pre class="devsite-terminal devsite-click-to-copy">
    241 echo func_stack_trace &gt; /d/tracing/trace_options
    242 </pre>
    243 </li>
    244 <li>Increase the buffer size:
    245 <pre class="devsite-terminal devsite-click-to-copy">
    246 echo 64000 &gt; /d/tracing/buffer_size_kb
    247 </pre>
    248 </li>
    249 <li>Turn on tracing:
    250 <pre class="devsite-terminal devsite-click-to-copy">
    251 echo 1 &gt; /d/tracing/trace_on
    252 </pre>
    253 </li>
    254 <li>Run the test and get the trace:
    255 <pre class="devsite-terminal devsite-click-to-copy">
    256 cat /d/tracing/trace &gt; /data/local/tmp/trace
    257 </pre>
    258 </li>
    259 <li>View the trace to see lots and lots of stack traces:
    260 <pre class="devsite-click-to-copy">
    261     cameraserver-643   [003] ...1    94.192991: ion_client_destroy &lt;-ion_release
    262     cameraserver-643   [003] ...1    94.192997: &lt;stack trace&gt;
    263  =&gt; ftrace_ops_no_ops
    264  =&gt; ftrace_graph_call
    265  =&gt; ion_client_destroy
    266  =&gt; ion_release
    267  =&gt; __fput
    268  =&gt; ____fput
    269  =&gt; task_work_run
    270  =&gt; do_notify_resume
    271  =&gt; work_pending
    272  </pre>
    273 </li>
    274  </ol>
    275 
    276 <p>Based on inspection of the ion driver, we can see that
    277 <code>ion_client_destroy</code> is being spammed by a userspace function closing
    278 an fd to <code>/dev/ion</code>, not a random kernel driver. By searching the
    279 Android codebase for <code>\"/dev/ion\"</code>, we find several vendor drivers
    280 doing the same thing as the Hexagon driver and opening/closing
    281 <code>/dev/ion</code> (creating and destroying a new ion client) every time they
    282 need a new ion allocation. Changing those to
    283 <a href="https://android.googlesource.com/platform/hardware/qcom/camera/+/8f7984018b6643f430c229725a58d3c6bb04acab">use
    284 a single ion client</a> for the lifetime of the process fixed the bug.</p>
    285 </section>
    286 <hr>
    287 
    288 <p>If the data from function profiler isn't specific enough, you can combine
    289 ftrace tracepoints with the function profiler. ftrace events can be enabled in
    290 exactly the same way as usual, and they will be interleaved with your trace.
    291 This is great if there's an occasional long uninterruptible sleep in a specific
    292 function you want to debug: set the ftrace filter to the function you want,
    293 enable tracepoints, take a trace. You can parse the resulting trace with
    294 <code>trace2html</code>, find the event you want, then get nearby stack traces
    295 in the raw trace.</p>
    296 
    297 <h2 id="lock_stat">Using lockstat</h2>
    298 <p>Sometimes, ftrace isn't enough and you really need to debug what appears to
    299 be kernel lock contention. There is one more kernel option worth trying:
    300 <code>CONFIG_LOCK_STAT</code>. This is a last resort as it is extremely
    301 difficult to get working on Android devices because it inflates the size of the
    302 kernel beyond what most devices can handle.</p>
    303 <p>However, lockstat uses the debug
    304 locking infrastructure, which is useful for many other applications. Everyone
    305 working on device bringup should figure out some way to get that option working
    306 on every device because there <strong>will</strong> be a time when you think
    307 "If only I could turn on <code>LOCK_STAT</code>, I could confirm or refute this
    308 as the problem in five minutes instead of five days."</p>
    309 
    310 <section class="expandable">
    311 <h4 class="showalways">Show Issue: Stall in SCHED_FIFO when cores at max load
    312 with non-SCHED_FIFO</h4>
    313 
    314 <p>In this issue, the SCHED_FIFO thread stalled when all cores were at maximum
    315 load with non-SCHED_FIFO threads. We had traces showing significant lock
    316 contention on an fd in VR apps, but we couldn't easily identify the fd in use.
    317 To follow along with the example, <a href="perf_traces.zip">download the zip
    318 file</a> of traces (which also includes other traces referred to in this
    319 section), unzip the file, and open the trace_30905547.html file in your browser.
    320 </p>
    321 
    322 <p>We hypothesized that ftrace itself was the source of lock contention, when a
    323 low priority thread would start writing to the ftrace pipe and then get
    324 preempted before it could release the lock. This is a worst-case scenario that
    325 was exacerbated by a mixture of extremely low-priority threads writing to the
    326 ftrace marker along with some higher priority threads spinning on CPUs to
    327 simulate a completely loaded device.</p>
    328 <p>As we couldn't use ftrace to debug, we got <code>LOCK_STAT</code> working
    329 then turned off all other tracing from the app. The results showed the lock
    330 contention was actually from ftrace because none of the contention showed up in
    331 the lock trace when ftrace was not running.</p>
    332 </section>
    333 <hr>
    334 
    335 <p>If you can boot a kernel with the config option, lock tracing is similar to
    336 ftrace:</p>
    337 <ol>
    338 <li>Enable tracing:
    339 <pre class="devsite-terminal devsite-click-to-copy">
    340 echo 1 &gt; /proc/sys/kernel/lock_stat
    341 </pre>
    342 </li>
    343 <li>Run your test.</li>
    344 <li>Disable tracing:
    345 <pre class="devsite-terminal devsite-click-to-copy">
    346 echo 0 &gt; /proc/sys/kernel/lock_stat
    347 </pre>
    348 </li>
    349 <li>Dump your trace:
    350 <pre class="devsite-terminal devsite-click-to-copy">
    351 cat /proc/lock_stat &gt; /data/local/tmp/lock_stat
    352 </pre>
    353 </li>
    354 </ol>
    355 
    356 <p>For help interpreting the resulting output, refer to lockstat documentation
    357 at <a href="https://www.kernel.org/doc/Documentation/locking/lockstat.txt"><code>&lt;kernel&gt;/Documentation/locking/lockstat.txt</code></a>.</p>
    358 
    359 </body>
    360 </html>
    361