Reducing Linux booting time
Did you ever wonder why embedded devices boots really fast, even though that kind of machine has very limited resources somehow manage to reduce the booting time significantly compared to a desktop or laptop computer?
Sure, basically they are meant to do only one job, so they are a stripped-down version of an OS, almost always Linux based machines. And of course, that OS is built against specific hardware, so it hasn’t to support different machines as common Linux distributions do.
Could we apply the same techniques used in such machines to achieve similar boot times for our computers without losing functionality?
To answer that question, let's quickly review how a Linux machine boot process looks like.
Firmware
Embedded devices usually ship with a very basic firmware that grabs the bootloader from certain entry-point. Computers are far more complicated, they have a firmware nowadays called UEFI that is capable to boot also in legacy mode, emulating the behavior of previous firmware known as BIOSes.
Either UEFI or BIOS, every option that we enable may consume more boot time, especially boot device detection, having enabled the network stack while booting.
Advice: disable unneeded hardware. Disable device autodiscover, for instance you can disable IDE or SATA channels that are not used (automatic detection consumes time)
Bootloader
Current GNU/Linux distros generally use grub. Grub is really slow, in particular when we add background images and change the screen resolution.
Sure, we can change the bootloader for something faster like systemd-boot (previously called gummiboot), but to me is too much of a hassle. I prefer to stick with the “old” grub, which has proven to be very stable and I have more experience with.
By changing the grub default config, we can lower the timeout to 0 and disable the graphical output. With these settings it will load really fast, one could even believe that’s not there.
$ vi /etc/default/grub
GRUB_TIMEOUT=0
GRUB_TERMINAL=console
Initramfs
Next on the boot-chain is loading the initramfs. This is a small (or not so small) image that contains a filesystem to provide the kernel modules that could be needed to boot the kernel: as the filesystem or SATA controller drivers.
On recent Debian versions initramfs is about 22 MB. These are generic images built by maintainers to allow a variety of devices to boot, but from those drivers, we need only a few to allow just one device to boot. We could even get rid of the image and save a considerable amount of time on each boot, but it will require to recompile the kernel without initramfs and having embedded in the kernel all boot related drivers (not as a module).
We can optimize boot times without recompiling the kernel, this just requires a change on initramfs configuration and generate the new image, with dep option we only add loaded modules into the image. With this method, the image got reduced to 6 MB in my case.
By changing the compression algorithm, we can save some time as some algorithms are faster to decompress the data. I’ve found that lz4 is the fastest for my case. It may vary for your CPU. The image is 6.6MB now, but it decompresses a lot faster.
$ sudo vi /etc/initramfs-tools/initramfs.conf
MODULES=dep
COMPRESS=lz4$ sudo update-initramfs -u
Kernel
If we want to change something here we will need to recompile the kernel. I prefer to use my distro precompiled kernel.
But wait! to write to the console the kernel makes a printk call, usually printing to the console is handled by a syscall so it interrupts your program, causing a detriment on the program performance. It is not exactly the case here, but printing to the console is wasting resources.
Hopefully, we can disable (almost all) printing.
By modifying again the default grub configuration, we can get rid of all systemd “Loading service” messages. The kernel will only print one line showing which version is booting and a filesystem check output unless there is some hardware error.
$ vi /etc/default/grub
GRUB_CMDLINE_LINUX_DEFAULT=”quiet loglevel=3"
We can also blacklist present hardware that we don’t use, by creating a file specifying a kernel module blacklist, like this:
$ cat /etc/modprobe.d/dvb.conf
blacklist dvb_usb_rtl28xxu
Init scripts and service units
The next and last step of the boot process is loading SystemV or Systemd for modern distros and on top of that all system services.
I’ll focus on Systemd as is much more frequent for recent GNU/Linux distributions.
Systemd comes with a great tool that eases measuring the boot speed.
$ systemd-analyze
I found that systemd configuration is not very useful for booting faster. Instead, we can disable system services to save much more precious time while booting.
We can use systemd to blame services:
$ systemd-analyze blame
A list will show the services that took longer to start. Start looking from the top and disable the ones that you don’t really need. Like so:
$ sudo systemctl disable NetworkManager-wait-online.service
Remember that you can disable services that you don’t need on every boot, maybe you are a developer and need MySQL or PostgreSQL sometimes. You can disable them and start the database service only when you need it after boot time:
$ sudo systemctl disable mysql.service
In my personal experience, I find docker much more practical rather than having installed all required services natively for developing software, as you can isolate your required services from developer machines and avoid dealing with tons of problems: environment issues, versioning issues and have only one way to build a consistent and reliable environment which can be used for continuous integration but also to ship software to production.
Further optimizations
Make sure you check out the following article to speed up your Linux machine.
Conclusion
With a few small changes on our Linux system, we can reduce booting time by ~700%. That’s seven times faster, depending on your machine. This may vary primarily because of your hard disk latency and transfer speed. M.2 SSD drives are usually a lot faster than SATA drives for example. In my laptop, I managed to boot fully within 4 seconds, and I can see my GDM login prompt in about 2 seconds.