webentwicklung-frage-antwort-db.com.de

Warum erhalte ich Speicherwarnungen, wenn nur 7 MB Speicher zugewiesen sind?

Ich führe meine iOS-App auf dem iPod touch-Gerät aus und ich erhalte Speicherwarnungen, auch wenn die Gesamtzuweisungsspitze nur 7 MB beträgt wie unten gezeigt (dies geschieht, wenn die Spielszene gedrückt wird):

low memory warning

Was finde ich seltsam ist das:

  • die linke Spitze (zum Zeitpunkt 0,00) entspricht 20 MB zugewiesenem Speicher (Einführungsszene) und gibt trotzdem KEINE Speicherwarnung aus.

  • die zentrale Spitze (um 35.00 Uhr) entspricht ungefähr 7 MB zugewiesenem Speicher (Spielszene wird gepusht) und gibt eine Speicherwarnung aus.

Ich verstehe nicht, warum ich diese Warnungen erhalte, wenn der Gesamtspeicher nur 7 MB beträgt. Ist das normal? Wie kann ich das vermeiden?

Density peaks

Wenn wir uns die Zuordnungsdichte ansehen, sehen wir das folgende Schema, das (für mich) keinen großen Unterschied zwischen dem Moment, in dem die Intro-Szene verschoben wird (0,00) und dem Moment, in dem die Game-Szene verschoben wird (35,00), zeigt. Da die Dichtespitzen ähnlich sind, würde ich annehmen, dass die Speicherwarnungen auf etwas anderes zurückzuführen sind, das ich nicht erkennen kann.

BEARBEITEN:

Ich bin einem Vorschlag gefolgt, stattdessen "Aktivitätsmonitor" zu verwenden, aber leider stürzt meine App ab, wenn ich die Spielszene mit nur 30 MB Speicher zugewiesen lade. Hier ist der Aktivitätsmonitorbericht.

Activity monitor report

Wenn ich mir den Bericht ansehe, sehe ich eine Gesamtsumme der realen Speicherauslastung von ungefähr 105 MB. Da dies auf den Arbeitsspeicher von RAM verweisen sollte und mein Modell über 256 MB von RAM verfügen sollte, sollte dies keine APP-Abstürze oder Probleme mit Speicherlecks verursachen.

Ich verwende den Leckanzeiger und er zeigt kein Leck in meiner App an. Ich habe auch alle anderen Apps getötet.

Wenn ich den Bericht jedoch analysiere, sehe ich einen erstaunlichen 167 MB virtueller Speicher, der meiner App zugeordnet ist. Ist das normal? Was bedeutet dieser Wert? Kann dies der Grund für den Absturz sein? Wie kann ich erkennen, welche Bereiche meines Codes dafür verantwortlich sind?

Virtual memory

Mein iPod ist ein Modell der 4. Generation mit einer Kapazität von 6,4 GB (Speicher) und nur 290 MB freiem Speicher. Ich bin nicht sicher, ob sich dies auf die Leistung des virtuellen Speichers Paging auswirkt.

EDIT 2: Ich habe mir auch SpringBoard genauer angesehen und die Nutzung des virtuellen Speichers beträgt 180 MB. Ist das normal? Ich habe einige Fragen/Antworten gefunden, die darauf hindeuten, dass SpringBoard für die automatische Freigabe von Objekten verantwortlich ist (dies sollte der Prozess für die Verwaltung des Bildschirms und der Startseite sein, aber ich bin nicht sicher, ob dies auch mit der Speicherverwaltung zu tun hat). Ist das richtig?

Noch ein Hinweis. Ich benutze ARC. Ich bin mir jedoch nicht sicher, ob dies viel mit dem Problem zu tun hat, da es keine offensichtlichen Speicherverluste gibt und XCode den Code umwandeln sollte, indem Release/Dealloc/Retain-Aufrufe zur kompilierten Binärdatei hinzugefügt werden.

EDIT 3: Wie gesagt benutze ich ARC und Cocos2d (2.0). Ich habe mit dem Aktivitätsmonitor herumgespielt. Ich habe herausgefunden, dass der Aktivitätsmonitor einwandfrei funktioniert, wenn ich den GameCenter-Authentifizierungsmechanismus entferne (neuer Zweifel: hatte jemand ein ähnliches Problem? Wird die GameCenter-Authentifizierungsansicht irgendwo beibehalten?). Allerdings habe ich festgestellt, dass ich jedes Mal, wenn ich vor der GameScene zwischen den verschiedenen Szenen hin und her navigiere (Anfangsszene -> Charakterauswahl -> Planetenauswahl -> Charakterauswahl -> Planetenauswahl -> usw. -> Charakterauswahl ..), die REAL MEMORY usage nimmt zu. Nach einer Weile bekomme ich Speicherwarnungen und die App wird von iOS getötet. Nun ist die Frage:

-> Ersetze ich die Szenen richtig? Ich rufe aus den verschiedenen Szenen folgendes auf:

[[CCDirector sharedDirector] replaceScene: [MainMenuScene scene]];

Ich habe Cocos2d 2.0 als statische Bibliothek und der Code von replaceScene lautet wie folgt:

-(void) replaceScene: (CCScene*) scene
{
    NSAssert( scene != nil, @"Argument must be non-nil");

    NSUInteger index = [scenesStack_ count];

    sendCleanupToScene_ = YES;
    [scenesStack_ replaceObjectAtIndex:index-1 withObject:scene];
    nextScene_ = scene; // nextScene_ is a weak ref
}

Ich frage mich, ob die Szene irgendwie nicht richtig freigegeben wird. Ich habe überprüft, ob die Bereinigungsmethode aufgerufen wird, habe aber auch einen CCLOG-Aufruf für die CCLayer-Freigabemethode und Neuerstellung der statischen Bibliothek. Das Ergebnis ist, dass die Freigabemethode anscheinend nicht aufgerufen wird hinzugefügt.

Ist das normal? : D

Ich stellte fest, dass andere Leute ähnliche Probleme hatten. Ich frage mich, ob es mit Zyklen und Selbstblockaden zu tun hat. Ich muss wirklich etwas Zeit damit verbringen, dies zu studieren, es sei denn, ab EDIT 3 kann mir bereits jemand sagen, was ich falsch mache :-)

22
mm24

Ich löste dieses Problem, indem ich einen Ausdruck der effektiven Speichernutzung in der Konsole hinzufügte. Auf diese Weise konnte ich eine genaue Messung des vom App-Prozess verwendeten realen Speichers erhalten. Die Verwendung des Instruments erwies sich als ungenau, da der tatsächlich verwendete Speicher nicht mit dem auf den Instrumenten angezeigten übereinstimmte.

Mit diesem Code kann die effektive Speichernutzung ermittelt werden:

-(vm_size_t)report_memory
{    
    struct task_basic_info info;
    mach_msg_type_number_t size = sizeof(info);
    kern_return_t kerr = task_info(mach_task_self(),
                                   TASK_BASIC_INFO,
                                   (task_info_t)&info,
                                   &size);
    if( kerr == KERN_SUCCESS ) {
    } else {
        NSLog(@"Error with task_info(): %s", mach_error_string(kerr));
    }
    return info.resident_size;
}
0
mm24

Die gesamte Speicherkapazität, die von allen Apps und Prozessen gemeinsam genutzt wird, wird unter iOS ausgeführt. Andere Apps können also viel Speicher verbrauchen, und Ihre App erhält auch eine Speicherwarnung. Sie erhalten Speicherwarnungen, bis dies nicht mehr ausreicht.

Um zu verstehen, was mit dem Speicher in Ihrer App tatsächlich passiert, sollten Sie

  1. Profilieren Sie Ihre App mit Lecks (ARC garantiert nicht, dass Sie keine Lecks haben, d. H. Ein Problem mit der Selbsterfassung).

  2. Verwenden Sie die Heapshot-Analyse (hier kurz beschrieben http://bentrengrove.com/blog/2013/4/26/heapshot-analysis )

Und lesen Sie diesen Beitrag über Speicher und virtuellen Speicher in iOS: http://liam.flookes.com/wp/2012/05/03/finding-ios-memory/

3
ilya