Thread Previous • Date Previous • Date Next • Thread Next |
Our boot time target is 10s, that's from the boot loader to a fully logged in desktop (through auto-login). To reach that time, a budget is given to the identifiable parts of the boot sequence. This week I've been concentrating on the kernel and initramfs, the target budget is 2s. After this time, the root filesystem must be mounted and the init daemon started. Now, there's a strong push from some camps that the initramfs isn't needed; and that we can build storage drivers and filesystem drivers into the kernel. While this is fine for bespoke hardware images, we *do* need the initramfs for the default case because we have to support the widest possible hardware configuration out of the box. Our boot performance targets are for the default case, so they include the initramfs. Note that this support for the widest possible *hardware* configuration is different from support for software configuration. Another win for the initramfs is that it can be configured to support additional software steps such as RAID, LVM, Encrypted root filesystem, Live CD (casper), NFS boot, etc. That being said, such software configuration is an option. We aim to support a user who moves their drive from one hardware configuration to another; but it's ok for a user who moves the software image from a single drive to software RAID, or encrypted root, to need to regenerate their initramfs. So, on with the bootcharts (these are all from an SSD-based Dell Mini 10v). Since we're interested in the kernel and initramfs only, the only time we're interested in is when the init daemon is started. Due to the curious nature of init, and that one init process execs another, this isn't *quite* as simple as looking up that process. Instead look for when the "sreadahead" service is started. max-karmic-20090728-1.png is pretty much a default install of Karmic α3, as you can see the time for the kernel and initramfs is a whopping 4s! Double our budget. You'll notice that the framebuffer driver, fbcon, and usplash are all being started inside the initramfs. What happens if we take these out? Everything added to the initramfs has more than an O(1) time penalty. Firstly there's the simple size of the binaries and files necessary to support things. These increase the size of the initramfs, so increase the loading time for the boot loader to load it into memory. And remember, the boot loader uses BIOS calls to load things, no DMA or speed advantage - every byte hurts. The initramfs is compressed, so every byte added now needs to be decompressed into kernel memory. This doubles the hurt. And then the initramfs needs to be unpacked from the cpio image into the ramfs, now the hurt is trebled! The initramfs has one job to do: mount the root filesystem. Adding anything else results in a significant performance penalty. The reason cited for doing things in the initramfs is that they need to be done very quickly after boot. These boot graphs show the irony of that. usplash started in the initramfs (-1.png) starts 3.2s into the boot. If we strip it all out, and start it first thing after the initramfs is loaded, it can be started 2.5s into the boot! The initramfs scripts spend a lot of wasted time and effort doing things that really don't need to be done: In the "framebuffer" init-top script: modprobe -q intel_agp modprobe -q i915 modprobe -q ${FB} ${OPTS} The initramfs is force-loading the framebuffer console, and framebuffer drivers. It also spends quite a bit of effort figuring out *which* framebuffer it might want to load. (The possible value of FB is specified on the command-line, or matroxfb_base) Ironically, intel_agp, i915 and matroxfb_base (along with the other framebuffer drivers I randomly checked) *ALL* already specify PCI modalias rules in the modules. In other words, they will be automatically loaded by udev *anyway* So why are we spending the effort to figure it out when it'll happen by magic by just deleting the script and leaving the module there. Another reason to not put things like this into the initramfs is that the initramfs is *optional*. If you're hardcoding anything, that should be setting off alarm bells. In this case, consider the following line in the "kernelextras" hook: force_load fbcon and in the "framebuffer" init-top script: modprobe -q fbcon What happens if you don't boot with an initramfs? What loads fbcon? It turns out that *nothing* does! Force-loading fbcon like this in the initramfs actually hides a bug (that it's not loaded otherwise) I'd also removed all the console and keymap related scripts when removing usplash. The original justification for some of these was that it was impossible to set the console font while usplash was running. In other words, putting usplash in the initramfs introduced yet more bugs, which required even more expensive workarounds! You might need your keymap to enter the passphrase, but that's an *optional* feature. Those who enabled encrypted root should automatically get these hooks and scripts, those who don't do not need them. Continuing in the vein of hardcoding things, if you now read the thermal hook, alarm bells should be going off. I'm partly to blame for this one as well. We force-load the fan and thermal modules. Who will load them if we skip the initramfs? Turns out, udev does. So if udev automatically loads them anyway, *WHY* do we force-load them? (Also worth pointing out that they're built in to the Ubuntu kernel, not modules!) Finally we have a bunch of things in the initramfs like dmsetup, fuse and ntfs-3g intended to support edge-case filesystems. Again, this is a software change; it's *ok* to require people to update their initramfs if they change to or from these. Thus they should only go into the initramfs if they're going to be used! (And in the case of fuse, who loads the fuse module if the initramfs is skipped) What's the result of removing all this stuff? max-karmic-20090729-4.png Down from 4s to 2.5s! We're only 0.5s shy of the budget, with no significant loss of functionality in the default install. So what about that last 0.5s? Well, scripts/local needs a bit of a study. There's a lot of stuff in there to figure out the root filesystem type, and loop waiting for it. But we're using udev, which already probes for all this stuff *including* UUIDs and LABELs. Why don't we just ship a udev rule that matches on the root filesystem, and then continues the init script to mount it? Another thing to look at is max-karmic-20090729-4.svg - this is the kernel initcall boot graph. As you can see, the populate_rootfs() function takes up 0.4s on its own - if we made this an asynchronous call it could happen in the background while the rest of the kernel initialises. (I've tried this and keep getting thwarted so far, but am working on it) I'd also from a pure-kernel POV say that isapnp_init could probably be an async call as well. There's also still the question of everything that initramfs-tools drags in by itself (many modules, etc.) without hooks. I think from an initramfs POV what I'd like to see/do is: - everything should be a hook, mkinitramfs without a hook should generate a near-empty initramfs - hooks should be trivially configurable so that they (*and their accompanying scripts*) are only included if the software configuration requires it I'm also looking at dracut as an alternative to initramfs-tools, in case it will be better suited to this kind of bare approach. Scott -- Scott James Remnant scott@xxxxxxxxxxxxx
Attachment:
max-karmic-20090728-1.png
Description: PNG image
Attachment:
max-karmic-20090729-4.png
Description: PNG image
Attachment:
max-karmic-20090729-4.svg
Description: image/svg
Attachment:
signature.asc
Description: This is a digitally signed message part
Thread Previous • Date Previous • Date Next • Thread Next |