Thursday 27 March 2008

Boot times (Ubuntu)


I've been playing with bootchart (which I was very impressed by). I thought I should share my findings about boot time.

The biggest improvement came from generating a boot profile (booting once with the "profile" option), so that readahead worked well on my system. I found compiling a custom kernel to work _without an initramfs_ also had a significant effect. But I also found a couple of other tweaks which can save a second or two:

console-setup

ckbcomp is run by setupcon each boot (twice) to generate a keymap for the console, using the X keymap files. This takes a reasonable amount of CPU; it can take almost a second to run during boot. setup-con had already saved the generated keymap - this is done when the console-setup package is installed/reconfigured (or when "/etc/init.d/console-setup restart" is run manually). Unfortunately it only used it if /usr wasn't (yet) mounted. It wasn't immediately obvious how to make it do the right thing, so I just hacked it to always read my saved keymap. (It's a hack because I commented out the code which would regenerate the keymap if the configuration changes)

hwclock

hwclock is invoked twice during the boot process, from hwclockfirst.sh and hwclock.sh. Unfortunately it waits for the next second boundary before it reads/sets the clock. In other words, whenever it's run it will take an average of half a second. Two observations here:

  1. This really ought to be run in parallel with something, rather than blocking the entire boot process. I enabled concurrency=shell in /etc/rc, renumbered the boot script to run in parallel with keyboard-setup, and removed the ".sh" extension which also prevented hwclock.sh from being run in parallel with anything else.
  2. When built for a 64-bit intel system, hwclock does not trust RTC (hardware clock) interrupts. This means it has to _busy wait_ for the next second boundary, which consumes 100% CPU, slowing down the boot and generally looking stupid. I think it should trust the kernel - I patched it to use RTC interrupts and it worked just fine. This should be a low risk change: in the worst case it will time out and continue after waiting 5 seconds for an interrupt.
To be more specific: the kernel should return an error if it does not support RTC interrupts. However, on 64 bit intel systems hwclock does not trust the kernel to do this, so it always has to busy-wait.
 /* Turn on update interrupts (one per second) */
#if defined(__alpha__) || defined(__sparc__) || defined(__x86_64__)
/* Not all alpha kernels reject RTC_UIE_ON, but probably they should. */
rc = -1;
errno = EINVAL;
#else
rc = ioctl(rtc_fd, RTC_UIE_ON, 0);
#endif
if (rc == -1 && (errno == ENOTTY || errno == EINVAL)) {
/* This rtc device doesn't have interrupt functions. This is typical
on an Alpha, where the Hardware Clock interrupts are used by the
kernel for the system clock, so aren't at the user's disposal.
*/
if (debug)
printf(_("%s does not have interrupt functions. "),
rtc_dev_name);
ret = busywait_for_rtc_clock_tick(rtc_fd);