Please note that User Registration has been temporarily disabled due to a recent increase in automated registrations. If anyone needs an account, please request one here: RequestAccount. Thanks for your patience!--Wmat (talk)
Please email User:Wmat if you experience any issues with the Request Account form.

Improving Android Boot Time Outline

From eLinux.org
Revision as of 18:14, 28 July 2010 by Tim Bird (Talk | contribs)

Jump to: navigation, search

Here is the outline for my talk:

  • Title

  • Outline
    • Android boot overview
    • Measuring boot times
    • Problem areas
      • Some gory details
    • Ideas for improvements

  • Android boot overview
    • bootloader
    • kernel
    • init
    • zygote
      • building preload heap
      • start package manager
    • service manager
      • start services

  • measuring bootup time
    • systems measured: adp1, n1, evm
      • adp1 with donut
      • n1 with eclair
      • evm with eclair
        • NOTE: used nfs root filesystem (file IO timings might be bogus)

  • Tools for measuring and tracing boot time
    • stopwatch
    • grabserial
    • printk times
    • bootchart
    • strace
    • logcat
    • method tracer*
    • ftrace*

  • stopwatch

  • grabserial

  • printk times

  • bootchart

  • strace

  • logcat
    • extra instrumentation for preloading classes
    • PARSE_CHATTY flag for package scanning
    • mention my own tool 'logdelta'

  • method tracer*
    • method traces is built in to
  • ftrace*
    • I could have really used ftrace for some things
    • (especially to see page faults intermingled with system calls)
    • kernel version for my primary development board (2.6.29) didn't support it
    • should be usable in future versions of Android (Froyo is at 2.6.32)
    • NOTE: ARM is missing function graph tracing - see Ftrace Function Graph ARM

  • Problem Areas
    • First, a bootchart for EVM board
    • bootloader init
    • kernel init
    • zygote class preloading
    • package scanning
    • service initialization

  • bootloader init
    • outside scope of this talk
    • didn't measure commercial bootloader, only development one (U-boot)

  • kernel init
    • is mostly the usual suspects
    • (initcall_debug results)
    • USB

  • zygote class preloading
    • zygote pre-loads just under 2000 classes, and instantiates them in its heap
    • controlled by file:

  • package manager package scan
    • EVERY package is scanned at boot time
    • Very deep nesting, with abstraction
    • Not sure of exact set of purposes
      • But I see validation of certificates, permissions, capabilities and dependencies, etc.
    • Very difficult to trace
      • It bounces between java, c++ and kernel
      • And uses mmaped files (meaning accesses cause page faults)!!
        • So it's not even using syscalls for reading the data

  • Package scan call tree

[put call tree here]


  • parseZipArchive()
    • evil routine that builds an in-memory data structure for accessing a package file
    • scans the entire package, checking the content headers
      • caused read of almost entire package
      • touches every page in mmaped file, even if a sub-file in the archive won't be

read later

      • e.g. entire package is scanned, when only the AndroidManifest.xml file is requested

  • new Resources()
    • reads all resources in a file
    • is this really necessary?

  • Ideas for Enhancements
    • First, a side note on toothpaste..
    • kernel speedups
    • optimize package scan
    • optimize class preloading
    • miscellaneous optimizations
    • sreadahead??

  • Toothpaste
    • Problem with optimizations are that reduction in one area causes some other problem (either in speed or size) in some other area
    • i.e. when you squeeze the tube of toothpaste, it just moves somewhere else, and doesn't actually come out the end
    • This is demonstrated with class preloading and page cache effects
      • I tried to improve things, but the I/O delays just moved somewhere else in the system, sometimes making things worse
      • e.g. AutoText - eliminated and gained 4 seconds during class preloading, but /system/frameworks/frameworks-res.apk was just loaded later in the boot
      • e.g. Contacts.apk - moved AndroidManifest.xml to its own package, to avoid reading the entire (1.6M) package to read this one file, but next reference to contents of Contacts.apk caused the index rebuild again (costing the entire page cache load)

  • kernel speedups
    • outside the scope of this presentation
    • see http://elinux.org/Boot_Time
    • should really be able to get kernel up in 1 second
      • modulo network delays

  • Optimize Class Preloading
    • Preload less, and let apps pay penalty for shared class and resource use
      • move some classes to services, and have preloaded class be an accessor stub
      • figure out how to share heap back with zygote
      • This needs a lot of analysis - Google Android devs know that the whole process of selecting what classes to preload is a black art
    • Thread the heap construction
      • There is some evidence that class preloading has I/O waits, and would benefit from threading
      • Don't know if this is possible
      • NOTE: all threads need to terminate before spawning Android apps
    • Use pre-constructed dalvik heap
      • (more on next slide)

  • Use pre-constructed dalvik heap
    • Basic operation:
      • Snapshot the heap at end of preloading
      • Check for modifications to any class in preload list, and do regular preload
      • Otherwise, load pre-constructed heap
    • Issues:
      • Don't know if this is possible
        • Need to find parts of heap that are identical on each boot
        • Probably need separate "always-the-same" and "may-change" classes
      • Needs careful analysis, and knowledge of each class

  • Optimize Package Scan
    • Most definitely! should be first thing attacked
    • Need to continue analysis
      • Most likely, should switch to a compressed flash file system

  • Miscellaneous
    • zoneinfo inefficiences
      • discovered with strace
      • routines that do read syscall for 40 bytes, 8 bytes, 8 bytes (hundreds of times)
        • no buffering at user level, sloppy loop coding
      • linear scan of timezone file
        • for a file not present!!
      • probably only a few hundred milliseconds, but worth changing

  • Sreadahead??
    • could use sreadahead to pre-fill page cache
    • however, this just masks bad behavior
      • Contacts.apk (half of 1.6M) is read 4 times! during boot
      • filling page cache makes reads after first one fast, but it would be better to avoid (most of) the reads altogether
        • better to just optimize or eliminate parseZipArchive()
    • sreadahead should be used dead last (after all other enhancements)

  • Conclusions
    • Sorry - no speedups yet
    • But, have a good foundation and set of tools for improving things going forward
    • Premature optimization is the root of all evil
      • Be very careful of optimizing wasteful operations
      • Better to improve or eliminate the operations, than hide the wasteful operations with caching

  • Observations
    • Beware of systemic problems
      • Package management basically builds a persistent container and compression architecture in user space
      • Except, it rebuilds the in-core data structure for it over and over
      • Just use the file system, for heaven's sake!