Titanium Mobile – Vermeiden und Aufspüren von Memory Leaks in Android und iOS – Teil 2

In Teil 1 wurde erklärt, wie Sie Memory Leaks in Titanium Mobile vermeiden. Diese Fortsetzung erklärt das Aufspüren von Memory Leaks.

iOS: Memory Leaks finden

In iOS lässt sich relativ einfach heraus finden, ob Memory Leaks existieren. Gehen Sie dazu wie folgt vor:

  1. Starten Sie Ihre iOS Anwendung im iPad- oder iPhone-Simulator
  2. Rufen Sie das Programm „Instruments“ aus dem Ordner „/Developer/Applications“ auf
  3. Wählen Sie das Template „Allocations“
  4. Wählen Sie bei „Choose Target“ den Simulator aus. Diesen erkennen Sie am Namen Ihrer iOS App
  5. Drücken Sie den roten „Record“ Button um die Aufzeichnung zu starten
  6. Ich empfehle Ihnen, rechts oben im Texteingabefeld „Instrument Detail“ nach „TiUI“ zu filtern. Dadurch werden nur noch Titanium UI-Objekte angezeigt.

Das weitere Vorgehen erläutere ich Ihnen am Beispiel der Open Source Anwendung Piwik Mobile. In diesem Falle gilt es heraus zu finden, ob das Fenster „Einstellungen“ Leaks hat. Dazu habe ich die App gestartet, den zuvor genannten Filter „TiUI“ gesetzt, Instruments an den Simulator gekoppelt und die Aufzeichnung gestartet.

In Piwik Mobile öffne ich nun das Fenster „Einstellungen“. Instruments sieht danach wie folgt aus:

Zunächst sehen Sie am Graphen links oben, dass der Speicherverbrauch angestiegen ist. Weiter unten bei „Object Summary“ sehen Sie die erstellten Titanium Objekte. Folgendes bedeuten die einzelnen Felder:

Category Der Name des Titanium Objektes
Live Bytes Wie viel Speicher im Moment dadurch belegt wird
Living Die Anzahl der Objekte, die gerade im Speicher sind
Transitory Wie viele Objekte bereits bereinigt wurden
Overall Bytes Hier wird auch Speicher mit einberechnet, der bereits freigegeben wurde
Overall Wie viele Objekte bisher insgesamt erzeugt wurden. Auch die Objekte, die bereits freigegeben wurden, zählen hier mit.

Im konkreten Fall sehen Sie, dass das Fenster „Einstellungen“ 15 Labels enthält, eine TableView, zehn TableViewRow’s, vier TableViewSection’s, ein Fenster usw. Diese Zahlen finden Sie in der Spalte „Living“.

Als nächstes schließe ich das Fenster über den „Zurück“ Button. Sämtliche zuvor erstellten UI-Objekte werden danach nicht mehr benötigt und sollten aufgeräumt werden.

Sie sehen nun im Graphen links oben, dass nach dem Schließen der Speicherverbrauch enorm herunter gegangen ist. Zudem befinden sich weniger Einträge in der „Object Summary“. Das bedeutet, dass alle Objekte aufgeräumt wurden, von denen kein Eintrag mehr zu sehen ist. Allerdings wurde eine View, ein Fenster und eine ButtonBar nicht aufgeräumt. Es sind also Memory Leaks vorhanden! Nun sollte im Code nachgeschaut werden, warum diese Objekte nicht freigegeben wurden. Sehr wahrscheinlich existieren noch Referenzen.

Wenn Sie im linken Menü „Allocation Lifespan“ den Wert „All Objects Created“ auswählen, sehen Sie die aufgeräumten Objekte. Standardmäßig ist „Created & Still Living“ aktiviert. In dieser Ansicht sehen Sie nur die Objekte, von denen mindestens eines aktuell im Speicher ist. Sobald ein Objekt vom GC freigegeben wurde, wird der Wert in der Spalte „Living“ um eins reduziert und die Spalte „Transitory“ um eins erhöht.

In diesem Fall existieren zum Beispiel keine Labels mehr, aber 18 Stück konnten aufgeräumt werden.

Lassen Sie sich nicht davon beirren, wenn die Zahl in der Spalte „Transitory“ wächst. Dies ist ein gutes Zeichen! Die Anzahl in der Spalte „Living“ sollte bei 0 oder konstant bleiben, je nachdem was für eine Aktion Sie ausführen. Öffnen und schließen Sie zum Beispiel öfter hintereinander das gleiche Fenster, sollte die Zahl bei Living nicht ansteigen, nur die Zahl in Transitory.

