Articles

From “power on” to “gtk GUI usable” as fast as possible

In gtk+, Programming, raspberry pi on November 22, 2015 by oli4444

In my Raspberry Pi + Hifiberry-amp + Pitft project I’ve been looking how to speed up the boot process.

[edit] I updated various parts of this post with suggestions from the comments. [/edit]

The original boot process took around 60 seconds from “power on” until my gtk app was visible and responding. I used the original (Wheezy based) raspbian, with autologon on tty1, and in the .bash_profile I called startx. In /home/pi/.xinitrc I started my application without starting a display manager:
#!/bin/sh
PYTHONIOENCODING=utf_8
export PYTHONIOENCODING
exec /usr/bin/python /home/pi/sqgui2.py

(b.t.w. the PYTHONIOENCODING is there otherwise python will give an exception when calling print with a non-ascii unicode character)

By removing a few services from the init process I removed 10 seconds from the boot process. Still 50 seconds. But further options on Raspbian Wheezy are limited.

Next step was to move to Raspbian Jessie, which has systemd. This gave an unwanted side effect: the hifiberry was detected correctly, but did not produce any sound anymore. Removing a line added for the pitft device_tree=bcm2708-rpi-b-plus.dtb from /boot/config.txt fixed this problem. And the pitft is still working.

In systemd I can start X11 as soon as userspace is running. However this generated an error – the touchscreen device has to be available first. The touchscreen input is in udev configured as /dev/input/touchscreen. I created /etc/systemd/system/xinit-login.service with the following content:
[Unit]
Wants=dev-input-touchscreen.device
After=dev-input-touchscreen.device
DefaultDependencies=false
[Service]
Type=simple
ExecStart=/bin/su pi -l -c /usr/bin/xinit -- VT08
WorkingDirectory=/home/pi/
[Install]
WantedBy=local-fs.target

[edit] with suggestions from the comments in now looks like:

[Unit]
Wants=dev-input-touchscreen.device
After=dev-input-touchscreen.device
DefaultDependencies=false
[Service]
Type=simple
ExecStart=/usr/bin/xinit
WorkingDirectory=/home/pi/
User=pi
Group=Users
Environment=PYTHONIOENCODING=utf_8
[Install]
WantedBy=local-fs.target

and .xinitrc is now a hardlink to the gtk application sqgui.py [/edit]

This makes my xinit session start directly after the touchscreen device is available. This reduced the startup time to 28 seconds. Much better! (b.t.w. I haven’t look if all entries in xinit-login.service are correct, perhaps the contents can be improved).

Systemd has a good tool called systemd-analyze which analyzes the boot process. That way you can easily see which parts take too much time. That helped me to strip off another 2 seconds. An interesting question is how the udev config can be improved to create the touchscreen device earlier in the boot process. Another interesting question is how X11 can be configured to start faster, or how python + gtk3 can be configured to start faster. If you have any suggestions please leave them in the comments.

Next thing was to make the system readonly. I installed busybox-syslogd instead of rsyslogd, since it can do in-memory logging. [edit] I now switched to systemd-journald for in memory logging [/edit]

I analyzed which directories changed after a reboot, and moved those to a tmpfs in-memory filesystem. The /etc/fstab now looks like:
proc /proc proc defaults 0 0
/dev/mmcblk0p1 /boot vfat defaults,ro 0 2
/dev/mmcblk0p2 / ext4 defaults,noatime,ro 0 1
tmpfs /tmp tmpfs defaults,noatime 0 0
tmpfs /var/lock tmpfs defaults,noatime 0 0
tmpfs /var/lib/dhcpcd5 tmpfs defaults,noatime 0 0
tmpfs /var/log tmpfs defaults,noatime 0 0

Possibly this can be optimized with a single tmpfs mount and symlinks to reduce the mount time of 4 tmpfs filesystems.

[edit] did that, they are all symlinks to /tmp now [/edit]

The only remaining issue that I didn’t solve yet is handling of /etc/resolv.conf when moving the setup to a different network. Because /etc/ is readonly the resolv.conf is now fixed for my local wifi network.

[edit] disabling the UART, and moving from the debian networking scripts to systemd-networkd reduced the boot time to 21 seconds! [/edit]

Advertisements

13 Responses to “From “power on” to “gtk GUI usable” as fast as possible”

  1. Why use a syslogd at all? journald is already logging everything in memory.

  2. “prelink -a” may help and sometimes, on flash storage, using btrfs with mount options compress-force,noatime,ssd_spread will shave many seconds from boot (mainly because of compression).
    As for logs, I would remove rsyslog and use only journald in ram-only mode.

  3. If you’re running Debian Jessie, you can drop busybox-syslogd in favor of systemd-journal, which does in-memory logging by default. That should give you a slight performance improvement, as well as reducing your overall memory usage.

    You can also drop the su in favor of User and Group settings in the service.

    If you don’t mind going further off the beaten path, you could get some performance improvements by making the X server use socket activation, so that you can launch X and your application in parallel.

    You could also cut the shell out of your program startup time, and run /home/pi/sqgui2.py directly as a service. Make it depend on the X socket unit, and set the environment variable via Environment= in the service file. In addition to cutting out your own tiny wrapper script, this cuts out Debian’s entire X session machinery, which you don’t need.

  4. One option: make /etc/resolv.conf a symlink to /run/resolv.conf and adjust your dhcp scripts to update it there.

    Another option: use a local caching dnsmasq or something so /etc/resolv.conf is always pointing to 127.0.0.1. (The dnsmasq would need to discover the real LAN DNS server from DHCP, possibly using the same mechanism as in option one: a /run/resolv.conf updated by DHCP scripts.)

  5. Did you disable kernel log output to UART?
    Depending on the implementation this might speed up the kernel initialization, as it might be waiting
    for the slow serial out.

  6. > [edit] disabling the UART, and moving from the debian networking scripts to systemd-networkd reduced the boot time to 21 seconds! [/edit]

    What does “systemd-analyze critical-chain” show now?

    • systemd-analyze critical-chain is a bit useless since I start X11 way before the multi user target has been reached. I’ve currently messed up the system by removing too many services, so I’ve to fix things a bit before I can show what takes most time right now.

  7. Check if your uboot uses the standard 3 second boot delay, that’s another easy optimisation.

  8. I had played with R-Pi using TinyCore distro (PiCore). It allows you to load everything to the memory and only services that are really needed. Headless version boots in ~10 sec on my B+. With X11 it might take longer, though.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: