Rheinwerk Computing < openbook > Rheinwerk Computing - Professionelle Bücher. Auch für Einsteiger.
Professionelle Bücher. Auch für Einsteiger.

Inhaltsverzeichnis
Geleitwort
Vorwort
1 Hello iPhone
2 Die Reise nach iOS
3 Sehen und anfassen
4 Alles unter Kontrolle
5 Daten, Tabellen und Controller
6 Models, Layer, Animationen
7 Programmieren, aber sicher
8 Datenserialisierung und Internetzugriff
9 Multimedia
10 Jahrmarkt der Nützlichkeiten
Stichwort

Buch bestellen
Ihre Meinung?

Spacer
Apps programmieren für iPhone und iPad von Klaus M. Rodewig, Clemens Wagner
Das umfassende Handbuch
Buch: Apps programmieren für iPhone und iPad

Apps programmieren für iPhone und iPad
Rheinwerk Computing
1172 S., geb., mit DVD
49,90 Euro, ISBN 978-3-8362-2734-6
Pfeil 6 Models, Layer, Animationen
Pfeil 6.1 Modell und Controller
Pfeil 6.1.1 iOS Next Topmodel
Pfeil 6.1.2 View an Controller
Pfeil 6.1.3 Gerätebewegungen auswerten
Pfeil 6.1.4 Modell an Controller
Pfeil 6.1.5 Undo und Redo
Pfeil 6.1.6 Unit-Tests
Pfeil 6.2 Als die Views das Laufen lernten
Pfeil 6.2.1 Animationen mit Blöcken
Pfeil 6.2.2 Transitionen
Pfeil 6.2.3 Zur Animation? Bitte jeder nur einen Block!
Pfeil 6.3 Core Animation
Pfeil 6.3.1 Layer
Pfeil 6.3.2 Vordefinierte Layer-Klassen
Pfeil 6.3.3 Der Layer mit der Maske
Pfeil 6.3.4 Unser Button soll schöner werden
Pfeil 6.3.5 Spieglein, Spieglein an der Wand
Pfeil 6.3.6 Der bewegte Layer
Pfeil 6.3.7 Daumenkino
Pfeil 6.3.8 Relativitätstheorie
Pfeil 6.3.9 Der View, der Layer, seine Animation und ihr Liebhaber
Pfeil 6.3.10 Transaktionen
Pfeil 6.3.11 Die 3. Dimension
Pfeil 6.4 Scrollviews und gekachelte Layer
Pfeil 6.4.1 Scrollen und Zoomen
Pfeil 6.4.2 Die Eventverarbeitung
Pfeil 6.4.3 Scharfe Kurven
Pfeil 6.4.4 Ganz großes Kino
Pfeil 6.4.5 PDF-Dateien anzeigen
Pfeil 6.5 Über diese Brücke musst du gehen
Pfeil 6.5.1 Toll-free Bridging und ARC
Pfeil 6.5.2 C-Frameworks und ARC
Pfeil 6.6 Was Sie schon immer über Instruments wissen wollten, aber nie zu fragen wagten
Pfeil 6.6.1 Spiel mir das Lied vom Leak
Pfeil 6.6.2 Ich folgte einem Zombie
Pfeil 6.6.3 Time Bandits
Pfeil 6.6.4 Instruments und der Analyzer

Rheinwerk Computing - Zum Seitenanfang

6.6Was Sie schon immer über Instruments wissen wollten, aber nie zu fragen wagtenZur nächsten Überschrift

Und nun zu etwas ganz anderem: Wie gut kennen Sie eigentlich noch die Speicherverwaltungsregeln? In welchen Fällen hält noch mal eine Variable das Objekt, auf das sie verweist? Und wie war das noch mal bei Core Foundation? Wenn Sie sich jetzt unsicher sind, dürfen Sie natürlich gerne zurückblättern. Allerdings wird Ihnen auch dann, wenn Sie die Regeln und ihre Anwendung beherrschen, wahrscheinlich von Zeit zu Zeit der eine oder andere Speicherverwaltungsfehler unterlaufen. Wenn Sie Glück haben, sendet Ihnen Ihr Programm zarte Hinweise. Im schlechtesten Fall macht es das indes nur bei den Nutzern Ihrer App. Nach Murphys Gesetz – »Was schiefgehen kann, geht schief« – ist Letzteres der Regelfall.

Sie können und sollten den Analyzer über Ihren Programmcode laufen lassen und versuchen, möglichst alle Warnungen zu beseitigen. Leider findet auch der Analyzer nicht alle Fehler, und auch mit dem Debugger mogelt sich schon mal die eine oder andere Schwachstelle durch. Es gibt jedoch noch eine weitere Möglichkeit, Schwachstellen im Programm zu finden: Instruments und Arbeit. Da Sie von Arbeit sicherlich schon mal gehört haben, dreht sich dieser Abschnitt hauptsächlich um Instruments.

Instruments ist ein Programm aus den Entwicklungswerkzeugen von Apple, das Sie bereits zusammen mit dem SDK installiert haben. Es erlaubt die Aufzeichnung und anschließende Analyse unterschiedlicher Messwerte Ihrer Programme, um deren Schwachstellen zu finden. Es kann Ihnen jedoch nur Hinweise geben, wo Sie nach den Schwachstellen suchen müssen. Es macht Ihnen leider keine Vorschläge zu deren Behebung.

Instruments funktioniert dabei nach einem Baukastensystem, bei dem jeder Baustein ein Messinstrument ist. Sie können für Ihre Instruments-Sitzungen diese Bausteine beliebig kombinieren. Zurzeit bietet Instruments ungefähr fünfzig solcher Messinstrumente an, von denen allerdings einige OS X vorbehalten sind.

Sie starten Instruments, indem Sie den Button Run oben links in Xcode gedrückt halten und im Dropdown-Menü den Punkt Profile auswählen (siehe Abbildung 6.42).

Abbildung

Abbildung 6.42 Starten von Instruments

Nach dem Start öffnet Instruments den in Abbildung 6.43 dargestellten Auswahldialog, mit dem Sie ein bestehendes Instruments-Dokument oder eine Dokumentvorlage auswählen können. In der Regel benutzen Sie die zweite Option. Hier bietet Ihnen Instruments bereits eine Palette mit vorkonfigurierten Mess-Szenarien an. Alternativ können Sie auch eine leere Vorlage auswählen, die Sie individuell nach Ihren Bedürfnissen konfigurieren können. Für den Anfang sollten Sie lieber ein vorkonfiguriertes Szenario verwenden. Falls Instruments Ihr Programm sofort startet, ohne vorher den Auswahldialog anzuzeigen, haben Sie wahrscheinlich das Programm noch in Instruments geöffnet. Schließen Sie also am besten immer alle Fenster von Instruments, bevor Sie eine neue Analyse starten.

Abbildung

Abbildung 6.43 Auswahldialog in Instruments

Operation am lebenden Programm

Damit Sie einen anschaulichen Eindruck von Instruments bekommen, finden Sie auf der beiliegenden DVD und im Git-Repository zum Buch das Beispielprojekt Instruments. Den Quellcode finden Sie auf der DVD unter Code/Apps/iOS6/Instruments oder im Github-Repository zum Buch im Unterverzeichnis https://github.com/Cocoaneheads/iPhone/tree/Auflage_3/Apps/iOS6/Instruments.

Die App stellt verschiedene Analysesituationen bereit und enthält deshalb absichtlich Schwachstellen für die nachfolgend beschriebenen Mess-Szenarien, und alle nachfolgenden Beispiele beziehen sich auf diese App. Die Schwachstellen im Beispielprojekt sind relativ offensichtlich. Wahrscheinlich verstecken sie sich in Ihren Programmen wesentlich besser. Hier kommt dann das zweite Gegenmittel ins Spiel: Arbeit.


Rheinwerk Computing - Zum Seitenanfang

6.6.1Spiel mir das Lied vom LeakZur nächsten ÜberschriftZur vorigen Überschrift

Eine der wichtigste Aufgabe von Instruments ist das Auffinden von Speicherlecks. Speicherlecks führen im schlimmsten Fall nicht direkt zu einem Fehlverhalten Ihres Programms. Stattdessen erhält es vom Betriebssystem Speicherwarnungen, deren Verarbeitung die App verlangsamen. Schließlich stürzt das Programm dann doch ab, wobei sich die Absturzsituation nur sehr schwer reproduzieren lässt.

Das automatische Referenzzählen verhindert zwar in vielen Fällen Speicherlecks; es gibt dennoch viele Situationen, in denen Speicherlecks auftreten können:

  1. bei Einsatz der C-Frameworks von Apple (z. B. Core Foundation, Core Graphics)
  2. bei Verwendung von malloc, calloc, new (C++) oder anderer Speicherverwaltungsfunktionen und -operatoren
  3. beim Einsatz von Bibliotheken mit manuellem Referenzzählen
  4. Retain-Zyklen; also Objekte, die sich gegenseitig im Speicher halten, wie beispielsweise Erna und Fritz in Kapitel 2, »Die Reise nach iOS«

Die Vorlage Leaks mit dem gleichnamigen Messinstrument kann Ihnen helfen, auch solche Speicherverwaltungsfehler zu finden.

Öffnen Sie das Instruments-Projekt in Xcode, und starten Sie Instruments wie oben beschrieben. Im Auswahldialog (siehe Abbildung 6.43) wählen Sie die Schablone Leaks aus, mit der Sie Speicherlecks finden können. Instruments startet Ihre App, abhängig von Ihrer Auswahl in Xcode, im Simulator oder auf einem iOS-Gerät. Außerdem öffnet es das in Abbildung 6.44 dargestellte Fenster. Die Schablone erzeugt zwei Messinstrumente, die Sie in der linken Spalte oben finden. Mit Allocations messen Sie den Speicherverbrauch Ihrer App, während Leaks die Speicherlecks aufzeichnet. Wenn Sie im oberen Bereich des Fensters ein Messinstrument auswählen, zeigt Instruments Ihnen im unteren Bereich dazu Detailinformationen an.

Abbildung

Abbildung 6.44 Speicheranalyse mit Instruments

Nach dem Start erscheint neben Allocations ein blaues »Gebirge«, das den verbrauchten Speicher der symbolisiert. Dabei stellen die Höhen keine absoluten, sondern relative Werte zum maximalen Speicherverbrauch dar, und Sie erkennen große Speicherreservierungen daran, dass weiter links liegende Teile des Gebirges plötzlich abflachen.

Der Bereich neben Leaks bleibt zunächst leer, da das Programm bislang noch kein Speicherleck erzeugt hat. Wenn Sie jedoch den Knopf malloc in der iPhone-App drücken, erscheint im Leaks-Bereich nach einer Verzögerung ein roter Balken (siehe Abbildung 6.45). Der Balken kennzeichnet das Auftreten eines Speicherlecks.

Abbildung

Abbildung 6.45 Grafische Anzeige eines Speicherlecks in Instruments

Oben links im Fenster befindet sich der Button Stop. Damit können Sie die Ausführung der App beenden, wenn Sie genug Leaks gesammelt haben. Durch Auswählen des Leaks-Instruments in der Spalte Instruments wie in Abbildung 6.45 zeigt das Programm im unteren Fensterbereich Details zu den gefundenen Leaks an. In der linken Spalte können Sie die Einstellungen des Instruments anpassen, während der Bereich auf der rechten Seite die gefundenen Speicherlecks auflistet (siehe Abbildung 6.46).

Abbildung

Abbildung 6.46 Details des Leaks-Instruments

Einstellungssache

Leaks sammelt die Speicherlecks in regelmäßigen Intervallen. Die Intervall-Länge ist standardmäßig auf zehn Sekunden eingestellt, weswegen Instruments den roten Balken für das Speicherleck auch erst mit einer Verzögerung anzeigt. Über das Eingabefeld Snapshot interval können Sie diesen Wert anpassen. Das geht auch, während eine Messung läuft. Sie können diese Wartezeit allerdings auch durch Drücken des Buttons Snapshot Now abkürzen. Dann sammelt Leaks augenblicklich alle Speicherlecks.

Wenn Sie den Pfeil eines Speicherlecks in der Spalte Address (siehe den Mauszeiger in Abbildung 6.46) anklicken, gelangen Sie zu den Details des Lecks. Hier sehen Sie unter anderem den Referenzzähler und die Erzeugungszeit relativ zum Programmstart. Durch Drücken des Reiters Leaks by Backtrace gelangen Sie wieder zurück zur Übersicht mit allen Speicherlecks.

Sie können sich über ª+cmd+E oder den Menüpunkt ViewExtended Detail den Aufrufstapel anzeigen lassen (siehe Abbildung 6.47), der zu der Programmstelle führt, an der das Programm den Speicher des Lecks reserviert hat. Sie bekommen darüber in vielen Fällen einen recht guten Hinweis, wo Sie mit der Fehlersuche für die Speicherverwaltung beginnen sollten.

Durch einen Doppelklick auf eine Zeile im Aufrufstapel können Sie sich die entsprechende Stelle im Quellcode anzeigen lassen. Das funktioniert natürlich nur für Symbole, deren Quellcode zum Projekt gehört. In der Regel sind das die Zeilen mit dem schwarzen User-Symbol, wie beispielsweise bei der ausgewählten Zeile in der Abbildung. Wenn Sie einen Doppelklick auf Zeile im Stapel ausführen, die in Abbildung 6.47 hervorgehoben ist, zeigt Instruments Ihnen die folgende Zeile an:

Abbildung

Abbildung 6.47 Anzeige eines einfachen Lecks mit Aufrufstapel

Abbildung

Abbildung 6.48 Hier erzeugt die App ein Speicherleck.

Sie befindet sich in der Methode makeMallocLeak. Die Anweisung reserviert Speicher und weist ihn einer lokalen Variablen zu. Da die Methode diesen Speicher allerdings nicht wieder freigibt und ihn auch nicht weitergibt, so dass ihn eine andere Methode freigeben könnte, entsteht hier ein Speicherleck. Dieser Speicherverwaltungsfehler ist also ziemlich offensichtlich, und auch der Analyzer entdeckt diesen Fehler.

Zurück auf Los

Sie können von der Detailansicht zu den allgemeineren Ansichten zurückkehren, indem Sie auf die Pfeilsymbole oberhalb der Detailansicht (siehe die oberste Zeile in Abbildung 6.46) klicken.

Außerdem können Sie in jeder Ansicht die Spaltenanzeige durch einen Rechtsklick auf die Titelleiste an Ihre Bedürfnisse anpassen. Dadurch können Sie einzelne Spalten ausblenden. Die Reihenfolge der Spalten verändern Sie durch Verschieben der Spaltenköpfe und die Zeilensortierung durch einfaches Anklicken der Spaltenköpfe.

Über den Button Attribute in der App erzeugen Sie komplexere Speicherlecks. Damit Instruments ein Speicherleck erkennt, müssen Sie diesen Button allerdings mindestens zweimal drücken. Wenn Sie sich danach die Details dieses Lecks ansehen, zeigt Instruments Ihnen mehrere Zeilen statt einer Zeile an (siehe Abbildung 6.49).

Dabei enthält jede Zeile eine Speicherverwaltungsoperation, und der Spalte Event Type können Sie die jeweilige Operation entnehmen. Da der Fehler aus dem Programm und nicht aus den Systembibliotheken von Apple stammt, brauchen Sie nur die Zeilen zu analysieren, die Instruments in der Spalte Responsible Library stehen haben. Außerdem können Sie durch Aktivieren des Buttons Unpaired alle Ereignisse ausblenden, die Instruments als unproblematisch erkannt hat. Dadurch bleibt in der Übersicht eine Zeile aus dem Programm mit dem Ereignistyp Retain übrig; es ist die selektierte Zeile in Abbildung 6.49.

Abbildung

Abbildung 6.49 Detailanzeige für ein komplexeres Leck

In der Spalte Responsible Caller sehen Sie die Methode, die die Operation aufruft. In der ausgewählten Zeile steht dort beispielsweise –[InstrumentsViewController makeAttributeLeak]. Dieses Retain hat also die Methode makeAttributeLeak im InstrumentsViewController ausgelöst. Auch diese Methode scheint sich an die Speicherverwaltungsregeln zu halten, und beim ersten Aufruf erzeugt sie ja auch noch kein Leck (siehe Listing 6.108).

Instruments und die Systembibliotheken

Zu dieser Zeile kann Instruments Ihnen keinen Quellcode anzeigen, da es keinen Zugang dazu hat. Der Quellcode für den Autoreleasepool befindet sich schließlich bei Apple und ist nicht öffentlich. Für die Überprüfung Ihrer Speicherverwaltung ist das auch nicht notwendig. Außerdem sollten Sie die Möglichkeit, dass Cocoa Touch ein Speicherleck erzeugt, erst nach Ausschluss aller anderen Möglichkeiten in Betracht ziehen. [Anm.: Es gibt durchaus einige bekannte Speicherlecks in Cocoa Touch; die Wahrscheinlichkeit, dass Ihr Code den Fehler verursacht, ist jedoch wesentlich höher.]

- (IBAction)makeAttributeLeak {
_attributeLeak = [[InstrumentsDemoObject object] retain];
}

Listing 6.108 Speicherleck bei Attributzuweisung

Wenn Sie die Methode indes wiederholt ausführen, gibt sie jedoch das Objekt, auf das _attributeLeak verweist, nicht frei. Nach den Speicherverwaltungsregeln muss sie das allerdings machen, da die Variable das Objekt ja hält. Um diesen Speicherverwaltungsfehler zu beheben, sollten Sie lieber den Setter verwenden.

- (IBAction)makeAttributeLeak {
self.attributeLeak = [InstrumentsDemoObject object];
}

Listing 6.109 Methode ohne Speicherleck

Speicherverwaltung

Der Speicherverwaltungsfehler in der Methode makeAttributeLeak ist für Anfänger schwer zu erkennen, und sogar der Analyzer in Xcode findet ihn nicht. Sie können solche Fehler jedoch durch die konsequente Verwendung von Accessoren vermeiden.

Es können auch mehrere Objekte ein Speicherleck erzeugen. Wenn Sie den Button Retain Cycle in der Beispiel-App drücken, zeigt Ihnen Instruments drei Zeilen in der Übersicht an, und wenn Sie sich über den Aufrufstapel den entsprechenden Quellcode anzeigen lassen, markiert Instruments auch drei Zeilen anstatt einer (siehe Abbildung 6.50).

Abbildung

Abbildung 6.50 Mehrere Verursacher eines Speicherlecks

Das Leck entsteht hier durch zwei Arrays, die sich gegenseitig enthalten, also einen Retain-Zyklus erzeugen. Obwohl nur zwei Objekte dieses Leck erzeugen, zeigt Instruments drei Speicherbereiche an. Kann Instruments etwa nicht zählen?

Wenn Sie die markierten Stellen in Abbildung 6.50 betrachten, sind die beiden ersten offensichtlich richtig; hier reserviert die Methode Speicher für die beiden Arrays. Die dritte Markierung liegt bei dem Methodenaufruf von addObject:. Da ein veränderliches Objekt jedoch nahezu beliebig viele Objekte aufnehmen kann, muss es seinen Speicher bei Bedarf vergrößern können, und das ist anscheinend hier geschehen.


Rheinwerk Computing - Zum Seitenanfang

6.6.2Ich folgte einem ZombieZur nächsten ÜberschriftZur vorigen Überschrift

Was passiert eigentlich, wenn Sie ein Objekt hinter einem Dangling Pointer weiterverwenden? Die Antwort ist nichts für schwache Nerven, lieber Leser, denn es entsteht ein Zombie, der in Ihrem Speicher Angst und Schrecken verbreitet. Das Schlimme an Zombies ist, dass das von ihnen angerichtete Unheil erst lange nach seiner Entstehung auftreten kann.

In Ihrer App entsteht ein Zombie, wenn Sie einen Verweis auf ein Objekt verwenden, nachdem Sie es freigegeben haben. Die Freigabe muss dabei indes nicht unbedingt über die gleiche Variable wie der Zombie-Zugriff erfolgen. Das erschwert natürlich die Suche nach diesen Ungeheuern.

Abbildung

Abbildung 6.51 Ein Zombie im Hauptspeicher

Abbildung 6.51 veranschaulicht einen Zombie im Hauptspeicher. Alles beginnt mit einem Objekt, das seine Daten irgendwo im Hauptspeicher schön ordentlich abgelegt hat 1. Irgendwann gibt das Programm den Speicherbereich dieses Objekts frei, obwohl es noch Referenzen auf dieses Objekt hat. Dadurch hat es einen Zombie erzeugt, und alle Verweise darauf sind Dangling Pointer 2. Der Zugriff auf dieses Objekt über die Dangling Pointer muss indes jetzt noch nicht zu einem Fehler oder Absturz führen, da der Speicherbereich ja in der Regel immer noch die Daten des ursprünglichen Objekts enthält, was die Abbildung durch graue Ziffern darstellt.

Jedes Mal, wenn das Programm danach ein neues Objekt anlegt, besteht jedoch die Möglichkeit, dass dieses neue Objekt den Speicherbereich des Zombies oder Teile davon belegt und überschreibt 3. Diese Situation kann unterschiedliche Fehler hervorrufen. Das Programm kann sich unvorhergesehen verhalten oder abstürzen. In der Regel bemerken Sie erst in dieser Situation, dass Ihr Programm einen Zombie enthält.

Die Beispiel-App Instruments erlaubt Ihnen auch die Erzeugung von Zombies. Sie brauchen dabei keine Angst zu haben. Sie machen das ja unter Laborbedingungen, und da kann Ihnen nichts passieren – na ja, fast nichts. Starten Sie die App über den Profile-Button aus Xcode in Instruments, und wählen Sie die Schablone Zombies im Auswahldialog aus.

Abbildung

Abbildung 6.52 Instruments hat einen Zombie entdeckt.

Nach dem Start zeigt Instruments Ihnen den Speicherverbrauch der App an. Wenn Sie zweimal auf den Button Object klicken, hält die Ausführung an. Instruments zeigt einen Dialog wie in Abbildung 6.52. Wenn Sie den Pfeil neben der Speicheradresse anklicken, gelangen Sie zu einer Auflistung der Speicherverwaltungsoperationen, die das Programm auf dem Objekt ausgeführt hat. Wenn Sie den Button By Time aktivieren, listet Instruments die Speicherverwaltungsereignisse ihrer zeitlichen Abfolge nach auf (siehe Abbildung 6.53). Auch hier können Sie wieder die unproblematischen Ereignisse über den Button Unpaired ausblenden.

Abbildung

Abbildung 6.53 Speicherverwaltungsoperationen eines Zombies

Die letzte Zeile enthält die Methode oder Funktion, die auf den Zombie zugegriffen hat. Es ist die Systemfunktion _NSDescriptionWithLocaleFunc, auf deren Quellcode Sie keinen Zugriff haben. Diese Funktion hat zwar auf den Zombie zugegriffen, sie hat ihn jedoch nicht erzeugt. Der Zombie ist durch das Release in der vorletzten Zeile entstanden, wie Sie an dem Referenzzähler sehen. Da dieses Release jedoch vom Autoreleasepool gesendet wurde, kann diese Zeile auch nicht direkt für den Fehler verantwortlich sein. Der Verursacher ist entweder das Autorelease der zweiten oder das Release der vierten Zeile.

Auch hier können Sie sich über den Aufruf von ViewExtended Detail oder ª+cmd+E jeweils den Aufrufstapel zu den Anweisungen auf der rechten Seite des Fensters anzeigen lassen. Der Stapel stellt alle Systemsymbole in grauer Schrift mit einem farbigen Icon dar. Dagegen stellt er die Symbole aus Ihrem Programmcode in schwarzer Schrift mit einem schwarzen Icon dar. Abbildung 6.54 zeigt einen Ausschnitt eines Aufrufstapels. Mit einem Doppelklick auf diese Symbole springen Sie an die entsprechende Stelle des Quelltextes.

Abbildung

Abbildung 6.54 Detailansicht und Ausschnitt des Aufrufstapels

Da sich der Convenience-Konstruktor object an die Speicherverwaltungsregeln hält, bleibt überraschenderweise nur die Methode makeZombie als Kandidat übrig.

- (IBAction)makeZombie {
id theZombie = [InstrumentsDemoObject object];
NSLog(@"zombies=%@", self.zombies);
[self.zombies addObject:theZombie];
[theZombie release];
}

Listing 6.110 Zombie-Erzeugung

Da die Methode object nicht auf die erste Speicherverwaltungsregel passt, hält die Variable theZombie nicht das Objekt. Also darf sie das Objekt auch nicht freigeben. Der Fehler liegt also in der letzten Zeile der Methode, die ein Release an die Variable theZombie sendet.

Automatisches Referenzzählen und Zombies

Von einem ARC-Compiler übersetzter Code sollte in der Regel keine Zombies mehr erzeugen, wenn Sie anstatt assign den Speicherverwaltungstyp weak in den Property-Deklarationen verwenden. Sie können zwar auch mit eingeschaltetem ARC Zombies erzeugen, indem Sie beispielsweise Void-Zeiger oder den Modifizierer __unsafe_unretained verwenden. Diese Fälle sollten in der Praxis allerdings extrem selten auftreten.


Rheinwerk Computing - Zum Seitenanfang

6.6.3Time BanditsZur nächsten ÜberschriftZur vorigen Überschrift

Instruments hilft Ihnen allerdings nicht nur beim Finden von Speicherverwaltungsfehlern, sondern es kann auch andere Schwachstellen des Programms aufdecken. Zu den gesuchtesten Schwachstellen in Programmen gehören die Methoden und Funktionen, die Ihr Programm langsam und schwerfällig machen. Mit dem Messinstrument Time Profiler können Sie wunderbar den Zeitverbrauch Ihrer Methoden und Funktionen messen.

Je öfter Sie im Instruments-Beispielprogramm auf den Button Compute Sum drücken, umso länger braucht die App für die Berechnung der angezeigten Werte. Anscheinend ist die Implementierung also für größere Werte unzureichend. Um dem Zeitfresser auf die Spur zu kommen, starten Sie das Programm in Instruments aus Xcode heraus. Im Auswahldialog wählen Sie die Schablone Time Profiler aus.