Sie können auch einen Blick auf den kompletten Speicherverbrauch werfen. Entfernen Sie dazu den Filter „TiUI“ rechts oben.

Zu sehen ist, dass das geöffnete Fenster „Einstellungen“ etwas mehr als 1MB Speicher belegt (Overall Bytes). Nach dem Schließen des Fensters beträgt der Verbrauch nur noch 26KB (Live Bytes). Optimalerweise steht hier 0KB. Dieser Wert ist aber in Ordnung. Durch das Entfernen der zuvor genannten Leaks sollte dieser Wert gegen 0 gehen.

Android: Memory Leaks finden

Bei Android ist das Aufspüren von Memory Leaks in Titanium Mobile Apps leider nicht ganz so einfach. Auf eine so detaillierte Anzeige wie bei iOS müssen Sie verzichten. Sie haben hauptsächlich die Möglichkeit, den generellen Speicherverbrauch im Blick zu behalten. Dazu gehen Sie wie folgt vor:

  1. Öffnen Sie Ihre Android App im Simulator
  2. Starten Sie die Anwendung DDMS. Dieses Programm befindet sich im Verzeichnis „tools“ des Android-SDK’s
  3. Wählen Sie Ihre Anwendung in der linken Auswahlliste von DDMS aus
  4. Aktivieren Sie „Show heap updates“ (Icon ganz links oben)
  5. Wechseln Sie in den Tab „VM Heap“
  6. Drücken Sie „Cause GC“. Links davon erscheint danach wie viel Speicher die Anwendung gerade alloziert, wie groß der Heap ist usw.

Auch in diesem Beispiel erläutere ich das weitere Vorgehen am Beispiel der Piwik Mobile App. In DDMS sehen Sie, dass die App nach dem Start 3,42MB Speicher benötigt.

Als nächstes öffne ich wie unter iOS das Fenster „Einstellungen“. Sobald dieses Fenster komplett geladen ist, drücke ich erneut den „Cause GC“ Button. Dadurch aktualisiert sich der angezeigte Verbrauch. Sie sehen, dass der Verbrauch von 3,42MB auf 3,56MB angestiegen ist.

Nun schließe ich das Fenster „Einstellungen“ um zu sehen, ob der Speicherverbrauch danach herunter geht. Optimalerweise beträgt der Wert in der Spalte „Allocated“ danach wieder 3,42MB. Leider ist es nicht ganz so einfach. Das Freigeben von Speicher ist ein aufwendiger Prozess und es wird durch den „Cause GC“ Button nicht immer unbenötigter Speicher freigegeben. Teilweise wird der Speicher erst dann aufgeräumt, wenn das verfügbare Memory Limit knapp wird. Das Limit beträgt bei Android meist zwischen 16 und 32MB.

Daher bleibt Ihnen oft nichts anderes übrig, als die gleiche Aktion mehrmals auszuführen. Beobachten Sie dabei, wie sich der Speicherverbrauch verhält. Wird der benötigte Speicher mit der Zeit nicht höher bzw. wird immer wieder Speicher freigegeben, ist alles in Ordnung. Erhalten Sie einen „OutOfMemory“ Fehler, sollten Sie auf alle Fälle Ihren Code überprüfen.

Wenn unter iOS keine Leaks existieren, haben Sie in der Regel auch unter Android keine Probleme damit. Allerdings sollten Sie darauf achten, dass plattformspezifische Codestellen keine Leaks verursachen.

Beispiel:

if (isAndroid) {
    // Führe diese Aktion nur in Android aus.
    var label = Ti.UI.createLabel({text: 'Leak'});
    Ti.UI.currentWindow.add(label)
}

Hier würde der Label unter Umständen nicht aufgeräumt werden. Dieser wird nur in Android erzeugt und ist dadurch unter iOS nicht sichtbar.

Zum Schluss noch ein Tipp:

Im Tab „Emulator Control“ können Sie die Internet-Geschwindigkeit begrenzen, Anrufe sowie SMS an den Simulator senden und den Standort ändern.

Dieser Eintrag wurde veröffentlicht in Development, JavaScript von Thomas Steur. Setze ein Lesezeichen zum Permalink.

Über Thomas Steur

Thomas Steur ist Senior Developer bei der Mayflower GmbH und arbeitet hier hauptsächlich an großen PHP- und JavaScript-Projekten. In seiner Freizeit entwickelt er seit 3 Jahren die offizielle Piwik Mobile App für iOS und Android, die auf dem Titanium Mobile SDK basiert. Er twittert unter @tsteur und ist außerdem auf Google+ sowie GitHub zu finden.

Für neue Blogupdates anmelden:


Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht.