Tweaking for a faster boot time

From ArchWiki
Revision as of 23:27, 24 January 2010 by Duologic (Talk | contribs) (Out of date warning)

Jump to: navigation, search

Merge-arrows-2.pngThis article or section is a candidate for merging with Speedup boot.Merge-arrows-2.png

Notes: Speedup boot (Discuss in Talk:Tweaking for a faster boot time#)

Summary

This is the result of 2 days of tweaking for a faster boot time.

Why: just because you can, for other people to see what is possible with Arch Linux.

See the forumtopic, the scripts may differ from the one in the topic because of further tweaking.

Grub to agetty in 13s (coming from 24s) on a Dell Inspiron 1525 (Core2Duo T5450 1,66 Ghz) (bootcharts in same forumtopic)

Warning: the scripts below may or may not be out of date.

/etc/inittab

This will not increase the speed that much, but every little bit helps.

#
# /etc/inittab
#

# Boot to console
id:3:initdefault:

# Use once instead of wait
rc::sysinit:/etc/rc.sysinit
rs:S1:once:/etc/rc.single
rm:2345:once:/etc/rc.multi
rh:06:once:/etc/rc.shutdown
su:S:once:/sbin/sulogin -p

#Start lesser agetty's and login from agetty
c1:2345:respawn:/sbin/agetty -8 38400 vc/1 linux
c2:2345:respawn:/sbin/agetty -8 38400 vc/2 linux

ca::ctrlaltdel:/sbin/shutdown -t3 -r now

# End of file

Alternatively instead of using agetty, use fgetty which is smaller and fast by replacing:

c1:2345:respawn:/sbin/agetty -8 38400 vc/1 linux

with

1:23:respawn:/sbin/fgetty tty1

/etc/mkinitcpio.conf

This didn't really speed up my boot, but on some systems it does.

This didn't work for me on Kernel 2.6.27 and needed to put Udev back in HOOKS, never tried to figure out why it didn't work. I tried again when installing kernel 2.6.28 and that did work. If you use a USB keyboard, add 'usbinput' in HOOKS

My boot device was a separate partion on a SATA drive formatted as ext3. I needed to enable AHCI in my BIOS, before this it used a ATA module.

#
# /etc/mkinitcpio
#

#Load necessary modules to mount boot device
MODULES="ahci sd-mod ext3"
BINARIES=""
FILES=""
HOOKS="base"

# End of file

/etc/rc.sysinit

Here I had the most work, and gained the most speed.

I took out the stuff I didn't use: LVM, RAID and Encrypted devices.

Including default behavior for the clock, LOCALE, KEYMAP and HOSTNAME directly into this file, so it doesn't have to load it from #/etc/rc.conf.

I've added a lot of ampersands to send these processes to the background. Watch out with what you send to the background, because otherwise later commands that depend on the backgrounded process might be called before the process is running. The first time '/sbin/hwclock' and '/sbin/udevadm settled' are called are examples of that.

Also I've put '/sbin/udevadm trigger &' earlier and in background, so it had the time to load until '/sbin/udevadm settled' is called.

Putting in 'status "Updating Module Dependencies" /sbin/depmod -A' in comment requires you to run it when you install new modules. It is not a required for boot, so I don't know what it does there in first time.

#!/bin/bash
#
# /etc/rc.sysinit
#

. /etc/rc.conf
. /etc/rc.d/functions

echo " "
printhl "Arch Linux\n"
printhl "${C_H2}http://www.archlinux.org"
printhl "Copyright 2002-2007 Judd Vinet"
printhl "Copyright 2007-2008 Aaron Griffin"
printhl "Distributed under the GNU General Public License (GPL)"
printsep

# mount /proc, /sys and our RAM /dev
/bin/mount -n -t ramfs none /dev
/bin/mount -n -t proc none /proc
/bin/mount -n -t sysfs none /sys

# Create our default nodes that minilogd may need
/bin/mknod /dev/null c 1 3
/bin/mknod /dev/zero c 1 5
/bin/mknod /dev/console c 5 1

# More initial /dev setup that udev doesn't do
/bin/ln -snf /proc/self/fd /dev/fd
/bin/ln -snf /proc/self/fd/0 /dev/stdin
/bin/ln -snf /proc/self/fd/1 /dev/stdout
/bin/ln -snf /proc/self/fd/2 /dev/stderr
/bin/ln -snf /proc/kcore /dev/core
/bin/mkdir /dev/pts
/bin/mkdir /dev/shm

# start up our mini logger until syslog takes over
/sbin/minilogd

# anything more serious than KERN_WARNING goes to the console
# 'verbose' cmdline parameter enables more messages
if /bin/grep -q " verbose" /proc/cmdline; then
        /bin/dmesg -n 8
else
        /bin/dmesg -n 3
fi

# enable rtc access
/sbin/modprobe rtc-cmos >/dev/null 2>&1
RTC_MAJOR=$(/bin/grep -w rtc /proc/devices 2>/dev/null); RTC_MAJOR="${RTC_MAJOR%% *}"
if [ -n "$RTC_MAJOR" ]; then
        /bin/mkdir /dev/misc/
        /bin/mknod /dev/misc/rtc0 c $RTC_MAJOR 0
        /bin/ln -s /dev/misc/rtc0 /dev/rtc
fi

# Set clock early to fix some bugs with filesystem checks
# Clock is set again later to match rc.conf
if [ -f /etc/localtime ]; then
        /sbin/hwclock --hctosys --localtime --directisa --noadjfile
fi

echo > /proc/sys/kernel/hotplug

if [ -x /sbin/udevadm -a -d /sys/block ]; then
        # We have udev and /sys appears to be mounted, use UDev
        stat_busy "Starting UDev Daemon"
        /sbin/udevd --daemon
    /sbin/udevadm trigger &
    udevstart="$(/bin/date +%s%0N)"
        stat_done
else
        # Static /dev, our last resort
        status "Using static /dev filesystem" true
fi

# Load modules from the MODULES array defined in rc.conf
if ! [ "$load_modules" = "off" ]; then
        if [ -f /proc/modules ]; then
                stat_busy "Loading Modules"
                for mod in "${MODULES[@]}"; do
                        if [ "$mod" = "${mod#!}" ]; then
                                /sbin/modprobe $mod &
                        fi
                done
                stat_done
        fi
        if [ -d /proc/acpi ]; then
                stat_busy "Loading standard ACPI modules"
                ACPI_MODULES="ac battery button fan processor thermal"
                k="$(echo $BLACKLIST ${MOD_BLACKLIST[@]} | /bin/sed 's|-|_|g')"
                j="$(echo ${MODULES[@]} | /bin/sed 's|-|_|g')"
                #add disabled MODULES (!) to blacklist - much requested feature
                for m in ${j}; do
                        [ "$m" != "${m#!}" ] && k="${k} ${m#!}"
                done
                # add disablemodules= from commandline to blacklist
                k="${k} $(echo ${disablemodules} | /bin/sed 's|-|_|g' | /bin/sed 's|,| |g')"
                for n in ${ACPI_MODULES}; do
                        if ! echo ${k} | /bin/grep "\<$n\>" 2>&1 >/dev/null; then
                                /sbin/modprobe $n > /dev/null 2>&1 &
                        fi
                done
                stat_done
        fi
fi

# run udev uevents
if /bin/pidof -o %PPID /sbin/udevd >/dev/null; then
        stat_busy "Loading UDev uevents"
        /sbin/udevadm settle
        stat_done
        udevend="$(/bin/date +%s%0N)"
        printhl "   UDev uevent processing time: $((($udevend-$udevstart)/1000000))ms"
fi

# bring up the loopback interface
if [ -d /sys/class/net/lo ]; then
        stat_busy "Bringing up loopback interface"
        /sbin/ifconfig lo 127.0.0.1 up &
        if [ $? -ne 0 ]; then
                stat_fail
        else
                stat_done
        fi
fi

status "Mounting Root Read-only" /bin/mount -n -o remount,ro /

FORCEFSCK=
[ -f /forcefsck ] && FORCEFSCK="-- -f"
NETFS="nonfs,nonfs4,nosmbfs,nocifs,nocodafs,noncpfs,nosysfs,noshfs,nofuse,nofuseblk"

if [ -x /sbin/fsck ]; then
        stat_busy "Checking Filesystems"
        if /bin/grep -qw quiet /proc/cmdline; then
                /sbin/fsck -A -T -C -a -t $NETFS $FORCEFSCK >/dev/null 2>&1
        else
                /sbin/fsck -A -T -C -a -t $NETFS $FORCEFSCK 2>/dev/null
        fi
        fsckret=$?
        if [ ${fsckret} -gt 1 ]; then
                stat_fail
                if [ $((${fsckret}&2)) -eq 2 ]; then
                        echo
                        echo "********************** REBOOT REQUIRED *********************"
                        echo "*                                                          *"
                        echo "* The system will be rebooted automatically in 15 seconds. *"
                        echo "*                                                          *"
                        echo "************************************************************"
                        echo
                        /bin/sleep 15
                else
                        echo
                        echo "*****************  FILESYSTEM CHECK FAILED  ****************"
                        echo "*                                                          *"
                        echo "*  Please repair manually and reboot. Note that the root   *"
                        echo "*  file system is currently mounted read-only. To remount  *"
                        echo "*  it read-write type: mount -n -o remount,rw /            *"
                        echo "*  When you exit the maintenance shell the system will     *"
                        echo "*  reboot automatically.                                   *"
                        echo "*                                                          *"
                        echo "************************************************************"
                        echo
                        /sbin/sulogin -p
                fi
                echo "Automatic reboot in progress..."
                /bin/umount -a
                /bin/mount -n -o remount,ro /
                /sbin/reboot -f
                exit 0
        fi
        stat_done
fi

stat_busy "Mounting Local Filesystems"
/bin/mount -n -o remount,rw /
/bin/rm -f /etc/mtab*
# make sure / gets written to /etc/mtab
/bin/mount -o remount,rw /
# Write /proc, /sys and /dev to /etc/mtab
if [ -e /proc/mounts ]; then
        /bin/grep -e "/proc " -e "/sys " -e "/dev " /proc/mounts >> /etc/mtab
fi
# now mount all the local filesystems
/bin/mount -a -t $NETFS
stat_done

status "Activating Swap" /sbin/swapon -a &

stat_busy "Configuring System Clock"
if [ ! -f /var/lib/hwclock/adjtime ]; then
        echo "0.0 0 0.0" > /var/lib/hwclock/adjtime &
fi

/bin/rm -f /etc/localtime
/bin/cp "/usr/share/zoneinfo/Europe/Brussels" /etc/localtime
/sbin/hwclock --hctosys --localtime --directisa
stat_done

if [ -f /var/run/random-seed ]; then
        stat_busy "Initializing Random Seed"
        /bin/cat /var/run/random-seed >/dev/urandom &
        stat_done
fi

stat_busy "Removing Leftover Files"
/bin/rm -f /etc/nologin &>/dev/null &
/bin/rm -f /etc/shutdownpid &>/dev/null &
/bin/rm -f /var/lock/* &>/dev/null &
/bin/rm -rf /tmp/* /tmp/.* &>/dev/null &
/bin/rm -f /forcefsck &>/dev/null &
(cd /var/run && /usr/bin/find . ! -type d -exec /bin/rm -f -- {} \; )
: > /var/run/utmp &
# Keep {x,k,g}dm happy with xorg
/bin/mkdir /tmp/.ICE-unix && /bin/chmod 1777 /tmp/.ICE-unix
/bin/mkdir /tmp/.X11-unix && /bin/chmod 1777 /tmp/.X11-unix
stat_done

#status "Updating Shared Library Links" /sbin/ldconfig
#status "Updating Module Dependencies" /sbin/depmod -A &

status "Setting Hostname: Pinguin" /bin/hostname "Pinguin" &

# Flush old locale settings
: >/etc/profile.d/locale.sh
/bin/chmod 755 /etc/profile.d/locale.sh
# Set user defined locale
[ -z "$LOCALE" ] && LOCALE="en_US"
stat_busy "Setting Locale: en_US"
echo "export LANG=en_US" >>/etc/profile.d/locale.sh
stat_done

stat_busy "Setting Consoles to UTF-8 mode"
# UTF-8 consoles are default since 2.6.24 kernel
# this code is needed not only for older kernels,
# but also when user has set vt.default_utf8=0 but LOCALE is *.UTF-8.
for i in $(/usr/bin/seq 0 63); do
        usr/bin/kbd_mode -u < /dev/vc/${i}
        printf "\e%%G" > /dev/vc/${i}
done
# the $CONSOLE check helps us avoid this when running scripts from cron
echo 'if [ "$CONSOLE" = "" -a "$TERM" = "linux" -a -t 1 ]; then printf "\e%%G"; fi' >>/etc/profile.d/locale.sh
stat_done

status "Loading Keyboard Map: be-latin1" /bin/loadkeys -q -u "be-latin1" &

# Adding persistent network/cdrom generated rules
if [ -f "/dev/.udev/tmp-rules--70-persistent-cd.rules" ]; then
        stat_busy "Adding persistent cdrom udev rules"
        /bin/cat /dev/.udev/tmp-rules--70-persistent-cd.rules >> /etc/udev/rules.d/70-persistent-cd.rules
        stat_done
fi
if [ -f "/dev/.udev/tmp-rules--70-persistent-net.rules" ]; then
        stat_busy "Adding persistent network udev rules"
        /bin/cat /dev/.udev/tmp-rules--70-persistent-net.rules >> /etc/udev/rules.d/70-persistent-net.rules
        stat_done
fi

# Save our dmesg output from this boot
if [ -f /var/log/dmesg.log ]; then
        /bin/rm /var/log/dmesg.log
fi
/bin/dmesg > /var/log/dmesg.log &

# End of file

/etc/rc.conf

I've stripped out everything here that I included by default in #/etc/rc.sysinit and #/etc/rc.shutdown.

In this version the modules I need for my laptop are in the MODULES array, so there is no need to turn MOD_AUTOLOAD on. I could strip out some modules, but didn't find the time to figure that out. The list I got from 'hwdetect --show-modules-order'. I did take out snd-hda-codec and dock, because these gave an error on load.

#
# /etc/rc.conf
#

MOD_AUTOLOAD="no"

MODULES=(ac battery button processor thermal video wmi agpgart intel-agp dcdbas hid usbhid i2c-i801 i2c-core evdev 
ff-memless joydev pcspkr psmouse serio_raw led-class mmc_core ricoh_mmc sdhci-pci sdhci rtc-cmos rtc-core rtc-lib 
output iTCO_vendor_support iTCO_wdt snd-mixer-oss snd-pcm-oss snd-hwdep snd-page-alloc snd-pcm snd-timer snd snd-hda-
intel soundcore pata_acpi ata_generic ahci ata_piix sky2 mac80211 rfkill usb-storage usbhid usbcore ehci-hcd uhci-hcd 
vboxdrv vboxnetflt)

DAEMONS=(syslog-ng @hal @fam @crond @alsa)

# End of file

In this version the modules are discovered by the system itself. I guess this is the smallest a usable /etc/rc.conf can get.

MOD_AUTOLOAD="yes"
MODULES=()
DAEMONS=(syslog-ng @hal @fam @crond @alsa)

/etc/rc.shutdown

This doesn't have anything to do with the boot time, but with #/etc/rc.conf. By stripping out a lot out, I broke the shutdown script. In meanwhile I've taken out the unnecessary stuff (LVM, ...).

#!/bin/bash
#
# /etc/rc.shutdown
#

. /etc/rc.conf
. /etc/rc.d/functions

# avoid staircase effect
/bin/stty onlcr

echo " "
printhl "Initiating Shutdown..."
echo " "

# avoid NIS hanging syslog-ng on shutdown by unsetting the domainname
if [ -x /bin/domainname ]; then
        /bin/domainname ""
fi

if [ -x /etc/rc.local.shutdown ]; then
        /etc/rc.local.shutdown
fi

if [ "$PREVLEVEL" = "3" -o "$PREVLEVEL" = "5" ]; then
        # Shutdown daemons
        let i=${#DAEMONS[@]}
        while [ $i -ge 0 ]; do
                if [ "${DAEMONS[$i]:0:1}" != '!' ]; then
                        ck_daemon ${DAEMONS[$i]#@} || stop_daemon ${DAEMONS[$i]#@}
                fi
                let i=i-1
        done
        # find any leftover daemons and shut them down in reverse order
        if [ -d /var/run/daemons ]; then
                for daemon in $(/bin/ls -1t /var/run/daemons); do
                        stop_daemon $daemon
                done
        fi
fi

# Terminate all processes
stat_busy "Sending SIGTERM To Processes"
/sbin/killall5 -15 &> /dev/null
/bin/sleep 5
stat_done

stat_busy "Sending SIGKILL To Processes"
/sbin/killall5 -9 &> /dev/null
/bin/sleep 1
stat_done

stat_busy "Saving Random Seed"
/bin/dd if=/dev/urandom of=/var/run/random-seed count=1 bs=512 2> /dev/null
stat_done

stat_busy "Saving System Clock"
/bin/rm -f /etc/localtime
/bin/cp "/usr/share/zoneinfo/Europe/Brussels" /etc/localtime
/sbin/hwclock --systohc --localtime --directisa
stat_done

# removing psmouse module to fix some reboot issues on newer laptops
/sbin/modprobe -r psmouse >/dev/null 2>&1

# Write to wtmp file before unmounting
/sbin/halt -w

stat_busy "Deactivating Swap"
/sbin/swapoff -a
stat_done

stat_busy "Unmounting Filesystems"
/bin/umount -a -r -t noramfs,notmpfs,nosysfs,noproc
stat_done

stat_busy "Remounting Root Filesystem Read-only"
/bin/mount -n -o remount,ro /
stat_done

# Power off or reboot
if [ "$RUNLEVEL" = "0" ]; then
        printsep
        printhl "${C_H2}POWER OFF"
        /sbin/poweroff -d -f -h -i
else
        printsep
        printhl "${C_H2}REBOOTING"
        # if kexec is installed and a kernel is loaded, use it
        [ -x /sbin/kexec ] && /sbin/kexec -e > /dev/null 2>&1
        /sbin/reboot -d -f -i
fi

# End of file

/lib/udev/load-modules.sh

Something little, but improving, here. It takes away the blacklisting function for the MODULES array in #/etc/rc.conf, but when MOD_AUTOLOAD off it's not used either way.

Check Speedup_udev#Blacklisting_modules if you need blacklisting. I got this tweak from the same page, there are other ways to do this on there.

#!/bin/sh
#
# /lib/udev/load-modules.sh
#

/sbin/modprobe $1 &

# End of file

Additional Resources