Mit Gentoo im Geschwindigkeitsrausch

Gentoo ist dazu da, um an unsere Bedürfnisse angepasst zu werden. Dies beinhaltet für manche Leute auch, die Optimierung auf Geschwindigkeit.

Zuerst sollten wir uns mit der Frage beschäftigen, was den PC langsam macht. Dateizugriffe auf Festplatten und andere Laufwerke bremsen dabei das System am Meisten. Der Grund dafür ist darin zu suchen, dass der Computer dabei meist auf Daten warten muss um etwas tun zu können. Was wäre, wenn alles im RAM liegen würde?

Exakt. Genau das wollen wir machen. Wir verlegen die meist gebrauchten Teile in den RAM, genauergesagt in ein Ramdrive. Nach langem Experimentieren hat sich herausgestellt, dass es den grössten Geschwindigkeitsvorteil bringt, wenn man nur folgende Teile auf ein Ramdrive schiebt:

  1. /usr/lib
  2. /lib
  3. /usr/bin
  4. /usr/sbin
  5. /sbin
  6. /bin

Es macht keinen Sinn alle Daten in einem Ramdrive zu lagern, da immer das Risiko besteht, dass die dort gelagerten Daten verlorengehen. Daher ist es nötig, unser Disk-Layout etwas anzupassen um eine entsprechend sichere Lösung zu konstruieren:

  • /usr sollte auf eine eigene Partition
  • /home ist als Datenspeicher auf einer eigenen Partition
  • /root ist analog zu /home zu behandeln (oder ein Symlink zu /home/root)
  • /var ist der Platz für Logs und Portage-Caches

Die Installation selbst sollte nach Handbuch erfolgen. Zu guterletzt erstellen wir noch ein leeres Verzeichnis /newroot welches uns als Mountpoint dienen wird.

Wenn wir nun am System Dateien verändern wollen wir natürlich, dass diese permanent verändert werden. Die Datei /etc/conf.d/local.stop leistet uns dabei gute Dienste:

