Flash Builder 4 Profiler:如何发现哪些对象导致已知的内存增加?
我知道探查器问题可能非常笼统,但这里我有一个非常具体的问题和示例。
我知道在下面的代码中(取自 Joshua 的问题),无限数量的circle对象实例被添加到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>
I know profiler questions can be quite general, but here I have a very specific question and example.
I know that in the following code (taken from Joshua's question), that an infinite number of circle object instances are being added to the hostComponent. This obviously causes gradual slowing down of the app.
My question is, when I run the Flash Builder Profiler, where exactly do I see where the problem lies?
To try it out, create a new Flex 4 project, and paste in this code:
<?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>
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
首先,在玩了一下应用程序后,我会查看“内存使用情况”面板:
注意内存增加越来越多。
有一个“运行垃圾收集器”按钮可以强制执行 GC。然而,当你点击它时,内存并不会减少。
下一步是找出罪魁祸首。为此,您可以使用“活动对象”面板:
看起来像这样,分配一些 Vector 实例,一切看起来好的。
默认情况下,许多类是从活动对象数据网格中过滤出来的。幸运的是,我们可以指定要显示和隐藏哪些类。
默认情况下,flash.xx 包中的所有类都是隐藏的。从过滤列表中删除它们会给表格带来一些有趣的东西:
注意图形行:871 个实例已被删除创建并且它们仍然在记忆中!有了这些信息,您就可以假设 Graphics 实例是导致应用程序速度减慢的原因。如果您还过滤掉 mx.* 类,您将看到有 871 个 UIComponents 实例。每次创建 UIComponent 时,都会实例化一个 Graphics 对象。
最后一步是在屏幕上不再需要每个 UIComponent 后将其删除,并查看是否有任何性能改进。
First, I would look at the Memory Usage panel after playing a bit with the application :
Notice the memory increases more and more.
There is a "Run Garbage Collector" button that forces the GC. However, when you click on it, the memory doesn't decrease.
The next step is to identify the culprits. For that, you use the Live Objects panel :
It looks like that, appart some Vector instances, everything looks allright.
By default, a lot of classes are filtered from the live objects datagrid. Fortunately, one can specify which classes will be displayed and hidden.
All classes from the flash.x.x packages are hidden by default. Removing them from the filtered list bring somthing interesting to the table :
Notice the Graphics row : 871 instances have been created and they are all still in memory! With that info, you can suppose the Graphics instances are responsible of the slow down of the application. If you also filter out the mx.* classes, you will see there are 871 UIComponents instances. Everytime a UIComponent is created, there is a Graphics object also instancied.
Final step is to remove each UIComponent once it's no more needed on screen and look if there is any performance improvement.
UIComponent 的创建位置(如果双击 Allocation Trace 视图,其中会显示行号 - 在本例中为 30 - 它会在 Source 视图中打开该位置)。
现在您知道内存问题的根源
要修复累积内存泄漏,请添加以下内容:
在 fadeEffect.play(); 之后添加
并添加功能:
where that UIComponent was created (if you double click on the Allocation Trace view where it gives you the line number - 30 in this case - it opens that location in Source view).
Now you know the source of the memory problem
To fix the accumulative memory leak, add the following:
After fadeEffect.play(); add
and add the function: