Nachdem ich das Virtualisierungssetup aus einem vergangenen Blogpost eine Weile betrieben hatte, haben sich schon einige VMs darin angesammelt. Da das Host-System allerdings nur 8 GiB Arbeitsspeicher hat, wurde es langsam ein wenig eng: Das Auslagern mehrerer Seiten in den Swap hat vor allem die Bedienung des Alpine-Hosts sehr zäh und unzuverlässig gemacht.
Klar könnte ich mehr RAM in mein Gerät einbauen: RAM kostet ja nicht mehr so viel. Aber zum Glück gibt es noch eine andere Lösung, die vor allem die Effizienz steigert. (Und ich bin ja eigentlich immer eher für effiziente Software. :D)
Exkurs: Das Betriebssystem und der Arbeitsspeicher
Das Betriebssystem verwaltet den Arbeitsspeicher in kleinen Einheiten, den sog. Pages (auf Deutsch auch Kacheln). Eine Kachel ist üblicherweise 4 KiB groß.
Benötigt ein Prozess (mehr) Speicherplatz zur Ausführung, bekommt er diesem vom Betriebssystem zugewiesen.
Das ganze passiert transparent: Wenn der Prozess z.B. ein GiB Speicher anfragt, aber davon nur 2 KiB benutzt, bekommt er vom Betriebssystem trotzdem vorgespielt, dass er ein GiB zur exklusiven Nutzung bekommen habe:
- OS: 1 GiB Speicher? Da kann ja jeder kommen!
- OS: “Das hier ist ein GiB Speicher” *schiebt eine 4 KiB-große Kachel hin*
- Proc: “Okay, dankeschön.” *Beginnt mit der Arbeit*
Für den Prozess sieht es tatsächlich so aus, dass er ein GiB Speicher bekommen habe. Nur das Betriebssystem führt intern eine Tabelle darüber, welche Kacheln dem Prozess wirklich gehören und verwendet werden.
Erst sobald der Prozess versucht, die versprochenen Kacheln zu benutzen, reserviert das Betriebssystem diese auch wirklich für den Prozess. So wird sichergestellt, dass auch nur dann Speicher belegt ist, wenn er auch wirklich benutzt wird.
Den freien Speicher, selbst, wenn er auch schon anderen Prozessen versprochen wurde, kann man nämlich mehrfach verleihen. Vielleicht ein bisschen so, wie Kredite von einer Bank… Zwinkersmiley.
Kernel-Samepage-Merging
Kernel Samepage Merging ist eine Technik, um Arbeitsspeicher zu sparen. Das funktioniert in etwa so:
Wenn auf einem Host nun mehrfach das (fast) gleiche Programm läuft, liegen auch mehrfache Kopien desselben im Arbeitsspeicher. Das gilt auch bei VMs: Wenn fünf Debian-11-VMs auf der Maschine laufen, liegt Debian auch fünf Mal im Arbeitsspeicher, obwohl man es strenggenommen nur einmal bräuchte.
KSM schafft hier Abhilfe, indem es regelmäßig den RAM nach exakt gleichen Kacheln absucht, um diese in einer einzelnen Kachel zusammenzulegen. Im Falle des Debian-Setups, könnten wir so also theoretisch vier Debian-Kopien einsparen.
Red Hat hat bei Experimenten 52 Windows-XP VMs mit jeweils einem GiB RAM auf einem Host mit nur 16 GiB Arbeitsspeicher laufen lassen.
Der Speichergewinn hängt jedoch stark vom Einsatzszenario ab: Es gibt auch zwischen den VMs unterschiedliche Kacheln (z.B. die Programme, die in ihnen laufen).
Ein Tradeoff von KSM ist, dass es etwas mehr CPU-Leistung braucht, da es nach gleichen Kacheln erst scannen muss. Falls man mehr RAM einbauen kann, sollte man das also bevorzugen.
KSM unter Alpine aktivieren
KSM kann man im laufenden Betriebssystem unter dem Pfad /sys/kernel/mm/ksm/
einschalten und konfigurieren. Der Kernel muss mit KSM-Support kompiliert worden sein, was aber für alle heute gängigen Kernel von Allzweck-Distros zutreffen sollte.
# KSM einschalten
echo 1 > /sys/kernel/mm/ksm/run
# Den Abstand zwischen zwei Scan hochsetzen (Standard: 20 ms)
echo 2000 > /sys/kernel/mm/ksm/sleep_millisecs
Man kann auch weitere Parameter einstellen. Welche, ist in der Dokumentation von KSM beschrieben.
Die gesetzten Parameter sind nach einem Neustart weg. Sie müssen bei jedem reboot neu gesetzt werden, z.B. mit einem Skript.
KSM persistieren: /etc/local.d/
executable-script: /etc/local.d/ksm.start
:
#!/bin/sh
echo 1 > /sys/kernel/mm/ksm/run
echo 2000 > /sys/kernel/mm/ksm/sleep_millisecs
https://wiki.gentoo.org/wiki//etc/local.d