Nach dem Start der App bleibt der untere Bereich zunächst leer. Wenn Sie einige Male den Button Compute Sum drücken, füllt Instruments die Anzeige mit Funktions- und Methodennamen. Stellen Sie die Sortierung nach der ersten Spalte, Running Time, absteigend ein. Sie zeigt Ihnen den absoluten und den relativen Zeitverbrauch für die Ausführung des jeweiligen Symbols. Wenn Sie auf der linken Seite in der Rubrik Call Tree die Option Separate by Thread aus- und die Option Top Functions einschalten, zeigt Instruments wesentlich mehr Zeilen in der Übersicht an. Viele Zeilen enthalten jedoch C-Funktionen oder Methoden aus den Systembibliotheken. Sie können diese Zeilen über die Option Hide System Libraries ausblenden. Durch diese Einstellungen sollte die Anzeige ungefähr so wie in Abbildung 6.55 aussehen.

Abbildung

Abbildung 6.55 Gefilterter Aufrufstapel

An den relativen Zeiten (Prozentzahlen) sehen Sie, dass sich in der Übersicht einige Zeitfresser befinden. Beispielsweise hat das zweite Symbol von oben, die Methode computeSum in der Klasse InstrumentsDemoObject, einen Zeitverbrauch von über 90 %. Anscheinend hat diese Methode einen gehörigen Hunger auf die wertvolle Rechenzeit. Allerdings verbraucht diese Methode nicht die Zeit für sich allein, sondern ruft andere Methoden auf, die ebenfalls sehr zeitraubend sind. Sie können das überprüfen, indem Sie den Eintrag durch Anklicken des Dreiecks neben dem Symbolnamen aufklappen.

Durch einen Doppelklick auf eine Zeile in der Übersicht zeigt Instruments den Quellcode des Symbols an. Instruments hebt hierbei die Zeilen mit höherem Zeitverbrauch hervor und zeigt den relativen Zeitverbrauch bezogen auf den Gesamtzeitverbrauch der Methode an (siehe Abbildung 6.56). Falls dort keine Prozentzahlen stehen, können Sie die Ansicht über das Zahnradsymbol rechts über dem Quelltext anpassen. Wählen Sie dort den Punkt View as Percentage aus.

Abbildung

Abbildung 6.56 Zeitverbrauch der Anweisungen in einer Methode

Durch Anklicken des grauen Kreises mit dem »i« können Sie sich den Aufrufstapel für diese Zeile ansehen. Dort finden Sie als unterstes Symbol die Methode sum, und Sie gelangen durch einen Doppelklick auf dieses Symbol zu dieser Methode. Auf diese Weise können Sie sich immer weiter durch die Methoden des Programms hangeln, um vielleicht den Zeitfresser zu finden.

Anscheinend verbraucht die Methode sum ihre Rechenzeit fast komplett im Schleifenrumpf für den Aufruf der Methode successorWithIndex: (siehe Abbildung 6.57). Instruments hebt diese Zeile freundlicherweise rot hervor und unterstreicht den Methodennamen.

Abbildung

Abbildung 6.57 Dem Zeitverbrauch auf der Spur ...

Wenn Sie den Methodennamen anklicken, gelangen Sie zum Quelltext dieser Methode. Auch hier zeigt Instruments Ihnen wieder den relativen Zeitverbrauch der Zeilen in Prozent an. Diese Methode verbraucht den größten Teil ihrer Rechenzeit für den Aufruf des Getters successor. Dabei hängen die genauen Zahlen natürlich davon ab, wie oft Sie den Button gedrückt haben.

Abbildung

Abbildung 6.58 ... die anscheinend im Nichts endet

Da es sich um eine synthetisierte Property handelt, sieht das zunächst nach einer Sackgasse aus. Ein einzelner lesender Property-Aufruf verbraucht natürlich nicht so viel Zeit. Allerdings befindet er sich in einer Schleife, genau wie die Methode successorWithIndex:. Die Anzahl der Schritte der inneren Schleife hängt von dem Parameter inIndex ab. Dessen Wert ist der Schleifenindex der äußeren Schleife. Wenn die äußere Schleife bis 8 läuft, dann ruft die App successorWithIndex: insgesamt 8-mal auf und liest die Property 0 + 1 + 2 + 3 + 4 + 5 + 6 + 7 = 28-mal aus. Bei einer Länge von 1.000 kommen schon 500.500 Zugriffe zustande, und bei 8.000 sind es gar über 32 Millionen. Das verbraucht natürlich auch einiges an Rechenzeit.

Zur Behebung dieses Performance-Leaks ist also eine Neuimplementierung von sum notwendig. Anstatt auf die verkettete Liste über einen Index zuzugreifen, sollte sich die Schleife lieber über einen Zeiger durch die Liste hangeln:

- (NSUInteger)sum {
NSUInteger theSum = 0;
InstrumentsDemoObject *theItem = self;
while(theItem) {
theSum += theItem.counter;
theItem = theItem.successor;
}
return theItem;
}

Listing 6.111 Effizientere Implementierung der Summenberechnung

Dieses Verfahren besucht jedes Listenelement nur einmal. Bei einer Listenlänge von 8.000 Einträgen liest diese Implementierung den Nachfolger auch nur 8.000-mal aus.

Das leidige Thema Arbeit

Instruments kann Ihnen nur Hinweise auf die Schwachstellen in Ihren Programmen liefern. Die Behebung überlässt es großzügigerweise Ihnen ganz allein. Für die Suche nach Speicherverwaltungsfehlern kommen Sie also trotz Instruments nicht um die Kenntnis der Regeln herum.

Die Zeiträuber in Ihrer App zu suchen und zu beseitigen ist da schon komplizierter. Zwar liefert der Time Profiler Ihnen hier gute Hinweise; doch die Probleme zu lösen ist unter Umständen sehr schwierig oder gar unmöglich. Es muss ja schließlich nicht immer ein effizienteres Verfahren für die entsprechende Aufgabe geben.


Rheinwerk Computing - Zum Seitenanfang

6.6.4Instruments und der AnalyzerZur vorigen Überschrift

Einige Schwachstellen des Beispielprojekts Instruments lassen sich auch ohne Instruments über den Analyzer finden. Wenn Sie für das Projekt den Menüpunkt ProductAnalyze aufrufen, zeigt Ihnen Xcode zwei Schwachstellen des Programms an, die Sie auch mit Hilfe von Instruments gefunden haben (siehe Abbildung 6.59).

Abbildung

Abbildung 6.59 Schwachstellen über den Analyzer finden

Die Bedienung des Analyzers ist zwar einfacher, und er beschreibt auch das Problem häufig viel besser, als Instruments das vermag. Allerdings findet er bei weitem nicht so viele Schwachstellen wie Instruments. Beispielsweise bleiben der Retain-Zyklus und Attribute mit Speicherlecks oder Zombies dem Analyzer verborgen, und auch die Zeitbanditen lassen sich nur mit Instruments genauer untersuchen.



Ihr Kommentar

Wie hat Ihnen das <openbook> gefallen? Wir freuen uns immer über Ihre freundlichen und kritischen Rückmeldungen.

>> Zum Feedback-Formular
<< zurück




Copyright © Rheinwerk Verlag GmbH, Bonn 2014
Für Ihren privaten Gebrauch dürfen Sie die Online-Version natürlich ausdrucken. Ansonsten unterliegt das <openbook> denselben Bestimmungen, wie die gebundene Ausgabe: Das Werk einschließlich aller seiner Teile ist urheberrechtlich geschützt. Alle Rechte vorbehalten einschließlich der Vervielfältigung, Übersetzung, Mikroverfilmung sowie Einspeicherung und Verarbeitung in elektronischen Systemen.


Nutzungsbestimmungen | Datenschutz | Impressum

Rheinwerk Verlag GmbH, Rheinwerkallee 4, 53227 Bonn, Tel.: 0228.42150.0, Fax 0228.42150.77, service@rheinwerk-verlag.de


  Zum Katalog
Zum Katalog: Apps programmieren für iPhone und iPad






Neuauflage: Apps programmieren für iPhone und iPad
Jetzt bestellen


 Ihre Meinung?
Wie hat Ihnen das <openbook> gefallen?
Ihre Meinung

 Buchempfehlungen
Zum Katalog: Einstieg in Objective-C 2.0 und Cocoa






Einstieg in Objective-C 2.0 und Cocoa


Zum Katalog: Spieleprogrammierung mit Android Studio






Spieleprogrammierung mit Android Studio


Zum Katalog: Android 5






Android 5


Zum Katalog: iPhone und iPad-Apps entwickeln






iPhone und iPad-Apps entwickeln


 Shopping
Versandkostenfrei bestellen in Deutschland und Österreich
InfoInfo