Changes for upcoming openSUSE
As a result of my previous 2 second post I have submitted few changes to openSUSE to be included in a next release.
purge-kernels.service
patch has been accepted by our brave mkinitrd package maintainer- requested a split of mkinitrd setup script from
splashy
package, so users can freely remove the initrd integration without breaking resume et al - I opened feature 313851 to make NM the default network tool at least for laptops, because this expects a little more changes than add a package to laptop pattern
Run NetworkManager on demand
That is very uncommon user-case for *nix machines, but makes a perfect sense for consumer devices. My Amazon Kindle or today’s smartphone or tables works in the same way – device starts without a network connection and there’s a button or magic tap enabling it. On my laptop I already have such button – it is the Fn+F2 with a antenna symbol printed. This is the rfkill button turns my wlan card on and off.
So what I want is once I turn wifi on, NetworkManager should start and work. With systemd and it’s udev integration this is so simple, that I was not able to find a good howto for it. So here we are with a small howto for udev/systemd newbiew like me.
We need to know a sysfs name of wlan0 – simple find /sys/ -name 'wlan0'
will say us all we need. Then udevadm info
will tell you more
udevadm info --path=/sys/class/net/wlan0 --attribute-walk | less ... looking at device '/devices/pci0000:00/0000:00:1c.2/0000:01:00.0/net/wlan0': KERNEL=="wlan0" SUBSYSTEM=="net" DRIVER==""
That is all you need to know how to write a rule will match for all wlan cards.
# cat /etc/udev/rules.d/95-start-nm-on-wlan.rules SUBSYSTEM=="net", NAME=="wlan?", TAG+="systemd", ACTION=="add", ENV{SYSTEMD_WANTS}="NetworkManager.service"
To explain it – SUBSYSTEM
and NAME
are taken from previous output and means that following rule matches for all devices in net subsystem named wlan-something
. We should append tag systemd, because systemd
sees tagged devices only. The ACTION=="add"
says the rule will be evaluated only in case device will be added and the last part says to systemd
which service should be started.
In case you will want to stop NM, the
SUBSYSTEM=="net", NAME=="wlan?", TAG+="systemd", ACTION=="remove", ENV{SYSTEMD_WANTS}="NetworkManager-stop.service"
# cat /etc/systemd/system/NetworkManager-stop.service [Unit] Description=Stops NetworkManager Conflicts=NetworkManager.service [Service] ExecStart=/bin/true
WLAN cards
For onboard wlan cards following thing won’t work as they appear in a tree from early phase. Unfortunately I’ve found only one way how kernel exports the fact cable is plugged in and that’s changed /sys/class/net/eth0/carrier
. But inotify does not work with a quantum-like fs like sysfs is. The trouble is values appears in time of read, but inotify react on writes, which never appear.
How much the removal of getting IP address from boot saved the time?
# systemd-analyze Startup finished in 2719ms (kernel) + 4333ms (userspace) = 7052ms
which is about half of second.
Too much mounts in a parallel
The one thing surprised me was a long time until trivial mounts like debugfs were finished. The reason is that systemd
(at least 44, recent version use generator+ .mount
units) behaves differently to .mount
units and things in /etc/fstab
. In the first case, it executes the /bin/mount
. Which means a lot of ld, stats, mmap, and the big delay of the system start.
So move things to fstab, or disable the systemd mount unit (I did that for sys-kernel-debug.mount
and sys-kernel-security.mount
). I already masked the remount-rootfs.mount, which calls /bin/mount -o remount /
< only. That seems to me like a barrier for other mount units – iow this will be done as a last one. But who cares with a fast boot we have?
Way more changes
Then the systemd-modules-load.service delay a boot as it block sysinit.service, when basic boot ends. I read strace carefully, but it only load microcode_ctl module, but that took few seconds to be done. Thus I gently masked it.
The next change is backport from Factory package – this reduce the delay caused by all those tty devices to appear. Fortunately this will be part of next openSUSE as it is an upstream patch.
And as a last thing I wrote a simple xdm.service, instead of a big xdm init script. It will definitely need more love, but for me just works 🙂
cat /etc/systemd/system/xdm.service [Unit] Description=X Display Manager After=dbus.socket [Service] Type=simple ExecStart=/usr/bin/xdm -nodaemon Restart=always [Install] WantedBy=graphical.target
Voilà!
#systemd-analyze Startup finished in 2698ms (kernel) + 1513ms (userspace) = 4212ms
Using dracut
Because our brave systemd maintainer, Fréderic Crozat, chooses dracut as his hackweek project, I was curious if dracut can make some gain for me. I installed dracut and rebuilt and installed hardlink from his branches and try to investigate it. I would say the biggest advantage over mkinitrd is that dracut is configurable from command line. This is in a contrast with mkinitrd, where you have mostly no way how to exclude something – at least I did not find anything.
As Fréderic also pointed me, there is a --hostonly
switch, which include only things needed for boot of current machine only. For instance dracut
module kernel-modules
will pull only things needed to mount rootfs
(and if usrmount
is included, then it will add things for /usr
as well). Then I have excluded at least everything I can to have a working initramfs via -o
, --nofsck
and --strip
. And that is the resulting time
# systemd-analyze Startup finished in 726ms (kernel) + 1609ms (initramfs) + 1581ms (userspace) = 3917ms
Disabling way more things
As we are now versed in a looking at diagrams, there are still few ms we can save, even those changes are not sane ;-). The first one follows the NetworkManager.service
– now sshd.service
delays the boot a lot, because it systemd-update-utmp-level.service
waits on it’s finish. So let’s start it on demand
# cat /etc/udev/rules.d/95-start-nm-on-wlan.rules SUBSYSTEM=="net", NAME=="wlan?", TAG+="systemd", ACTION=="add", ENV{SYSTEMD_WANTS}="NetworkManager.service sshd.service"
and disable it. Then mask all few remaining things – systemd-login.service
, systemd-remount-api-vfs.service
, systemd-user-session.service
and rc-local.service
. But only in case you are pretty sure what you are doing, because you might loose an important functionality, especially if you use a DE expected such things.
And that is the last time I will post
# systemd-analyze Startup finished in 726ms (kernel) + 1502ms (initramfs) + 1112ms (userspace) = 3341ms
With a kernel with SATA+ext support builtin, I would reach the two second goal – 1839ms. Of course on a system, which functionality was extremely cut down, but my goal was to boot as fast as possible. In reality, hunting of ms does not makes your feeling better a lot (until you will type systemd-analyze
, of course)
This is the diagram of the really fast boot
Both comments and pings are currently closed.
way cool. This inspired me to go through my own laptop bootup list as well. A few notes:
– systemd-analyze doesn’t install on openSUSE 12.2 rc2, complains about dependencies
– making initrd smaller is really hard. I looked in it – darn, there’s some weird stuff in there. Yes, there are splashy and plymouth. But also libxml2 (1.4 mb) libgio (1,.3 mb), LibX11 (1.2 mb), libcairo (1 mb) and things like sqlite, libcups (!?!?!) and much more. why is that there?!?!? My kernel boot time is often 7 seconds – on a total of 10… 🙁
– I greatly dislike that removing some things I really don’t need (lvm2, mdadm, some crypt stuff) removes half my system – at least, most of YaST, including stuff like the bootloader configuration. That should really be cleaned up…
– I now have this beauty slowing down my boot: 6881ms laptop-mode.service — wtf?!? Seems the culprit there is re-mounting my filesystems with relatime (which I’ve already set to noatime anyway). I solved this in the laptop-mode config, disabling its control over my drives.
Hallo Jos, if you will be able to bug it, it will be great and do not forget to put the bnc numbers there.
very well done!
Could you also provide info on how to mask services from systemd?
thanks!
I just found that the 3 different available syslog services (one can easily install via yast) make a huge difference of up to 4 seconds. The best is syslog-ng:
syslogd
5876ms nfsserver.service
2129ms syslog.service
2112ms systemd-logind.service
754ms md.service
504ms SuSEfirewall2_setup.service
142ms SuSEfirewall2_init.service 5,6
rsyslog
4826ms nfsserver.service
2144ms syslog.service
2129ms systemd-logind.service
726ms md.service
492ms SuSEfirewall2_setup.service
169ms SuSEfirewall2_init.service
syslog-ng
4915ms nfsserver.service
728ms md.service
494ms SuSEfirewall2_setup.service
167ms syslog.service
165ms SuSEfirewall2_init.service
165ms systemd-logind.service
syslog-ng (second restart)
5874ms nfsserver.service
737ms md.service
495ms SuSEfirewall2_setup.service
166ms SuSEfirewall2_init.service
156ms syslog.service
142ms systemd-logind.service
Now I have: 3641ms (kernel) + 10314ms (userspace) = 13956ms
I’m trying for a while to cut the boot time. What I think it needs to be done is to start the minimal services that needs to get to the login (like you did). The rest of the services like networking and so on can be started in background after with a low (maybe distinct) priority and maybe only if they are needed… And not work with a ‘cut down system’.