Commit cbc60afe authored by amnesia's avatar amnesia
Browse files

a first attempt at improving cd boot time

parent c95efefa
......@@ -26,6 +26,14 @@ Package: network-manager-openvpn-gnome
Pin: release a=lenny-backports
Pin-Priority: 999
Package: python-pyinotify
Pin: release a=testing
Pin-Priority: 999
Package: python-support
Pin: release a=lenny-backports
Pin-Priority: 999
Package: *
Pin: release a=stable
Pin-Priority: 900
......
#! /bin/sh
### BEGIN INIT INFO
# Provides: boot-profile
# Required-Start: mountkernfs
# Required-Stop:
# X-Start-Before: udev mountdevsubfs
# Default-Start: S
# Default-Stop:
# Short-Description: profile files used during boot
### END INIT INFO
PATH=/sbin:/usr/sbin:/bin:/usr/bin
DESC="boot profiling system"
NAME=boot-profile
DAEMON=/usr/sbin/$NAME
DAEMON_ARGS="/lib/init/rw/boot-profile"
PIDFILE=/var/run/$NAME.pid
SCRIPTNAME=/etc/init.d/$NAME
# Exit if the package is not installed
[ -x "$DAEMON" ] || exit 0
# Exit if profiling is not enable
grep -qw "profile" /proc/cmdline || exit 0
# Read configuration variable file if it is present
[ -r /etc/default/$NAME ] && . /etc/default/$NAME
# Load the VERBOSE setting and other rcS variables
. /lib/init/vars.sh
# Define LSB log_* functions.
. /lib/lsb/init-functions
do_start() {
# Raise maximum inotify watch descriptors
echo 32768 >/proc/sys/fs/inotify/max_user_watches
start-stop-daemon --start --quiet --pidfile $PIDFILE --exec $DAEMON --test > /dev/null \
|| return 1
start-stop-daemon --start --quiet --pidfile $PIDFILE --exec $DAEMON -- \
$DAEMON_ARGS \
|| return 2
}
do_stop() {
start-stop-daemon --stop --quiet --retry=TERM/30/KILL/5 --pidfile $PIDFILE --name $NAME
RETVAL="$?"
[ "$RETVAL" = 2 ] && return 2
start-stop-daemon --stop --quiet --oknodo --retry=0/30/KILL/5 --exec $DAEMON
[ "$?" = 2 ] && return 2
rm -f $PIDFILE
return "$RETVAL"
}
case "$1" in
start)
[ "$VERBOSE" != no ] && log_daemon_msg "Starting $DESC" "$NAME"
do_start
case "$?" in
0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
esac
;;
stop)
[ "$VERBOSE" != no ] && log_daemon_msg "Stopping $DESC" "$NAME"
do_stop
case "$?" in
0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
esac
;;
restart|force-reload)
log_daemon_msg "Restarting $DESC" "$NAME"
do_stop
case "$?" in
0|1)
do_start
case "$?" in
0) log_end_msg 0 ;;
1) log_end_msg 1 ;; # Old process is still running
*) log_end_msg 1 ;; # Failed to start
esac
;;
*)
# Failed to stop
log_end_msg 1
;;
esac
;;
*)
echo "Usage: $SCRIPTNAME {start|stop|restart|force-reload}" >&2
exit 3
;;
esac
:
../init.d/boot-profile
\ No newline at end of file
#!/usr/bin/env python
from pyinotify import WatchManager, Notifier, \
ThreadedNotifier, ProcessEvent, IN_ACCESS
import re
import sys
import atexit
from signal import signal, SIGTERM
import os.path
# Ignore files matching this regular expression
IGNORE_RE = "^/(tmp|sys|proc|dev|live/cow)"
class ProfileProcessor(ProcessEvent):
def __init__(self, new_profile):
self.priority = 32767
self.files = {}
self.ignore_re = re.compile(IGNORE_RE)
self.new_profile = new_profile
def add_file(self, path):
if not self.files.has_key(path):
self.files[path] = self.priority
self.priority -= 1
def process_IN_ACCESS(self, event):
self.add_file(event.pathname)
def is_excluded(self, path):
return self.ignore_re.match(path)
def end_profiling(self):
for path, priority in self.files.iteritems():
self.new_profile.write("%-68s %s \n" % (path, priority))
self.new_profile.close()
def main():
if len(sys.argv) < 2:
print >>sys.stderr, "usage: %s <new-profile>" % sys.argv[0]
sys.exit(0)
new_profile = open(sys.argv[1], 'w')
wm = WatchManager()
profiler = ProfileProcessor(new_profile)
atexit.register(profiler.end_profiling)
signal(SIGTERM, lambda signum, stack_frame: sys.exit(0))
notifier = Notifier(wm, profiler)
wm.add_watch('/', IN_ACCESS, rec=True, exclude_filter=profiler.is_excluded)
notifier.loop(daemonize=True)
if __name__ == '__main__':
main()
......@@ -19,7 +19,7 @@ xterm
### Self-bla
# profiling => squashfs optimization
readahead
python-pyinotify
# contains mkpasswd, needed in chroot_local-hooks/01-password
whois
......
When amnesia is booted from a CD, there is a lot of seeks from one file to
another during boot. This could be improved by ordering files on the CD in
the order used during boot.
Implementation
==============
An *initscript* is loaded during 'S' runlevel, just at the begining of the
boot process. If `profile` has been specified on the kernel command line, it
starts the `boot-profile` daemon which uses `inotify` to record file that are
accessed during boot.
Once enough of the boot sequence has been profiled, `boot-profile` must be
manually `kill`'ed. Then, `/lib/init/rw/boot-profile` will contain a file
that is suitable for the `-sort` argument of `mksquashfs`.
Left to be done
===============
* Figure out how to specify the `-sort` argument to `lh_binary_rootfs`.
The *sortlist* will need to be copied to `chroot/` before.
* Test with a real CD if during boot time seeks occur less.
* Implement an automated way to update the *sortlist*.
[[boot-profile]] is a *sortlist* generated using the aformentioned
`boot-profile` daemon.
This diff is collapsed.
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment