dWing — die Welt ist nicht gerecht

sign in

Malloc Überprüfungen

Zwei Blog Einträge die ich kürzlich gelesen habe veranlassten mich dazu ein weit verbreitetes Problem in der Softwareentwicklung kritisch zu hinterfragen. Ich empfehle jedem Interessierten sich die Einträge und deren Verweise durchzulesen, dennoch fasse ich einige Punkte zusammen die mich selbst sehr überrascht haben.

Worum geht es denn überhaupt? Wenn man anfängt C zu lernen und zum Thema Speicherverwaltung übergeht wird immer darauf hingewiesen, dass die Funktion malloc() welche Speicher reserviert in Ausnahmefällen auch NULL zurückliefern kann. Dieser Ausnahmefall tritt auf, wenn das System keinen Speicher mehr hat, sagt man. Man solle also immer brav den Rückgabewert von malloc(), realloc() und calloc() auf NULL überprüfen damit man keine Speicherverletzung, also den Zugriff auf nicht vorhandenen Speicher produziert in welchem Fall das Programm abstürzen würde. Mehr dazu später.

Sehr überrascht hat es mich zu erfahren, dass ein scheiterndes malloc() gar nicht die Situation des aufgebrauchten Speichers beschreibt. Vielmehr bedeutet es, dass der Adressraum nicht ausreicht um die geforderte Menge Speicher zu adressieren. Bei heutigen 64bit Systemen ist dies praktisch unmöglich. Selbst wenn ich alle meine Festplatten und Speichermedien in einen 64bit Adressraum abbilde wäre noch reichlich Adressraum vorhanden und malloc() würde nicht fehlschlagen. Bei 32bit Programmen die leicht über die Grenze von 2G kommen können wie beispielsweise rechen- und speicherintensiven Spielen ist die allerdings ein recht akutes Problem. Der Umstieg auf 64bit Systeme schafft Abhilfe und ist zumindest im Windows und Spieleumfeld lange überfällig.

Was passiert denn wirklich im Falle von erschöpftem Speicher, der fälschlicherweise als Grund für ein fehlschlagendes malloc() angenommen wird? Zumindest in einer Linux Umgebung schaltet sich der sogenannte OOM Killer ein. Dieser tötet ganz einfach einen beliebigen Prozess auf dem System um sich dessen Speicher zu holen. Bevor der OOM Killer allerdings überhaupt aktiv wird, wird bereits der Großteil der Programme auf den swap ausgelagert, wodurch die Performance vor allem eines Desktops sowieso in den Keller geht.

Weiters wird erwähnt, dass die Überprüfung des malloc Rückgabewertes meist sehr entwicklungsintensiv ist und in vielen Fällen gar nicht getestet wird. Bei einem Fehlschlag wird das Programm meist sowieso beendet. Ob dies nun durch einen Speicherzugriffsfehler geschieht oder weil man selbst das Programm beendet ist in dem Fall egal, das Ergebnis ist das selbe.


Eine weitere interessante Überlegung die ich vor längerer Zeit gelesen habe und erwähnenswert ist: malloc() macht nur einen geringen Teil von Speicherreservierung aus. Viel öfter wird durch Funktionsaufrufe ein neuer Stack angelegt und Platz für lokale Funktionsvariablen reserviert. Würde in solch einem Fall der Speicher aus gehen hätte man sowieso keine Möglichkeit etwas zu retten und das Programm stürzt sowieso ab. Und solche implizite Speicherreservierung tritt im Laufe eines Programmes viel öfter auf als die explizite Reservierung mittels malloc().

Was bringt ureadahead

Nachdem readahead in Jaunty durch sreadahead in Karmic ersetzt wurde gab es heute ein Update auf ureadahead in karmic-proposed.

Jedes dieser Systeme sollte die Startzeit verkürzen indem Dateien bevor sie benutzt werden bereits in den RAM gelesen werden.

sreadahead sollte vor allem SSD Speicher beschleunigen und ist parallel zum normalen Startvorgang gelaufen. Leider hatte es bei mechanischen Festplatten den gegenteiligen Effekt. Da es parallel gelaufen ist, hat es selbst andere Prozesse beim Festplattenzugriff ausgebremst und der Startvorgang wurde insgesamt langsamer.

ureadahead ist eine Weiterentwicklung dessen. Dabei unterscheidet ureadahead zwischen SSDs und mechanischen Festplatten. Bei mechanischen erstellt er zuerst eine Liste aller Dateien, die beim starten benötigt werden, sortiert diese dann gemäß ihrer physikalischen Position auf der Festplatte und liest diese dann beim nächsten Start der Reihe nach aus. Die Sortierung stellt sicher, dass der Lesevorgang möglichst sequenziell abläuft um Bewegungen der Leseköpfe zu minimieren und Datendurchsatz zu maximieren. Dabei warten andere Prozesse bis dieser Vorgang beendet ist.


Wenn ich meinen eben erstellten Bootchart mit einem älteren vergleiche sieht man gleich, dass die Startzeit um fast 15 Sekunden verkürzt wurde. Kleine Erklärung: In den Grafen oben bedeutet das Rosa, dass die Festplatte ausgelastet ist bzw. dass Prozesse auf Daten von der Festplatte warten. Blau bedeutet, dass der Prozessor wirklich Arbeit verrichtet. Die grüne Linie bedeutet Datendurchsatz. Ist weder Rosa noch Blau vorhanden dann passiert nichts, die Festplatte ist inaktiv und der Prozessor hat nichts zu berechnen.

Und da fallen mir gleich zwei Probleme auf, die verbessert werden müssen.

Alles in allem bin ich aber mit dem heutigen Update sehr zufrieden und hoffe darauf, dass in Zukunft noch mehr in diese Richtung unternommen wird.

Karmic Startzeit

In meinem letzten Beitrag bin ich nicht dazu gekommen die Bootzeit von Karmic zu analysieren. In den Medien hieß es ja, es solle sehr viel schneller starten. Ich mache leider genau die gegenteilige Erfahrung.

Vergleicht man die Bootzeiten von Intrepid, Jaunty und Karmic, so sieht man dass Jaunty rund 15 Sekunden schneller als Intrepid war, Karmic allerdings um einiges Langsamer ist.

Man muss natürlich auch dazu sagen, dass diese Zeiten nicht vergleichbar sind. Mein neues Karmic System ist verschlüsselt und beim Desktop wird der Instant Messenger und der Musikspieler mit gestartet, was zuvor nicht der Fall war.

Würde ich die 15 Sekunden Überhang wegen der Festplattenverschlüsselung abziehen und noch großzügig weitere 15 Sekunden wegen den Programmen im Autostart so bin ich immer noch mit Jaunty gleich auf, also keinerlei Verbesserung.


Die Zeiten für die Kernel Initialisierung, also der Zeitpunkt an dem der tatsächliche Bootchart anfängt haben sich durch die Bank verschlechtert, von 2 auf fast 4 Sekunden. Was ist da schief gelaufen?

Auch die Verschlüsselung hat sich mit meinem heutigen Update um 2 Sekunden verschlechtert. Es lastet eine CPU voll aus für eine Sekunde, lastet danach die Festplatte für drei Sekunden voll aus um danach noch eine Sekunde nichts zu tun bevor es mir bestätigt, dass mein Kennwort richtig war und dann mit dem Startvorgang fortfährt. Vor dem heutigen Update hat es nur drei Sekunden gedauert, was auch schon unakzeptabel war. Da ist also auch einiges schief gelaufen.

Man sieht auch sehr deutlich den bereits erwähnten Overhead mit couchdb. Das kann man wirklich nur noch als FAIL bezeichnen.

Auch sind Lücken drinnen in denen der Rechner einfach nichts macht, die sich auf vier Sekunden summieren. FAIL.


Ich frage mich echt wie Ubuntu das gesetzte Ziel von zehn Sekunden zum nächsten Release erfüllen will. Dieses Ziel ist auch nur auf einer bestimmten Referenzplattform gesetzt die mit SSD bestückt ist, somit also null IO Overhead aufweist. Ich befürchte aber, dass Leute mit langsamen Laptopfestplatten in die Röhre schauen werden dabei. Sehr schade.

