Montag, 27. April 2009

Speicherfrust

Seit Monaten schlug ich mich herum mit einem äußerst nervigen Computerproblem, bis heute. Die Rede ist von meinem Gentoo, das sich aufhing sobald ich zuviel RAM belegt hatte. Ich konnte kein Swap verwenden; der Grund dafür ist, dass mein Mainboard (vermutlich aufgrund von starken Temperaturschwankungen in einer der heißeren Regionen Madagaskars) völlig hinüber ist. Durch den defekten DMA Controller bin ich gezwungen alle Geräte im PIO Modus anzusprechen, was das System natürlich enorm ausbremst da die CPU Last bei jedem Zugriff auf 100% schnellt.

Firefox ist ein einziger RAM-Fresser; da konnte es schon mal passieren, dass man eine Anwendung zuviel öffnete und schwups passierte es: Das System griff auf die Festplatte zu wie wild, Musik im Hintergrund fing an zu stocken, der Mauszeiger reagierte kaum noch - bis schließlich so ziemlich alles völlig zum erliegen kam. Kein Login von außen möglich. Mein einziger Ausweg war damals der kalte Reboot, da ich keine rettende Lösung kannte (außer aufzupassen dass der Speicherverbrauch nicht ein gewisses Maximum überschreitet).

Anfangs noch dachte ich, es läge ganz einfach an der Auslagerungsfunktion vom Kernel. Also, dass, sobald der RAM voll ist, er jede Menge Daten auf die Swap-Partition schaufelt (was ja eh schon langsam ist), und diese Aktion durch den lahmen PIO Modus alles Andere blockiert. Das erschien mir logisch woraufhin ich by-all-means versuchte diesen Mechanismus zu deaktivieren, was mir einfach nicht gelingen wollte. Zuallererst probierte ich es, mit swapoff, zu deaktivieren, kommentierte dann nachträglich den Eintrag für die Swap-Partition in /etc/fstab aus; ich setzte den sysctl Wert vm.swappiness auf null; ja, ich entfernte sogar letztendlich das Kernelmodul.

Es half alles nix. Der RAM war voll, und die Festplatte fing an zu rattern. Warum?? Ich fand keine Lösung. Irgendwann fand ich heraus, dass der Kernel ja eigentlich noch prächtig reagierte. Denn mit dem SysRq Key konnte ich erfolgreich den Schaden begrenzen und das System vernünftigen neustarten - später, nach erneuter Recherche, dann sogar lediglich die aktuelle X Session killen und mich neu einloggen. Trotzdem waren alle Programme zu, und die Arbeit teilweise verloren.

Heute, als ich Doxygen kompilieren wollte und mir das Debakel 5 Mal am Stück passierte, versuchte ich mich wieder einmal daran, diesem merkwürdigen Festplattenzugriff auf die Spur zu kommen. Manchmal sah man ja anhand von dmesg, dass der Kernel tatsächlich ein Programm ausgewählt und terminiert hatte aufgrund einer out-of-memory condition; das passierte aber viel zu selten - und wenn, dann auch erst nach einer halben Ewigkeit. Da jegliches Swapping vom Kernel bereits entfernt war brauchte ich dort nicht mehr suchen. Stattdessen nahm ich mir vor jede einzelne vm-Variable von sysctl zu überprüfen und wurde sehr schnell fündig. Des Pudels kern liegt im ausgetüftelten Speichermanagement von Linux.

Hier kann man den relevanten Part nachlesen (er beschreibt sogar fast dasselbe desaströse Verhalten im Abschnitt "Kernel virtual memory management"). Der Kernel vergibt nämlich allerhand Speicher, den er gar nicht hat, da er weiß, dass die meisten Programme gefräßige Monster sind. Dieses Zusammenspiel ist normalerweise kein Problem - auf meinem System jedoch, schon. Wieviel er sich dabei extra herausnimmt wird mit der sysctl Variable vm.overcommit_ratio festgelegt. Einmal auf 0 (% extra) gesetzt, gab es keine Probleme mehr. Ein geeigneter Task wurde beim Testlauf mit Gimp (und riesigen Bildern) sofort vom Kernel ausgewählt und gekillt...

Cool!

Nachtrag: Es ist nicht so einfach wie ich mir das vorgestellt hatte, es passiert nämlich immernoch: Der kswapd blockiert das ganze System (selbst Tasks die mit nice -20 laufen) und die CPU befindet sich 90% der Zeit in Wartestellung. Also forschte ich weiter und fand heraus, dass sich mit der Variable vm.overcommit_memory das Grenzverhalten einstellen lässt. Ist sie gleich null werden heuristische Verfahren angewendet, die abwägen, ob Anwendungen getötet werden müssen oder nicht. Bei dem Wert 2, wird konsequenter vorgegangen - das kann allerdings gefährlich werden wenn vm.overcommit_ratio null ist: Denn dann kann keine Anwendung mehr auf dem gesamten System Speicher reservieren, noch nicht mal init. Aber selbst mit der harten Einstellung kann es immer noch manchmal vorkommen, dass sich das System zu Tode kswapd't. Wer mehr Informationen dazu hat, bitte kommentieren ;-)

Nachtrag: Nach längerem Testen habe ich mich nun dazu entschlossen, meine Swap Partitionen wieder anzuschalten. Dabei kann man auch denen, die eine schnellere Zugriffsgeschwindigkeit besitzen, ganz einfach eine höhere Priorität geben als den Anderen. Diese Lösung ist tatsächlich empfehlenswerter, als das Swapping komplett auszuschalten - denn der wundersame, unaufhörliche Festplattenzugriff des kswapd, der das ganze System zu Tode blockiert, ist nämlich viel, viel schlimmer als im langsamen PIO Modus auszulagern. Mit dem deadline scheduler des Kernels lässt sich das auch noch ganz gut ertragen.

Keine Kommentare:

Kommentar veröffentlichen