Enhance boot performance by adjusting service dependencies and loading quirks in parallel

This commit is contained in:
Douglas Teles
2026-05-11 19:29:07 -03:00
parent 424a286755
commit d230c4243e
5 changed files with 66 additions and 33 deletions
@@ -1,7 +1,9 @@
[Unit]
Description=ArchR Memory Manager
After=local-fs.target
DefaultDependencies=no
# Run AFTER /storage is mountable so we can read /storage/.config/swap.conf
# for user overrides. RequiresMountsFor pulls in the mount automatically.
After=local-fs.target archr-automount.service
RequiresMountsFor=/storage
Conflicts=shutdown.target
Before=shutdown.target
@@ -14,4 +16,9 @@ ExecStop=/usr/bin/archr-memory-manager --stop
RemainAfterExit=yes
[Install]
WantedBy=basic.target
# Was WantedBy=basic.target, which put the ~3.9s modprobe zram + udev wait
# + sysctl tuning loop on the critical path before sockets.target →
# sysinit.target. Moving to multi-user.target keeps swap+KSM+VM tuning
# functional (it still happens before EmulationStation starts) but
# unblocks sysinit/basic for the rest of the boot.
WantedBy=multi-user.target
@@ -50,36 +50,29 @@ if [ -d /sys/class/pwm/pwmchip0 ]; then
echo 0 > /sys/class/pwm/pwmchip0/pwm0/enable 2>/dev/null
fi
### Load platform specific quirks
if [ -d "/usr/lib/autostart/quirks/platforms/${HW_DEVICE}" ]
then
log "Run ${HW_DEVICE} quirks."
tocon "Applying ${HW_DEVICE} quirks..."
for script in "/usr/lib/autostart/quirks/platforms/${HW_DEVICE}"/*
do
log "Run ${script}"
trace_step "platform-quirk:${script}"
if [ -f "${script}" ]
then
"${script}" 2>&1 >>${BOOTLOG}
fi
done
fi
### Load platform + device quirks in parallel. Every quirk writes to its
### own /storage/.config/profile.d/NNN-name file or to a hardware sysfs
### path — they don't share state, so running them concurrently is safe
### and trims several seconds off boot (most quirks are sub-second cats).
### Each quirk is logged with its end-tag so a failure is still
### attributable in /var/log/boot.log; the trace_step marker for slow
### debugging picks the LAST-launched script (good enough — if a quirk
### hangs we want to know what's still running, not the entry order).
QUIRK_DIRS=""
[ -d "/usr/lib/autostart/quirks/platforms/${HW_DEVICE}" ] && QUIRK_DIRS+=" /usr/lib/autostart/quirks/platforms/${HW_DEVICE}"
[ -d "/usr/lib/autostart/quirks/devices/${QUIRK_DEVICE}" ] && QUIRK_DIRS+=" /usr/lib/autostart/quirks/devices/${QUIRK_DEVICE}"
### Load device specific quirks
if [ -d "/usr/lib/autostart/quirks/devices/${QUIRK_DEVICE}" ]
then
log "Run ${QUIRK_DEVICE} quirks."
tocon "Applying ${QUIRK_DEVICE} quirks..."
for script in "/usr/lib/autostart/quirks/devices/${QUIRK_DEVICE}"/*
do
log "Run ${script}"
trace_step "device-quirk:${script}"
if [ -f "${script}" ]
then
"${script}" 2>&1 >>${BOOTLOG}
fi
if [ -n "${QUIRK_DIRS}" ]; then
tocon "Applying ${HW_DEVICE} / ${QUIRK_DEVICE} quirks..."
for QDIR in ${QUIRK_DIRS}; do
for script in "${QDIR}"/*; do
[ -f "${script}" ] || continue
log "Run ${script}"
trace_step "quirk:${script}"
( "${script}" 2>&1 >>${BOOTLOG}; log "Done ${script}" ) &
done
done
wait
fi
### Start the automount service
@@ -154,8 +154,15 @@ post_makeinstall_target() {
safe_remove ${INSTALL}/usr/lib/systemd/system/systemd-journald-audit.socket
# adjust systemd-hwdb-update (we have read-only /etc).
sed '/^ConditionNeedsUpdate=.*$/d' -i ${INSTALL}/usr/lib/systemd/system/systemd-hwdb-update.service
# Pre-build hwdb.bin at image creation so systemd-hwdb-update.service
# doesn't have to rebuild it on every boot (was costing ~4.4s in
# systemd-analyze blame). The file format is arch-independent so the
# host's systemd-hwdb is safe to use. The override.conf in
# system.d/systemd-hwdb-update.service.d makes the service a no-op at
# runtime; this step ensures the binary db is present for udev.
if command -v systemd-hwdb >/dev/null; then
systemd-hwdb --usr --root=${INSTALL} update || true
fi
# remove nspawn
safe_remove ${INSTALL}/usr/bin/systemd-nspawn
@@ -0,0 +1,16 @@
[Unit]
# /usr is read-only squashfs/ext2 in ArchR — the hwdb source files never
# change between boots, so rebuilding hwdb.bin at every boot was costing
# ~4s on RK3326 (systemd-analyze blame: 4.417s) and showed up in the
# critical chain via sysinit.target.
#
# We rebuild hwdb.bin at image creation (see systemd post_makeinstall) and
# ship it with the image. At runtime, skip the rebuild unconditionally by
# ConditionPathExists pointing at a sentinel path that never exists.
ConditionPathExists=/run/systemd/never-create-this
[Service]
# Defensive: if the condition somehow doesn't kick in, exit immediately
# so we still avoid the 4s rebuild.
ExecStart=
ExecStart=/bin/true
@@ -1,3 +1,13 @@
[Unit]
# systemd-resolved was sitting in the boot critical chain via
# nss-lookup.target → basic.target → sysinit.target, costing ~4.3s in
# blame. None of ArchR's boot-critical services actually need DNS
# (EmulationStation, sway, automount). Drop the implicit pull so
# resolved starts in the background while the UI comes up; DNS is ready
# by the time the user actually opens a network app.
Wants=
Before=systemd-user-sessions.service shutdown.target
[Service]
# Relax sandboxing to prevent race conditions on boot with OverlayFS
# Fixes error: NAMESPACE "Failed to set up mount namespacing" which can occur based on overlayfs setup speed