Karmic Impressionen

Bereits vor einiger Zeit hatte ich ein kleines Review zum neuen Ubuntu, genannt Karmic Koala verfasst. Schon damals war ich mit dem neuesten Stand der Dinge nicht wirklich glücklich. Heute einen Tag vor der offiziellen Veröffentlichung habe ich mein System wieder auf den neuesten Stand gebracht. Leider hat sich seither kaum was verbessert. Nur ein Problem, welches mich beim booten geplagt hatte wurde beseitigt.

Ich muss an dieser Stelle auch Kritik an Ubuntu üben denn so kann es einfach nicht mehr weiter gehen. Es werden immer mehr unnütze Funktionen hinzugefügt, die das System unnötig ausbremsen. Neuerdings ist Couchdb dazugekommen welches es ermöglichen soll Einstellungen und persönliche Dokumente mit einem Server und damit anderen Desktops abzugleichen. Auch wenn man diesen Dienst nicht nutzen will wird er trotzdem beim hochfahren gestartet und schluckt Systemressourcen. Das schlimme daran: Der Dienst ist in einer exotischen Sprache namens Erlang geschrieben und benötigt aus welchen Gründen auch immer XULRunner. Somit läuft ein weiterer Systemdienst mit einer interpretierten Sprache und verbraucht dementsprechend mehr als 10M Speicher. Beim starten fragt es irgendwelche Sachen von XULRunner ab wodurch dieser beim booten gestartet wird, was eine Menge ausmacht, denn XULRunner ist eine riesige Applikation.

Ubuntu sollte endlich Abstand davon nehmen Systemdienste in Python, Perl, Erlang oder sonst irgendwas zu implementieren. Da könnten sie ja gleich anfangen alles in Java oder C# zu machen. Ubuntu sollte mehr investieren um das System so leichtgewichtig wie möglich zu halten und unnötige Funktionen vermeiden.

Gnome an sich macht in diese Richtung schon vieles. Veraltete Bibliotheken werden über Bord geworfen um die Anwendungen abzuspecken. Außerdem wird HAL langsam aber sicher durch Udev ersetzt. Ubuntu hat zwar das Ziel HAL über Bord zu werfen auch verfolgt aber dennoch werden bei mir zehn oder mehr HAL Prozesse beim hochfahren gestartet und bleiben danach im Speicher. Dies ist doch eine gute Möglichkeit Startzeit zu verkürzen und Speicher nicht unnötig zu verbrauchen.


Ähnlich den Bootzeit Meilensteinen sollte Ubuntu auch für den Speicherverbrauch klare Meilensteine und messbare Ziele definieren. Ein fertig gestartetes System mit allen Systemdiensten die in der Standardinstallation dabei sind sollte nicht mehr als z.b. 170M für die 32bit und 250M für die 64bit Version verbrauchen. Dies natürlich auf einem genormten Referenzsystem, denn die Hardware macht bezüglich Grafik einiges aus.

Impressionen: Windows 7 vs. Karmic

Lange haben ich und einige Freunde auf Windows 7 gewartet. Vor kurzem dann ist es im eAcademy erschienen und ich habe mir eine kostenlose Studentenlizenz gegönnt :)

Und ich muss sagen: Ich bin positiv überrascht. Die Installation war einfach und schnell. Mit Ausnahme von Touchpad und Grafikkarte wurden alle Gerätetreiber direkt über das Windows Update installiert. Das WLAN hatte selbst schon während der Installation funktioniert. Das System selbst fühlt sich recht schnell an, verbraucht in der 32bit Version nur um die 500M. Nachdem ich einige Dienste deaktiviert hatte änderte sich daran nicht sehr viel, der Verbrauch liegt immer noch bei rund 500 oder etwas darunter. Also bleiben mehr Ressourcen für speicherhungrige Spiele über. Bionic Commando läuft zumindest recht brauchbar, auch wenn es ein wenig ruckelt. Die Startzeit ist auch zufriedenstellend. Ich war außerdem sehr überrascht als ich sah, dass das System nur knappe 10G auf der Festplatte belegt. Inklusive 2G Swap und 1,5G Suspend Dateien.

