2013-07-31 15 views
7

Sto lavorando a un'app per Windows Phone 8 e sto riscontrando un problema di perdita di memoria. Ma prima un po 'di storia. L'app funziona (sfortunatamente) usando WebBrowser come pagine. Le pagine sono piuttosto complesse con un sacco di javascript coinvolti.Cosa potrebbe causare questo problema di memoria?

La parte nativa dell'app, scritta in C#, è responsabile di alcune semplici comunicazioni con javascript (ad esempio, nativo è un delegato per javascript per comunicare con un server), crea animazione per la transizione delle pagine, il monitoraggio, la persistenza , ecc. Tutto è fatto in un'unica PhoneApplicationPage.

Dopo alcuni arresti anomali per le eccezioni di memoria, ho iniziato a profilare l'app. Vedo che i WebBrowser, che sono la parte principale dell'app, sono disposti correttamente. Ma il problema che sto vedendo è che la memoria continua ad aumentare. Quel che è peggio, ho un piccolo riscontro dal profiler. Da quanto ho capito, il grafico del profiler dice che c'è un grosso problema, mentre i numeri del profiler dicono che non c'è alcun problema ...

Nota: il passaggio rappresenta una navigazione da un browser web a un altro browser web. Lo spike viene creato (suppongo) dall'animazione tra i due controlli. Nello span che ho selezionato nell'immagine, stavo facendo una navigazione in avanti e una all'indietro con un massimo di 5 WebBrowser (2 per i menu che sono sempre lì, 1 per la pagina indice, 1 per la pagina da cui mi muovo e 1 per la pagina verso cui navigo). Ad ogni navigazione il profiler mostra il numero corretto di WebBrowser: 5 dopo aver navigato in avanti, 4 dopo aver navigato indietro.

Nota 2: ho aggiunto la linea rossa per rendere più chiaro che la memoria sta andando in quel lasso di tempo

Come si può vedere dall'immagine profiler l'utilizzo della memoria è abbastanza grande ma i numeri Diciamo che è basso e in quel lasso di tempo, l'allocazione mantenuta è inferiore a quando è iniziata ...

Spero di aver inserito abbastanza informazioni. Voglio alcune idee su cosa potrebbe causare questo problema. Le mie idee finora sono:

-la javascript nel WebBrowser sta facendo qualcosa di sbagliato (ad esempio non pulendo qualche gestore di eventi). Anche se questo è il caso, il WebBrowser non dovrebbe rilasciare la memoria quando viene distrutta?

-utilizzare una PhoneApplicationPage univoca è qualcosa di malvagio che non dovrebbe essere fatto e cambiarne la struttura potrebbe causare questo.

-other?

Un'altra domanda: perché il grafico mostra la quantità corretta di memoria utilizzata mentre il numero non lo fa?

Se hai bisogno di maggiori informazioni sul profiler, chiedi e le posterò domani.

+2

'perché fa il grafico mostra la quantità corretta di utilizzo di memoria, mentre il numero non lo fanno?' I "numeri" mostrano solo la quantità di memoria gestita sei consumando. Significa semplicemente che il resto viene consumato dal codice nativo (il che rende il WebBrowser un colpevole allettante). Sfortunatamente, non ci sono abbastanza informazioni per trovare la causa principale. Se si crea un progetto semplice con un singolo WebBrowser, quindi si tenta di utilizzare la logica simile all'applicazione (distruggendo e ricreando istanze di browser Web), è possibile riprodurre la perdita? Se è così, si prega di indicare come riprodurlo da parte mia e potrei essere in grado di aiutare –

+0

@KooKiz Ho provato a creare un progetto più semplice in cui aggiungo e rimuovo WebBrowser dalla pagina ma funziona correttamente e non trattiene memoria . ora sto cercando di riprodurre la comunicazione più complicata che si verifica tra l'aggiunta e la rimozione dei WebBrowser. –

risposta

1

