2011-02-10 12 views
11

So che le domande del profiler possono essere abbastanza generali, ma qui ho una domanda e un esempio molto specifici.Flash Builder 4 Profiler: come individuare quali oggetti causano un aumento di memoria noto?

So che nel codice seguente (tratto da Joshua's question), che un numero infinito di cerchio istanze di oggetti vengono aggiunti al hostComponent. Ciò ovviamente causa un graduale rallentamento dell'app.

La mia domanda è, quando eseguo il Flash Builder Profiler, dove esattamente vedo dove si trova il problema?

Running example of the app

di provarlo, creare un nuovo progetto Flex 4 e incollare questo codice:

<?xml version="1.0" encoding="utf-8"?> 
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009" 
       xmlns:s="library://ns.adobe.com/flex/spark" 
       xmlns:mx="library://ns.adobe.com/flex/mx" minWidth="955" minHeight="600" 
       initialize="onInit()" viewSourceURL="srcview/index.html"> 
    <fx:Script> 
     <![CDATA[ 
      import mx.core.UIComponent; 
      import mx.effects.Fade;   
      import spark.effects.Move; 

      private var hostComponent:UIComponent; 

      private function onInit():void{ 

       hostComponent = new UIComponent(); 
       hostComponent.id = "circleHostComponent"; 
      } 

      /* Add circle UIComponent objects to the hostComponent. 
       Move and Fade the circle objects */ 
      private function onTimerEvent(event:TimerEvent):void{ 

       var yPos:Number = Math.ceil(Math.random()*100); 
       var radius:Number = Math.ceil(Math.random()*5); //1-12 
       var effectAlpha:Number = Math.random()*0.5 + 0.2 // 0-1 
       var effectDuration:Number = Math.ceil(Math.random()*3000) + 1000; 

       var circle:UIComponent = new UIComponent(); 
       circle.graphics.beginFill(0x1C75BC, effectAlpha); 
       circle.graphics.drawCircle(90, yPos, radius); 
       circle.graphics.endFill(); 

       hostComponent.addChild(circle); 

       var moveEffect:Move= new Move(circle); 
       moveEffect.xBy = 300; 
       moveEffect.duration = effectDuration; 

       moveEffect.play(); 

       var fadeEffect:Fade = new Fade(circle); 
       fadeEffect.alphaFrom = 1; 
       fadeEffect.alphaTo = 0; 
       fadeEffect.duration = effectDuration; 

       fadeEffect.play(); 

       this.addElement(hostComponent); 

      } 

      private function onClick():void{ 
       startButton.enabled = false; 
       var t:Timer = new Timer(100, 0); 
       t.start(); 
       t.addEventListener(TimerEvent.TIMER, onTimerEvent); 

      }  

     ]]> 
    </fx:Script> 

    <fx:Declarations> 
     <!-- Place non-visual elements (e.g., services, value objects) here --> 
    </fx:Declarations> 

    <s:Button id="startButton" label="Click to Start" click="onClick()" /> 
</s:Application> 
+2

Non vedo l'ora di vedere una risposta a questo. Ho avuto pochissima fortuna a decifrare l'output del profiler. +1 per una buona domanda. –

risposta

10

In primo luogo, vorrei guardare il pannello di utilizzo della memoria dopo aver giocato un po 'con il applicazione:

enter image description here

Avviso Nella memoria aumenta sempre di più. C'è un pulsante "Esegui Garbage Collector" che forza il GC. Tuttavia, quando si fa clic su di esso, la memoria non diminuisce.

Il passo successivo è identificare i colpevoli. Per questo, è possibile utilizzare Live pannello Oggetti:

enter image description here

Sembra che, appart alcuni casi Vector, tutto sembra allright. Per impostazione predefinita, molte classi vengono filtrate dal datagrid degli oggetti attivi. Fortunatamente, è possibile specificare quali classi saranno mostrate e nascoste. Tutte le classi dei pacchetti flash.x.x sono nascoste per impostazione predefinita. La rimozione dalla lista filtrata portare somthing interessante al tavolo:

enter image description here

Avviso fila grafica: 871 casi sono stati creati e sono tutti ancora in memoria! Con queste informazioni, è possibile supporre che le istanze grafiche siano responsabili del rallentamento dell'applicazione. Se si filtrano anche le classi mx. *, Verranno visualizzate 871 istanze di UIComponents. Ogni volta che viene creato un UIComponent, viene anche istanziato un oggetto Graphics.

Il passaggio finale consiste nel rimuovere ciascun UIComponent una volta che non è più necessario sullo schermo e controllare se vi sono miglioramenti delle prestazioni.

+1

+1 La rimozione del filtro ha dato molte più informazioni. Sulle opzioni di configurazione di Esegui Profiler, selezionare "Genera traccia di allocazione dell'oggetto". Scatta due istantanee di memoria, seleziona entrambe, fai clic su Trova oggetti in aggiramento. Usa la traccia di allocazione per vedere quando gli uiComponenti sono creati (sul segno di spunta del timer) - questo indica uno nella giusta direzione. – Ryan

+0

Pubblicherà uno screenshot di come trovare il colpevole esatto in un momento. – Ryan

8

Flash Builder Profiler

  1. Eseguire l'applicazione utilizzando Profiler (sceglie l'opzione per generare allocazione degli oggetti traccia quando richiesto)
  2. prendere due memoria Istantanee af pochi secondi di distanza
  3. selezionare entrambe le Memeory Snapshots e fare clic su Trova oggetti in aggiramento
  4. Assicurarsi di fare clic su Filt ering e rimuovere eventuali filtri
  5. Ordina per memoria. UIComponent sarà in cima/vicino all'inizio dell'elenco
  6. Fare doppio clic su UIComponent nella finestra oggetti sospesi - questo fa apparire la finestra Riferimenti oggetti.
  7. Fare clic su un UIComponent in Istanze e visualizzare la sua Traccia di allocazione, questo vi consente di sapere dove è stato creato tale UIComponent (se si fa doppio clic sulla vista Traccia allocazione dove si dà il numero di riga - 30 in questo caso - si apre quella posizione nella vista Origine).

ora si conosce la fonte del problema di memoria

Per risolvere la perdita di memoria di accumulazione, aggiungere il seguente:

Dopo fadeEffect.play(); aggiungere

fadeEffect.addEventListener(EffectEvent.EFFECT_END, onEffectEnd); 

e aggiungere la funzione di:

private function onEffectEnd(event:EffectEvent):void 
{ 
    trace(hostComponent.numChildren); 
    hostComponent.removeChild(event.target.target); 
    event.target.target = null; 
} 
+0

Sì, la funzione Confronta istantanee memoria di solito aiuta molto –

+0

Potrei semplicemente aggiungere (oppure ho perso qualcosa) - il passaggio 4 deve essere fatto prima del punto 2, altrimenti le istantanee verranno filtrate e non conterranno tutte le istantanee oggetti. – Kricket