Man kann also zu recht sagen: Windows 7 ist das bessere Vista so wie es von Anfang an hätte sein sollen.


Neben Windows 7 habe ich auch die neueste Alpha Version von Ubuntu, genannt Karmic Koala ausprobiert. Bisher bin ich leider etwas enttäuscht muss ich ehrlich zugeben. Anders als in einer virtuellen Umgebung verbraucht das System nicht um die 200 sondern etwas über 300M Speicher. Auch von den Anstrengungen zur Verkürzung der Bootzeit merke ich sehr wenig. Ich habe diesmal Autologin aktiviert, welches etwas Zeit spart aber mir scheint dass das neue xSplash diesen Gewinn wieder zunichte macht. Große bahnbrechende Änderungen sehe ich bisher nicht, es wurde wohl vor allem im Hintergrund sehr viel aufgeräumt. Eigentlich hätte ich gehofft das die vielen Aufräumungsarbeiten in Gnome etwas Speicher gespart hätten aber bisher merke ich davon nichts.

Ein neues Programm für den Umgang mit Festplatten und Partitionen ist enthalten. Damit kann man einfach Partitionen verwalten, auch mit RAID und Verschlüsselung. Negativ fällt mir dabei auf, dass sich das Programm bei jedem Start darüber beschwert dass meine Festplatte defekte Sektoren hätte. Da mir das bisher noch nie aufgefallen ist würde ich meinen dass es sich um Fehlalarm handelt. Diese Meldung ist allerdings sehr nervig, genau wie die Meldung beim Herunterfahren dass noch Programme laufen würden, die ich allerdings schon seit langem beendet hatte. Da muss eindeutig noch nachgebessert werden.


Eines meiner Ziele als ich den Laptop neu aufgesetzt hatte war es, das System von vorn bis hinten komplett zu verschlüsseln. Dies hat mir leider einen Tag Arbeit zu nichte gemacht. Denn für die Truecrypt System Verschlüsselung unter Windows ist es zwingend notwendig, Windows auf der ersten Partition zu installieren. Nachdem ich also ein zweites mal alles installiert hatte wurde die Windows System Partition verschlüsselt. Der Vorgang selbst ich recht einfach, aber mit dem Ergebnis bin ich nicht ganz zufrieden.

Will ich Windows starten, so gebe ich in dem Zuerst erscheinenden Truecrypt Bootloader mein Passwort ein und werde danach zu Grub umgeleitet wo ich dann Windows auswählen muss.

Will ich Linux starten so überspringe ich den Truecrypt Loader und Lade dann über Grub Linux. Erst danach gebe ich mein Passwort ein.

Einfacher wäre es sicherlich wenn zuerst Grub erscheint und danach die jeweilige Passworteingabe mit anschließendem Systemstart. In einigen Foren habe ich gelesen, dass der Truecrypt Loader sich über ein Defektes System beschwert sobald man wieder Grub in den MBR schreibt und von Grub aus den TC Loader startet. Also lass ich es lieber vorerst.


Was mich an der ganzen Sache extrem anpisst ist die Tatsache, dass ich in Linux meine Windows Partition nicht einbinden kann. TC beschwert sich zunächst über die Tatsache, dass die Systemverschlüsselung grundsätzlich verschieden ist zur Partitionsverschlüsselung. Wähle ich explizit Systemverschlüsselung so erzählt es mir irgendwelche wilden Geschichten über ASCII und Englische Tastaturen was in meinem Fall aber kaum ein Problem darstellen sollte.

Warum auch immer, ich komme aus dem Linux heraus nicht auf die Windows Partition. Sehr ärgerlich. Ich hatte zwar die Linux Partition mit 30G etwas größer bemessen um mehr Quellcode und Object-Dateien unterbringen zu können, aber für meine Musik- oder Filmsammlung reicht dies nicht aus. Mal sehn was sich da noch machen lässt, vielleicht muss ich doch etwas mit Tastaturlayout spielen.


newer posts
older posts