| <html devsite> |
| <head> |
| <title>Optimizing Boot Times</title> |
| <meta name="project_path" value="/_project.yaml" /> |
| <meta name="book_path" value="/_book.yaml" /> |
| </head> |
| <body> |
| <!-- |
| Copyright 2017 The Android Open Source Project |
| |
| Licensed under the Apache License, Version 2.0 (the "License"); |
| you may not use this file except in compliance with the License. |
| You may obtain a copy of the License at |
| |
| http://www.apache.org/licenses/LICENSE-2.0 |
| |
| Unless required by applicable law or agreed to in writing, software |
| distributed under the License is distributed on an "AS IS" BASIS, |
| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| See the License for the specific language governing permissions and |
| limitations under the License. |
| --> |
| |
| <p> |
| This document provides partner guidance for improving boot times for specific |
| Android devices. Boot time is an important component of system performance as |
| users must wait for boot to complete before they can use the device. For devices |
| such as cars where cold boot-up happens more frequently, having a quick boot |
| time is critical (no one likes waiting for dozens of seconds just to input a |
| navigation destination). |
| </p> |
| |
| <p> |
| Android 8.0 allows for reduced boot times by supporting several improvements |
| across a range of components. The following table summarizes these performance |
| improvements (as measured on a Google Pixel and Pixel XL devices). |
| </p> |
| |
| <table> |
| <tr> |
| <th>Component</th> |
| <th>Improvement</th> |
| </tr> |
| <tr> |
| <td>Bootloader |
| </td> |
| <td> |
| <ul> |
| <li>Saved 1.6s by removing UART log |
| <li>Saved 0.4s by changing to LZ4 from GZIP</li> |
| </ul> |
| </td> |
| </tr> |
| <tr> |
| <td>Device kernel |
| </td> |
| <td> |
| <ul> |
| <li>Saved 0.3s by removing unused kernel configs and reducing driver size |
| <li>Saved 0.3s with dm-verity prefetch optimization |
| <li>Saved 0.15s to remove unnecessary wait/test in driver |
| <li>Saved 0.12s to remove CONFIG_CC_OPTIMIZE_FOR_SIZE</li> |
| </ul> |
| </td> |
| </tr> |
| <tr> |
| <td>I/O tuning |
| </td> |
| <td> |
| <ul> |
| <li>Saved 2s on normal boot |
| <li>Saved 25s on first boot</li> |
| </ul> |
| </td> |
| </tr> |
| <tr> |
| <td>init.*.rc |
| </td> |
| <td> |
| <ul> |
| <li>Saved 1.5s by paralleling init commands |
| <li>Saved 0.25s by starting zygote early |
| <li>Saved 0.22s by cpuset tune</li> |
| </ul> |
| </td> |
| </tr> |
| <tr> |
| <td>Boot animation |
| </td> |
| <td> |
| <ul> |
| <li>Started 2s earlier on boot without fsck triggered, much bigger on boot with |
| fsck triggered boot |
| <li>Saved 5s on Pixel XL with immediate shutdown of boot animation</li> |
| </ul> |
| </td> |
| </tr> |
| <tr> |
| <td>SELinux policy |
| </td> |
| <td>Saved 0.2s on by genfscon |
| </td> |
| </tr> |
| </table> |
| |
| <h2 id="optimizing-bootloader">Optimizing Bootloader</h2> |
| |
| <p> |
| To optimize bootloader for improved boot times: |
| </p> |
| <ul> |
| <li>For logging: |
| <ul> |
| <li>Disable log writing to UART as it can take a long time with lots of |
| logging. (On the Google Pixel devices, we found it slows the bootloader 1.5s).</li> |
| <li>Log only error situations and consider storing other information to memory |
| with a separate mechanism to retrieve.</li> |
| </ul> |
| </li> |
| <li>For kernel decompression, considering using LZ4 for contemporary hardware |
| instead of GZIP (example <a class="external" |
| href="https://patchwork.kernel.org/patch/6810841/">patch</a>). Keep in mind that |
| different kernel compression options can have different loading and |
| decompression times, and some options may work better than others for your |
| specific hardware.</li> |
| <li>Check unnecessary wait times for debouncing/special mode entry and minimize |
| them.</li> |
| <li>Pass boot time spent in bootloader to kernel as cmdline.</li> |
| <li>Check CPU clock and consider parallelization (requires multi-core support) |
| for kernel loading and initializing I/O.</li> |
| </ul> |
| |
| <h2 id="optimizing-kernel">Optimizing Kernel</h2> |
| |
| <p> |
| Use the following tips to optimize the kernel for improved boot times. |
| </p> |
| |
| <h3 id="minimizing-device-defconfig">Minimizing device defconfig</h3> |
| |
| <p> |
| Minimizing kernel config can reduce kernel size for faster loading |
| decompression, initialization and smaller attack surfaces. To optimize the |
| device defconfig: |
| </p> |
| |
| <ul> |
| <li><strong>Identify unused drivers</strong>. Review the <code>/dev</code> and |
| <code>/sys</code> directories and look for nodes with general SELinux labels |
| (which indicates those nodes are not configured to be accessible by user space). |
| Remove any such nodes if found. |
| <li><strong>Unset unused CONFIGs</strong>. Review the .config file generated by |
| kernel build to explicitly unset any unused CONFIG that was turned on by |
| default. For example, we removed the following unused CONFIGs from the Google |
| Pixel: |
| |
| <pre |
| class="prettyprint"> |
| CONFIG_ANDROID_LOGGER=y |
| CONFIG_IMX134=y |
| CONFIG_IMX132=y |
| CONFIG_OV9724=y |
| CONFIG_OV5648=y |
| CONFIG_GC0339=y |
| CONFIG_OV8825=y |
| CONFIG_OV8865=y |
| CONFIG_s5k4e1=y |
| CONFIG_OV12830=y |
| CONFIG_USB_EHCI_HCD=y |
| CONFIG_IOMMU_IO_PGTABLE_FAST_SELFTEST=y |
| CONFIG_IKCONFIG=y |
| CONFIG_RD_BZIP2=y |
| CONFIG_RD_LZMA=y |
| CONFIG_TI_DRV2667=y |
| CONFIG_CHR_DEV_SCH=y |
| CONFIG_MMC=y |
| CONFIG_MMC_PERF_PROFILING=y |
| CONFIG_MMC_CLKGATE=y |
| CONFIG_MMC_PARANOID_SD_INIT=y |
| CONFIG_MMC_BLOCK_MINORS=32 |
| CONFIG_MMC_TEST=y |
| CONFIG_MMC_SDHCI=y |
| CONFIG_MMC_SDHCI_PLTFM=y |
| CONFIG_MMC_SDHCI_MSM=y |
| CONFIG_MMC_SDHCI_MSM_ICE=y |
| CONFIG_MMC_CQ_HCI=y |
| CONFIG_MSDOS_FS=y |
| # CONFIG_SYSFS_SYSCALL is not set |
| CONFIG_EEPROM_AT24=y |
| # CONFIG_INPUT_MOUSEDEV_PSAUX is not set |
| CONFIG_INPUT_HBTP_INPUT=y |
| # CONFIG_VGA_ARB is not set |
| CONFIG_USB_MON=y |
| CONFIG_USB_STORAGE_DATAFAB=y |
| CONFIG_USB_STORAGE_FREECOM=y |
| CONFIG_USB_STORAGE_ISD200=y |
| CONFIG_USB_STORAGE_USBAT=y |
| CONFIG_USB_STORAGE_SDDR09=y |
| CONFIG_USB_STORAGE_SDDR55=y |
| CONFIG_USB_STORAGE_JUMPSHOT=y |
| CONFIG_USB_STORAGE_ALAUDA=y |
| CONFIG_USB_STORAGE_KARMA=y |
| CONFIG_USB_STORAGE_CYPRESS_ATACB=y |
| CONFIG_SW_SYNC_USER=y |
| CONFIG_SEEMP_CORE=y |
| CONFIG_MSM_SMEM_LOGGING=y |
| CONFIG_IOMMU_DEBUG=y |
| CONFIG_IOMMU_DEBUG_TRACKING=y |
| CONFIG_IOMMU_TESTS=y |
| CONFIG_MOBICORE_DRIVER=y |
| # CONFIG_DEBUG_PREEMPT is not set |
| </pre> |
| </li> |
| </ul> |
| |
| <ul> |
| <li><strong>Remove CONFIGs that lead to unnecessary test runs on every |
| boot</strong>. While useful in development, such configs (i.e. |
| CONFIG_IOMMU_IO_PGTABLE_FAST_SELFTEST) should be removed in a production |
| kernel. |
| </li> |
| </ul> |
| |
| <h3 id="minimizing-driver-size">Minimizing driver size</h3> |
| |
| <p> |
| Some drivers in the device kernel can be removed if the function is not used to |
| reduce kernel size further. For example, if WLAN is connected through PCIe, the |
| SDIO support is not used and should be removed during compile time. For details, |
| refer to the Google Pixel kernel: net: wireless: cnss: add option to disable |
| SDIO support. |
| |
| </p> |
| |
| <h3 id="removing-compiler-optimization-for-size">Removing compiler optimization |
| for size</h3> |
| |
| <p> |
| Remove the kernel config for CONFIG_CC_OPTIMIZE_FOR_SIZE. This flag was |
| originally introduced when the assumption was that smaller code size would yield |
| hot cache hit (and thus be faster). However, this assumption is no longer valid |
| as modern mobile SoCs have become more powerful. |
| </p> |
| |
| <p> |
| In addition, removing the flag can enable the compiler warning for uninitialized |
| variables, which is suppressed in Linux kernels when the |
| CONFIG_CC_OPTIMIZE_FOR_SIZE flag is present (making this change alone has helped |
| us uncover many meaningful bugs in some Android device drivers). |
| </p> |
| |
| <h3 id="deferring-initialization">Deferring initialization</h3> |
| |
| <p> |
| Many processes launch during boot, but only components in critical path |
| (bootloader > kernel > init > file system mount > zygote > system server) |
| directly affect boot time. Profile <strong>initcall</strong> during kernel |
| booting to identify peripheral/components that are slow and not critical |
| to start init process, then delay those peripherals/components until later |
| in the boot process by moving into loadable kernel modules. Moving to |
| asynchronous device/driver probe can also help to parallel slow components |
| in kernel > init critical path. |
| </p> |
| |
| <pre |
| class="prettyprint"> |
| BoardConfig-common.mk: |
| BOARD_KERNEL_CMDLINE += initcall_debug ignore_loglevel |
| |
| driver: |
| .probe_type = PROBE_PREFER_ASYNCHRONOUS, |
| </pre> |
| |
| <p class="note"> |
| <strong>Note:</strong> Driver dependencies must be resolved carefully by adding |
| <code>EPROBEDEFER</code> support. |
| </p> |
| |
| <h2 id="optimizing-i-o-efficiency">Optimizing I/O efficiency</h2> |
| |
| <p> |
| Improving I/O efficiency is critical to making boot time faster, and reading |
| anything not necessary should be deferred until after boot (on a Google Pixel, |
| about 1.2GB of data is read on boot). |
| </p> |
| |
| <h3 id="tuning-the-filesystem">Tuning the filesystem</h3> |
| |
| <p> |
| The Linux kernel read ahead kicks in when a file is read from beginning or when |
| blocks are read sequentially, making it necessary to tune I/O scheduler |
| parameters specifically for booting (which has a different workload |
| characterization than normal applications). |
| </p> |
| |
| <p> |
| Devices that support seamless (A/B) updates benefit greatly from filesystem |
| tuning on first time boot (e.g. 20s on Google Pixel). An an example, we tuned |
| the following parameters for the Google Pixel: |
| </p> |
| |
| <pre |
| class="prettyprint"> |
| on late-fs |
| # boot time fs tune |
| # boot time fs tune |
| write /sys/block/sda/queue/iostats 0 |
| write /sys/block/sda/queue/scheduler cfq |
| write /sys/block/sda/queue/iosched/slice_idle 0 |
| write /sys/block/sda/queue/read_ahead_kb 2048 |
| write /sys/block/sda/queue/nr_requests 256 |
| write /sys/block/dm-0/queue/read_ahead_kb 2048 |
| write /sys/block/dm-1/queue/read_ahead_kb 2048 |
| |
| on property:sys.boot_completed=1 |
| # end boot time fs tune |
| write /sys/block/sda/queue/read_ahead_kb 512 |
| ... |
| </pre> |
| |
| <h3 id="miscellaneous">Miscellaneous</h3> |
| |
| <ul> |
| <li>Turn on the dm-verity hash prefetch size using kernel config |
| DM_VERITY_HASH_PREFETCH_MIN_SIZE (default size is 128). |
| <li>For better file system stability and a dropped forced check that occurs on |
| every boot, use the new ext4 generation tool by setting TARGET_USES_MKE2FS in |
| BoardConfig.mk.</li> |
| </ul> |
| |
| <h3 id="analyzing-i-o">Analyzing I/O</h3> |
| |
| <p> |
| To understand I/O activities during boot, use kernel ftrace data (also used by |
| systrace): |
| </p> |
| |
| <pre |
| class="prettyprint">trace_event=block,ext4 in BOARD_KERNEL_CMDLINE</pre> |
| <p> |
| To breakdown file access for each file, make the following changes to the kernel |
| (development kernel only; do not use in production kernels): |
| </p> |
| |
| <pre |
| class="prettyprint"> |
| diff --git a/fs/open.c b/fs/open.c |
| index 1651f35..a808093 100644 |
| --- a/fs/open.c |
| +++ b/fs/open.c |
| @@ -981,6 +981,25 @@ |
| } |
| EXPORT_SYMBOL(file_open_root); |
| |
| +static void _trace_do_sys_open(struct file *filp, int flags, int mode, long fd) |
| +{ |
| + char *buf; |
| + char *fname; |
| + |
| + buf = kzalloc(PAGE_SIZE, GFP_KERNEL); |
| + if (!buf) |
| + return; |
| + fname = d_path(&filp-<f_path, buf, PAGE_SIZE); |
| + |
| + if (IS_ERR(fname)) |
| + goto out; |
| + |
| + trace_printk("%s: open(\"%s\", %d, %d) fd = %ld, inode = %ld\n", |
| + current-<comm, fname, flags, mode, fd, filp-<f_inode-<i_ino); |
| +out: |
| + kfree(buf); |
| +} |
| + |
| long do_sys_open(int dfd, const char __user *filename, int flags, umode_t mode) |
| { |
| struct open_flags op; |
| @@ -1003,6 +1022,7 @@ |
| } else { |
| fsnotify_open(f); |
| fd_install(fd, f); |
| + _trace_do_sys_open(f, flags, mode, fd); |
| </pre> |
| |
| <p> |
| Use the following scripts to help with analyzing boot performance. |
| </p> |
| <ul> |
| <li><code>system/extras/boottime_tools/bootanalyze/bootanalyze.py</code> |
| Measures boot time with a breakdown of important steps in the boot process. |
| <li><code>system/extras/boottime_tools/io_analysis/check_file_read.py |
| boot_trace</code> Provides access information per each file. |
| <li><code>system/extras/boottime_tools/io_analysis/check_io_trace_all.py |
| boot_trace</code> Gives system-level breakdown.</li> |
| </ul> |
| |
| <h2 id="optimizing-init-*-rc">Optimizing init.*.rc</h2> |
| |
| <p> |
| Init is the bridge from the kernel till the framework is established, and |
| devices usually spend a few seconds in different init stages. |
| </p> |
| |
| <h3 id="running-tasks-in-parallel">Running tasks in parallel</h3> |
| |
| <p> |
| While the current Android init is more or less a single threaded process, you |
| can still perform some tasks in parallel. |
| </p> |
| |
| <ul> |
| <li>Execute slow commands in a shell script service and join that later by |
| waiting for specific property. Android 8.0 supports this use case with a new |
| <code>wait_for_property</code> command. |
| <li>Identify slow operations in init. The system logs the init command |
| exec/wait_for_prop or any action taking a long time (in Android 8.0, any command |
| taking more than 50 ms). For example: |
| |
| <pre |
| class="prettyprint">init: Command 'wait_for_coldboot_done' action=wait_for_coldboot_done returned 0 took 585.012ms</pre> |
| |
| <p> |
| Reviewing this log may indicate opportunities for improvements. |
| </p> |
| |
| <li>Start services and enable peripheral devices in critical path early. For |
| example, some SOCs require starting security-related services before starting |
| SurfaceFlinger. Review the system log when ServiceManager returns "wait for |
| service" — this is usually a sign that a dependent service must be started |
| first. |
| <li>Remove any unused services and commands in init.*.rc. Anything not used in |
| early stage init should be deferred to boot completed.</li></ul> |
| </li> |
| </ul> |
| |
| <p class="note"> |
| <strong>Note:</strong> Property service is part of init process, so calling |
| <code>setproperty</code> during boot can lead a long delay if init is busy in |
| builtin commands. |
| </p> |
| |
| <h3 id="using-scheduler-tuning">Using scheduler tuning</h3> |
| |
| <p> |
| Use scheduler tuning for early boot. Example from a Google Pixel: |
| </p> |
| |
| <pre |
| class="prettyprint">on init |
| # update cpusets now that processors are up |
| write /dev/cpuset/top-app/cpus 0-3 |
| write /dev/cpuset/foreground/cpus 0-3 |
| write /dev/cpuset/foreground/boost/cpus 0-3 |
| write /dev/cpuset/background/cpus 0-3 |
| write /dev/cpuset/system-background/cpus 0-3 |
| # set default schedTune value for foreground/top-app (only affects EAS) |
| write /dev/stune/foreground/schedtune.prefer_idle 1 |
| write /dev/stune/top-app/schedtune.boost 10 |
| write /dev/stune/top-app/schedtune.prefer_idle 1</pre> |
| |
| <p> |
| Some services may need a priority boost during boot. Example: |
| </p> |
| |
| <pre |
| class="prettyprint"> |
| init.zygote64.rc: |
| service zygote /system/bin/app_process64 -Xzygote /system/bin --zygote --start-system-server |
| class main |
| priority -20 |
| user root |
| ...</pre> |
| |
| <h3 id="starting-zygote-early">Starting zygote early</h3> |
| |
| <p> |
| Devices with file-based encryption can start zygote earlier at the zygote-start |
| trigger (by default, zygote is launched at class main, which is much later than |
| zygote-start). When doing this, make sure to allow zygote to run in all CPUs (as |
| the wrong cpuset setting may force zygote to run in specific CPUs). |
| </p> |
| |
| <h3 id="disable-power-saving">Disable power saving</h3> |
| |
| <p> |
| During device booting, power saving setting for components like UFS and/or CPU |
| governor can be disabled. |
| </p> |
| <p class="aside"><strong>Caution:</strong> Power saving should be enabled in |
| charger mode for efficiency.</p> |
| |
| <pre |
| class="prettyprint"> |
| on init |
| # Disable UFS powersaving |
| write /sys/devices/soc/${ro.boot.bootdevice}/clkscale_enable 0 |
| write /sys/devices/soc/${ro.boot.bootdevice}/clkgate_enable 0 |
| write /sys/devices/soc/${ro.boot.bootdevice}/hibern8_on_idle_enable 0 |
| write /sys/module/lpm_levels/parameters/sleep_disabled Y |
| on property:sys.boot_completed=1 |
| # Enable UFS powersaving |
| write /sys/devices/soc/${ro.boot.bootdevice}/clkscale_enable 1 |
| write /sys/devices/soc/${ro.boot.bootdevice}/clkgate_enable 1 |
| write /sys/devices/soc/${ro.boot.bootdevice}/hibern8_on_idle_enable 1 |
| write /sys/module/lpm_levels/parameters/sleep_disabled N |
| on charger |
| # Enable UFS powersaving |
| write /sys/devices/soc/${ro.boot.bootdevice}/clkscale_enable 1 |
| write /sys/devices/soc/${ro.boot.bootdevice}/clkgate_enable 1 |
| write /sys/devices/soc/${ro.boot.bootdevice}/hibern8_on_idle_enable 1 |
| write /sys/class/typec/port0/port_type sink |
| write /sys/module/lpm_levels/parameters/sleep_disabled N</pre> |
| |
| <h3 id="defer-non-critical-initialization">Defer non-critical initialization</h3> |
| |
| <p> |
| Non-critical initialization such as ZRAM can be deferred to boot_complete. |
| </p> |
| |
| <pre |
| class="prettyprint"> |
| on property:sys.boot_completed=1 |
| # Enable ZRAM on boot_complete |
| swapon_all /vendor/etc/fstab.${ro.hardware}</pre> |
| |
| <h2 id="optimizing-boot-animation">Optimizing boot animation</h2> |
| |
| <p> |
| Use the following tips to optimize the boot animation. |
| </p> |
| |
| <h3 id="configuring-early-start">Configuring early start</h3> |
| |
| <p> |
| Android 8.0 enables starting boot animation early, before mounting userdata |
| partition. However, even when using the new ext4 tool chain in Android 8.0, fsck |
| is still triggered periodically due to safety reasons, causing a delay in |
| starting the bootanimation service. |
| </p> |
| |
| <p> |
| To make bootanimation start early, split the fstab mount into two phases: |
| </p> |
| |
| <ul> |
| <li>In the early phase, mount only the partitions (such as |
| <code>system/</code> and <code>vendor/</code>) that don't require run |
| checks, then start boot animation services and its dependencies (such as |
| servicemanager and surfaceflinger). |
| <li>In the second phase, mount partitions (such as <code>data/</code>) that |
| do require run checks.</li> |
| </ul> |
| |
| <p> |
| Boot animation will be started much faster (and in constant time) regardless of |
| fsck. |
| </p> |
| |
| <h3 id="finishing-clean">Finishing clean</h3> |
| |
| <p> |
| After receiving the exit signal, bootanimation plays the last part, the length |
| of which can slow boot time. A system that boots quickly has no need for lengthy |
| animations which could effectively hide any improvements made. We recommend |
| making both the repeating loop and finale short. |
| </p> |
| |
| <h2 id="optimizing-selinux">Optimizing SELinux</h2> |
| |
| <p> |
| Use the following tips to optimize SELinux for improved boot times. |
| </p> |
| |
| <ul> |
| <li><strong>Use clean regular expressions (regex)</strong>. Poorly-formed regex |
| can lead to a lot of overhead when matching SELinux policy for |
| <code>sys/devices</code> in <code>file_contexts</code>. For example, the regex |
| <code>/sys/devices/.*abc.*(/.*)?</code> mistakenly forces a scan of all |
| <code>/sys/devices</code> subdirectories that contain "abc", enabling matches |
| for both <code>/sys/devices/abc</code> and <code>/sys/devices/xyz/abc</code>. |
| Improving this regex to <code>/sys/devices/[^/]*abc[^/]*(/.*)?</code> will |
| enable a match only for <code>/sys/devices/abc</code>. |
| <li><strong>Move labels to </strong><a |
| href="https://selinuxproject.org/page/FileStatements#genfscon">genfscon</a>. |
| This existing SELinux feature passes file-matching prefixes into the kernel in |
| the SELinux binary, where the kernel applies them to kernel-generated |
| filesystems. This also helps fix mislabeled kernel-created files, preventing |
| race conditions that can occur between userspace processes attempting to access |
| these files before relabeling occurs.</li> |
| </ul> |
| |
| <h2 id="tool-and-methods">Tool and methods</h2> |
| |
| <p> |
| Use the following tools to help you collect data for optimization targets. |
| </p> |
| |
| <h3 id="bootchart">Bootchart</h3> |
| |
| <p> |
| Bootchart provides CPU and I/O load breakdown of all processes for the whole |
| system. It doesn't require rebuilding system image and can be used as a quick |
| sanity check before diving into systrace. |
| </p> |
| |
| <p> |
| To enable bootchart: |
| </p> |
| |
| <pre> |
| <code class="devsite-terminal">adb shell 'touch /data/bootchart/enabled'</code> |
| <code class="devsite-terminal">adb reboot</code> |
| </pre> |
| |
| <p> |
| After boot up, fetch boot chart: |
| </p> |
| |
| <pre |
| class="prettyprint">$ANDROID_BUILD_TOP/system/core/init/grab-bootchart.sh</pre> |
| |
| <p> |
| When finished, delete <code>/data/bootchart/enabled</code> to prevent collecting |
| the date every time. |
| </p> |
| |
| <h3 id="systrace">Systrace</h3> |
| |
| <p> |
| Systrace allows collecting both kernel and Android traces during boot up. |
| Visualization of systrace can help in analyzing specific problem during the |
| boot-up. (However, to check the average number or accumulated number during the |
| entire boot, it is easier to look into kernel trace directly). |
| </p> |
| |
| <p> |
| To enable systrace during boot-up: |
| </p> |
| |
| <ul> |
| <li> In <code>frameworks/native/atrace/atrace.rc</code>, change: |
| |
| <pre |
| class="prettyprint">write /sys/kernel/debug/tracing/tracing_on 0</pre> |
| <p> |
| To: |
| </p> |
| |
| <pre |
| class="prettyprint">#write /sys/kernel/debug/tracing/tracing_on 0</pre> |
| </li> |
| |
| <p> |
| This enables tracing (which is disabled by default). |
| </p> |
| |
| <li>In the <code>device.mk</code> file, add the following line: |
| |
| <pre |
| class="prettyprint">PRODUCT_PROPERTY_OVERRIDES += debug.atrace.tags.enableflags=802922</pre> |
| </li> |
| |
| <li>In the device <code>BoardConfig.mk</code> file, add the following: |
| |
| <pre |
| class="prettyprint">BOARD_KERNEL_CMDLINE := ... trace_buf_size=64M trace_event=sched_wakeup,sched_switch,sched_blocked_reason,sched_cpu_hotplug</pre> |
| </li> |
| |
| <p> |
| For detailed I/O analysis, also add block and ext4. |
| </p> |
| |
| <li>In the device-specific <code>init.rc</code> file, make the following |
| changes: |
| <ul> |
| <li><code>on property:sys.boot_completed=1</code> (this stops tracing on boot |
| complete)</li> |
| <li><code>write /d/tracing/tracing_on 0</code></li> |
| <li><code>write /d/tracing/events/ext4/enable 0</code></li> |
| <li><code>write /d/tracing/events/block/enable 0</code></li> |
| </ul> |
| </li> |
| </ul> |
| |
| <p> |
| After boot up, fetch trace: |
| </p> |
| |
| |
| <pre class="devsite-terminal">adb root && adb shell "cat /d/tracing/trace" < boot_trace |
| ./external/chromium-trace/catapult/tracing/bin/trace2html boot_trace --output boot_trace.html |
| </pre> |
| |
| <p class="note"> |
| <strong>Note:</strong> Chrome cannot handle files that are too large. Consider |
| cutting the <code>boot_trace</code> file using <code>tail</code>, |
| <code>head</code>, or <code>grep</code> for necessary portions. And |
| I/O analysis often requires analyzing the captured <code>boot_trace</code> |
| directly, as there are too many events. |
| </p> |
| </body> |
| </html> |