Flash Builder 4 Profiler:如何发现导致已知内存增加的对象?

Dre*_*nai 11 apache-flex profiler flexbuilder flash-builder

我知道探查者的问题可能很普遍,但在这里我有一个非常具体的问题和例子.

我知道在下面的代码中(取自Joshua的问题),无数个圆形对象实例被添加到hostComponent.这显然会导致应用程序逐渐放缓.

我的问题是,当我运行Flash Builder Profiler时,我究竟在哪里看到问题出在哪里?

运行应用程序的示例

要试用它,请创建一个新的Flex 4项目,并粘贴以下代码:

<?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>
Run Code Online (Sandbox Code Playgroud)

Flo*_*n F 10

首先,在使用应用程序后,我会查看"内存使用情况"面板:

在此输入图像描述

请注意,内存越来越多.有一个"运行垃圾收集器"按钮强制GC.但是,单击它时,内存不会减少.

下一步是确定罪魁祸首.为此,您使用"实时对象"面板:

在此输入图像描述

它看起来像,一些Vector实例,一切看起来都很好.默认情况下,许多类都从活动对象datagrid中过滤掉.幸运的是,可以指定显示和隐藏哪些类.默认情况下,flash.xx包中的所有类都是隐藏的.从筛选列表中删除它们会给表格带来一些有趣的东西:

在此输入图像描述

注意Graphics行:已经创建了871个实例,它们仍然在内存中!有了这些信息,您可以假设Graphics实例负责应用程序的减速.如果还过滤掉了mx.*类,您将看到有871个UIComponent实例.每次创建UIComponent时,都会有一个Graphics对象也被实例化.

最后一步是在屏幕上不再需要时删除每个UIComponent并查看是否有任何性能改进.


Dre*_*nai 8

Flash Builder Profiler

  1. 使用Profiler运行应用程序(选择" 询问时生成对象分配跟踪 "选项)
  2. 相隔几秒钟拍摄两张内存快照
  3. 选择两个Memeory Snapshots,然后单击Find Loitering Objects
  4. 确保单击"筛选",然后删除所有筛选器
  5. 按内存排序.UIComponent将位于列表顶部/顶部
  6. 双击"闲置对象"窗口中的UIComponent - 这将打开"对象引用"窗口.
  7. 单击Instances下的UIComponent并查看其分配跟踪,这将告诉您创建UIComponent的位置(如果您双击分配跟踪视图,它在此处为您提供行号 - 在这种情况下为30 - 它将在Source中打开该位置视图).

现在你知道了内存问题的根源

要修复累积内存泄漏,请添加以下内容:

在fadeEffect.play()之后; 加

fadeEffect.addEventListener(EffectEvent.EFFECT_END, onEffectEnd);
Run Code Online (Sandbox Code Playgroud)

并添加功能:

private function onEffectEnd(event:EffectEvent):void
{
   trace(hostComponent.numChildren);
   hostComponent.removeChild(event.target.target);
   event.target.target = null;
}
Run Code Online (Sandbox Code Playgroud)