Non credo che ci siano informazioni sufficienti per trovare la causa della perdita e senza pubblicare l'intera soluzione non sono sicuro che ci possa essere, dato che la domanda riguarda l'individuazione della causa principale ...
Quello che posso offrire è l'approccio che ho usato quando ho avuto la mia perdita di memoria.

La tecnica è stato quello di:

  1. Aprire un profiler di memoria . Dal tuo screenshot vedo che ne stai usando uno. Ho usato perfmon.L'articolo This contiene informazioni sull'impostazione di perfmon e anche lo @fmunkert lo spiega piuttosto bene.
  2. Individuare un'area nel codice che si sospetta che sia probabile che la perdita si trovi in ​​quell'area. Questa parte dipende principalmente dal fatto che tu abbia una buona idea della parte del codice responsabile del problema.
  3. Spingere la perdita all'estremo: utilizzare le etichette e "goto" per isolare un'area/funzione e ripetere il codice sospetto molte volte (un ciclo funzionerà. Trovo che goto sia più conveniente per questo argomento).
  4. Nel ciclo ho utilizzato un punto di interruzione che ha arrestato ogni 50 colpi per esaminare il delta nell'utilizzo della memoria. Ovviamente è possibile modificare il valore in base a una variazione di perdita evidente nell'applicazione.
  5. Se si è individuata l'area che causa la perdita, l'utilizzo della memoria dovrebbe aumentare rapidamente. Se l'utilizzo della memoria non aumenta, ripeti le fasi 1-4 con un'altra area di codice che sospetti essere la causa principale. Se lo fa, continua a 6.
  6. Nell'area che hai trovato essere la causa, usa la stessa tecnica (goto + etichette) per ingrandire e isolare parti più piccole dell'area finché non trovi la fonte della perdita (Per favore non mi sottovalutare per il passo ricorsivo ...: 0)).

Si prega di notare che i lati verso il basso di questo metodo sono:

  1. Se si assegnano un oggetto nel ciclo, è lo smaltimento dovrebbe essere contenuta anche nel ciclo.
  2. Se si dispone di più di una sorgente di perdita, rende più difficile da individuare (ma ancora possibile)

prega di lasciare un commento se sono necessarie ulteriori spiegazioni.
Buona fortuna ...

0

Hai ripulito i gestori di eventi? Inavvertitamente potresti avere ancora dei riferimenti se i controlli sono rootati.

+0

Ho pulito i miei gestori di eventi, il WebBrowser era il responsabile –

1

Ok, dopo molte indagini, finalmente sono riuscito a trovare la perdita. la perdita viene creata dal controllo WebBrowser stesso che sembra avere un gestore di eventi che non viene rimosso quando lo si rimuove da un pannello. In effetti, la perdita è riproducibile seguendo questi passaggi:

  1. creare un nuovo browser web
  2. aggiungerlo a un pannello o qualsiasi altra cosa
  3. passare a una pagina, con un'immagine che è grande e pesante
  4. toccare da qualche parte nello spazio vuoto del browser (toccando l'immagine sembra di non creare la perdita)
  5. rimuovere e raccogliere il browser
  6. ripetere dal 1

ad ogni iterazione la memoria dell'immagine non viene mai raccolta e la memoria continua a crescere.

Un ticket per Microsoft era già stato inviato.

Il problema è stato risolto utilizzando un pool di browser web

+1

Avete trovato una soluzione reale o ricevuto un feedback da Microsoft? Abbiamo un'app che necessita di un controllo WebBrowser solo in una singola sezione e quando navighi e esci da quella sezione la memoria non viene mai liberata –

+0

Mi dispiace ma no. Il pool di WebBrowser funziona bene e quindi non ho dovuto indagare di più. Ti suggerisco di creare il webbrowser da codebehind e renderlo statico in modo da avere una sola istanza. Ciò renderà il browser sempre in memoria dopo la visualizzazione della pagina, ma almeno non mangerà nuova memoria ad ogni navigazione. –

Problemi correlati