11

Ho passato in rassegna molti post relativi alla gestione della memoria, ARC, tecniche di gestione della memoria come autoreleasepool e l'uso dello strumento strumenti per rilevare quale codice causa l'avvertimento della memoria ma in Nel mio caso non sono in grado di capire la causa esatta.Come trovare la vera causa di avviso di memoria e come risolvere nell'app per iOS

dettagli di base che è necessario conoscere l'applicazione:

  1. Abbiamo sviluppato un app iPad. In questo caso dobbiamo utilizzare più di 2000 immagini in alcuni casi, quindi quando la mia app non viene visualizzata non vogliamo mostrare loro un'immagine segnaposto (requisito del client). Per ottenere ciò, abbiamo utilizzato SDWebImage, archiviamo le immagini su disco e dopo di noi stanno caricando le immagini da lì.

  2. Ci sono così tante animazioni core che ho eseguito come "Gennie effect", display pop-up e tante altre core animazioni.

Abbiamo usato ARC nel nostro progetto e abbiamo scoperto che a causa di avviso di memoria applicazione si blocca in modo casuale.

Abbiamo usato Strumenti "Assegnazione" per trovare la memoria sporca.

In precedenza analizziamo i registri e abbiamo memorizzato le immagini con SDWebImage in DISK, risolve spesso il blocco dell'applicazione, ma l'app continua a bloccarsi a causa di un avviso di memoria.

Quando andiamo in profondità, abbiamo scoperto che "VM anonime" continua a incassare e non rilascia memoria quando si passa da uno schermo all'altro di iPad.

Ecco lo screenshot della profilazione della nostra app sul dispositivo.

enter image description here

Chiunque si prega di suggerire consigli o tecniche di codifica o di qualsiasi idea da cui possiamo ridurre il carico di memoria e risolvere avviso di memoria.

Qualsiasi aiuto sarà apprezzato. Grazie.

+1

La radice del problema è "più di 2000 immagini in alcuni casi". Avere troppe immagini caricate in memoria consumerà tutta la tua RAM. Non c'è modo di aggirare questo problema di base. Assicurati di caricare immagini con UIImage imageWithContentsOfFile anziché imageNamed in modo che non tutte le immagini vengano automaticamente memorizzate nella cache. Questo dovrebbe risolvere la maggior parte dei tuoi problemi, ma assicurati di conservare solo le immagini effettivamente necessarie in memoria. – MoDJ

risposta

1

Provare Infer può essere utile, segnala problemi di perdita di memoria in codice iOS e C.

Un analizzatore statico in distribuzione su Facebook, dove viene utilizzato come parte del processo di sviluppo per le app mobili. Inferifica obiettivi critici come eccezioni di puntatori nulli, perdite di risorse e perdite di memoria - problemi che portano a crash o degrado delle prestazioni nelle app.

+0

Se vedi l'immagine, puoi vedere che la memoria virtuale da 64 MB viene consumata da "Core UIImage Data". Hai idea del motivo per cui lo sta consumando? – Wolverine

1

Sembra che alcuni oggetti nell'app non vengano rilasciati, probabilmente a causa di un ciclo di conservazione. Controlla tutti i riferimenti ai delegati sono riferimenti deboli. Controlla anche i blocchi e assicurati che un riferimento forte a sé non venga catturato in un blocco. Se l'oggetto A mantiene un forte riferimento all'oggetto B, quindi passa un blocco contenente un riferimento forte a sé all'oggetto B, entrambi gli oggetti sono potenzialmente bloccati in un ciclo di conservazione. Utilizzare questa sintassi per passare un riferimento debole all'auto:

__weak typeof(self)weakSelf = self; 

[doSomethingWithBlock:^() { 
    __strong typeof(weakSelf)strongSelf = weakSelf; 
    if (!strongSelf) { 
     return; 
    } 
    [strongSelf doSomething];}]; 

in Swift fare questo:

someObject.doSomething() { [weak self] in 
        self?.doSomething() 
       } 

oppure usa [auto unowned] - sia creare una debole riferimento a sé, nel caso di [self debole], self è opzionale

Per garantire che tutti gli oggetti siano deallocati come previsto, inserire un'istruzione di registro nelle funzioni dealloc/deinit e verificare che vengano effettivamente chiamati.

+0

