For most embedded systems, particularly for consumer electronics like smartphone systems, to reduce the wait time of system power on or start up, the system must be fast enough.
Most embedded devices have strict time limits from power on to showing graphic UI, so speeding the boot time should be considered an important feature.
The following are the basic methods to speed system booting:
Disable unused features and functions in all booting components (bootloader, Linux kernel, system, and applications) of an embedded Linux system. This means let the system perform less but necessary jobs.
Some initialization procedures can be deferred to the background after the device has booted to a basically workable state.
If a multicore CPU is being used, parallize the boot process with multithreads.
Based on the considerations of power-cost optimization, set CPU frequency, bus frequency, memory frequency, and even external device working frequency (such as EMMC) as high as possible.
Measure the boot procedure and find out the time-cost bottlenecks.
Bootchart (http://www.bootchart.org/) is for performance analysis and visualization of the Linux boot process; it can be used for boot speedup optimization.
Android does include the init
method's built-in bootchartd
support, but requires the init
application to be rebuilt; for more details, visit http://elinux.org/Using_Bootchart_on_Android.
In our example, we introduce the BusyBox built-in bootchartd
support to measure the Android system boot procedure.
Configure Bootchart in BusyBox:
First, enable the Bootchart applet in BusyBox.
Init Utilities ---> [*] bootchartd [*] Compatible, bloated header [*] Support bootchartd.conf
Install BusyBox with
bootchartd
in Androidramdisk.img
:Then, copy the
busybox
binary to Androidramdisk.img
, create a link/bootchartd
tobusybox
, and create avar/log
directory.$ cd ramdisk/ $ ln -sf busybox /bootchartd $ mkdir var/log
Recompress the
ramdisk/
toramdisk.img
with the following:$ find . | cpio -H newc -o | gzip -9 > ../ramdisk.img
The link is for directly using
bootchartd
as theinit
process; thevar/log
directory is for saving the boot log generated bybootchartd
.Measure the Android system booting with BusyBox
bootchard
:Now start the Android emulator.
$ emulator @busybox-avd -shell -show-kernel -kernel ./zImage \ -ramdisk ./ramdisk.img \ -qemu -append "rdinit=/bootchartd bootchard_init=/init"
The
-qemu -append
options allow us to pass extra arguments to the Linux kernel; the precedingrdinit=/bootchartd
support replaces the default ramdiskinit
withbootchartd
, and thenbootchartd_init=/init
tellsbootchartd
to start the real/init
process.Get the bootchartd measuring log:
After a while, the Android UI will be started and a new file will be created to save the boot logs.
shell@android # ls -l /var/log total 72 -rw-r--r-- 1 0 0 73334 Jul 5 17:24 bootlog.tgz
Then, pull the logfile into our development system.
$ adb pull /var/log/bootlog.tgz
Draw the
bootchartd
log withpybootchartgui
, and analyze it.Analyze the boot log with
pybootchartgui
. This tool can generate a readable graphic output based on the previous boot logfile. In Ubuntu, we can install it simply with the following:$ sudo apt-get install bootchart pybootchartgui
Then draw a graph with it.
$ bootchart ./bootlog.tgz
It may generate an error, such as the header file format is not compatible with the original larger version of the bootchart:
File "/usr/lib/pymodules/python2.7/pybootchartgui/draw.py", line 341, in draw_header txt = headertitle + ': ' + mangle(headers.get(headerkey)) TypeError: cannot concatenate 'str' and 'NoneType' objects
To work around it, just let the
draw.py
file ofpybootchartgui
ignore the errors with except handling.$ vim /usr/lib/pymodules/python2.7/pybootchartgui/draw.py 338 for (headerkey, headertitle, mangle) in toshow: 339 header_y += ctx.font_extents()[2] 340 try: 341 txt = headertitle + ': ' + mangle(headers.get(headerkey)) 342 except: 343 continue 344 draw_text(ctx, txt, TEXT_COLOR, off_x, header_y)
If there are no other issues, we should get results successfully, as shown in the following screenshot:
At last, it's time to analyze the graph.
A bootchart picture will have a few of different bits of information that are of interest, especially the CPU and disk load graphs at the top.
There is a timeline running from left to right, with processes shown starting (and sometimes stopping) underneath it. The process CPU loads are indicated by the coloration of its process bar. The things to look for are the start and stop times of the different processes, and their CPU load. Long gaps with low load may mean a timeout or some other issue.
Once you have found out which processes are consuming time during the initialization, we can further check these by looking at the system logs with the logcat tool of Android; running them with strace, a profile (of Android), or perf; and reviewing the corresponding source code.
To speed system booting means to reduce the time cost at the system booting stage and also to increase the working frequency of all related devices and meanwhile reduce time cost resources. But, in real practice, the maximal frequency of the devices should be limited to reduce the power cost.
The whole booting procedure of an embedded system includes bootloader startup, kernel decompression and bootup, init
process launching, and system booting. bootchartd
is mainly for optimization of the booting stage after the init
process launches.
To measure the boot time of bootloader or the Linux kernel, we can use the Grabserial tool from http://elinux.org/Grabserial. For more related resources, visit http://www.elinux.org/Boot_Time.