##############
#!/bin/sh
CURRDIR=`/bin/pwd`
STORE=”root”
cd /
#Exclude anything that’s on it’s own partition here
tar cfp ${STORE}/fs.tar * –exclude=usr/* –exclude=root/* –exclude=home/* \
–exclude=proc/* –exclude=sys/* –exclude=tmp/* –exclude=var/* \
–exclude=opt/*
cd /usr/
# rm -fr /usr/bin /usr/sbin /usr/lib
# cp -a /usr/.bin /usr/bin
# cp -a /usr/.sbin /usr/sbin
# cp -a /usr/.lib /usr/lib
cd bin && tar cfp /${STORE}/usr_bin.tar *
cd ../sbin && tar cfp /${STORE}/usr_sbin.tar *
cd ../lib && tar cfp /${STORE}/usr_lib.tar *
# rm -fr /usr/bin /usr/sbin /usr/lib
# mkdir /usr/bin /usr/sbin /usr/lib
cd $CURRDIR

Dieses Script sollte in dem vorhin Erwähnten beim Shutdown aufgerufen werden. Aus Wartungstechnischen Gründen empfiehlt es sich es (wie oben) in einem eigenen File abzulegen. Ein guter Platz dafür ist /sbin.

Um / in einem Ramdrive zu haben (ja, ich bin mir bewusst, ich neige zu Übertreibungen) müssen wir uns einen eigenen initrd konstruieren der die erforderlichen Schritte durchführt:

mount /boot
touch /boot/initrd
dd if=/dev/zero of=/boot/initrd bs=1024k count=8
losetup /dev/loop0 /boot/initrd
mke2fs /dev/loop0
mkdir /mnt/initrd
mount /dev/loop0 /mnt/initrd
cd /mnt/initrd
mkdir etc dev lib bin proc new store
touch linuxrc etc/mtab etc/fstab
chmod +x linuxrc
for I in sh cat mount umount mkdir chroot tar; do cp /bin/$I bin/; done
cp /sbin/pivot_root bin/

Da wir im initrd nicht nur statische Binaries verwenden müssen wir die verwendeten Dateien mit Hilfe von ldd überprüfen:

ldd /bin/sh
linux-gate.so.1 => (0xffffe000)
libdl.so.2 => /lib/libdl.so.2 (0xb7fe2000)
libc.so.6 => /lib/tls/libc.so.6 (0xb7eca000)
/lib/ld-linux.so.2 (0xb7feb000)

Wichtig dabei ist, dass ihr die Überprüfung selbst macht, damit ihr wirklich alle wichtigen Dateien habt!!

Unser nächster Schritt besteht im Erstellen eines linuxrc-Scripts welches wie folgt aussieht:

cat /mnt/initrd/linuxrc
################
#!/bin/sh
export PATH=/bin
STOREDEV=/dev/hda10
STORE=/store
ROOTSIZE=128m

# Get kernel CMDLINE
mount -t proc none /proc
CMDLINE=`cat /proc/cmdline`
umount /proc

mount $STOREDEV $STORE

# Mount root and create read-write directories
mount -t tmpfs -o size=$ROOTSIZE none /new/ > /dev/null 2>&1
cd /new/ && tar xpf $STORE/fs.tar > /dev/null 2>&1
umount $STOREDEV
# Pivot root and start real init
cd /new
pivot_root . newroot
exec chroot . /bin/sh <<- EOF >dev/console 2>&1
exec /sbin/init ${CMDLINE}
EOF

Es folgt das Erstellen der Devicenodes, da wir keinen Devicemanager wie udev verwenden. Hilfreiche Dokumentationen finden sich in /usr/src/linux/Documentation/devices.txt:

mknod /mnt/initrd/dev/console c 5 1
mknod /mnt/initrd/dev/null c 1 3
mknod /mnt/initrd/dev/hda b 3 0
mknod /mnt/initrd/dev/hda4 b 3 4
mknod /mnt/initrd/dev/hda10 b 3 10

Dann unmounten wir den initrd und widmen uns der Datei /etc/init.d/localmount nach folgender Vorlage:

start() {
USRBINSIZE=32m
USRSBINSIZE=2m
USRLIBSIZE=256m

# Mount local filesystems in /etc/fstab.
ebegin “Mounting local filesystems”
mount -at nocoda,nonfs,noproc,noncpfs,nosmbfs,noshm >/dev/null
eend $? “Some local filesystem failed to mount”

ebegin “Mounting RAM filesystems”
mount -t tmpfs -o size=$USRBINSIZE none /usr/bin > /dev/null 2>&1
mount -t tmpfs -o size=$USRSBINSIZE none /usr/sbin > /dev/null 2>&1
mount -t tmpfs -o size=$USRLIBSIZE none /usr/lib > /dev/null 2>&1
cd /usr/bin && tar xpf /root/usr_bin.tar > /dev/null 2>&1
cd /usr/sbin && tar xpf /root/usr_sbin.tar > /dev/null 2>&1
cd /usr/lib && tar xpf /root/usr_lib.tar > /dev/null 2>&1
eend $? “Some RAM filesystems did not mount”

Wenn /usr/lib zu gross ausfällt besteht der beste Workaround darin, ein paar Dateien wegzubewegen und mit entsprechenden Symlinks zu ersetzen:

cd /usr/lib
for I in perl5 python2.3 portage modules gcc gcc-lib; do
mv $I ../local/lib/
ln -s ../local/lib/$I $I
done

Letzte Schritte:

mv /usr/sbin /usr/.sbin
mv /usr/bin /usr/.bin
mv /usr/lib /usr/.lib
update-balls
reboot

Gläubige Leute können an dieser Stelle noch ein Gebet sprechen, jedoch ist dies optional. Viel Glück.

Author:

Leave a Reply

Your email address will not be published. Required fields are marked *

Notify me of followup comments via e-mail. You can also subscribe without commenting.