Penso che se questo caso accade allora in Strumenti "Allocazione" mostra la memoria allocata a quella parte giusto? Anche se ho usato ARC e ho anche provato @autorelasepool durante la creazione di più oggetti. – Wolverine

+0

Se viene visualizzata l'immagine, è possibile vedere che la memoria virtuale da 64 MB viene utilizzata da "Dati nucleo UII". Hai idea del motivo per cui lo sta consumando? – Wolverine

1

Wolverine,

Non dicendo che questo è una risposta assoluta alla tua domanda, ma potrebbe fornire qualche suggerimento per risolvere il problema.

mio caso:

Oggi mattina durante il debug del crash di memoria proprio come i tuoi di in uno dei miei un'applicazione di chat ho mai incontrato uno scenario simile. Sto usando anche SDWebImage per memorizzare nella cache e caricare le immagini per gli usi successivi.

Le osservazioni iniziali mi hanno fatto credere che sia l'arresto a causa di SDWebImage. Presto ho capito che Crach era piuttosto a causa di un problema molto semplice.

Non avevo mai provato se il mio telefono ViewController dealloc veniva chiamato o meno. Inserendo un breakpoint in dealloc ho realizzato che dealloc non veniva mai chiamato (per vari motivi che ho risolto ora).

Come nel tuo caso, il mio chatViewController però non caricava 100 di immagini utilizzate per caricare 8 - 10 immagini alla volta e l'arresto anomalo iniziava ad apparire quando usavo immagini panoramiche piuttosto che immagini normali.

Conclusione:

  1. mio viewController aveva forte riferimento alla UIImageView che è stato caricando immagini e pesanti come dealloc non è mai stato chiamato per il mio viewController tutte le immagini caricate non sono mai stati realesed che ha portato in un incidente di memoria.

  2. Mentre stavo caricando immagini pesanti stavo eseguendo diversi calcoli per ridurre le dimensioni dell'immagine. La maggior parte dei calcoli ha comportato la creazione ripetuta di immagini da NSData utilizzando UIImageJPEGRepresentation. Ripetuta allocazione dei dati e variabile del titolare dell'immagine aggiunta al consumo di memoria dell'app.

  3. Poiché il mio ViewController implicava il numero di chiamate API, avevo creato una classe di servizio di riferimento singleton a cui passavo i blocchi di complection e che inconsciamente avevo usato auto all'interno dei blocchi di completamento passati ai metodi. Che in realtà ha contribuito all'aumento del conteggio dei riferimenti ARC e non ho mai permesso al mio controller di visualizzazione di ottenere deallocate.

modo di debug

  1. Come si è già accennato nella sua interrogazione che si sta caricando i carichi di immagini nella vostra ViewController assicurarsi che il viewController sarà disallocato correttamente e rilascia tutta la memoria caricate da tutti i ImageView presenti in ViewController.

  2. Se il dealloc del ViewController non viene chiamato allora come solo un modo per testare (non ricordare una soluzione) in viewWillAppear imposta su nil tutte le proprietà dell'immagine di imageView e cancella forzatamente la memoria caricata.

  3. Se il dealloc di ViewController non viene chiamato risulta essere il colpevole, provare a trovare dove si invia il self come riferimento forte. Se trovato prova a utilizzare weak self.

So che non è una risposta assoluta alla tua domanda. Sto solo condividendo la mia esperienza con te. Spero che questo ti dia un suggerimento per risolvere il tuo.

1

Nella sessione WWDC 2012 242 iOS App Performance: Memory, Apple introduce un modo per rilevare il problema di memoria con il modello di strumenti di allocazione, a partire da 31 minuti.

1. Heap SnapsShots
di Apple suggerisce spinta pop più volte prima di prendere una fotografia istantanea del mucchio, preferisco spingere comparsa solo una volta.

Il pulsante Snapshot si chiama "Mark Generation"
Snapshot button

Si dovrebbe prendere istantanee più volte.

2. Memory Growth

Se la memoria crescere tra ogni snapshot, è possibile scavare in una delle snapshot, tranne il primo.

enter image description here

ordinare gli oggetti per Persitent, probabilmente ha visto il vostro problema ViewController (se si preme solo pop una volta) .O si può solo cercare di esso.

persitent

3.Now si può scavare nella struttura chiamata, individuare e risolvere i problemi.

4. È possibile utilizzare questa tecnica non solo per push pop viewControllers, ma anche per scorrere in una tabellaView, eseguire un databaseSearch e qualsiasi altro caso.