Flash Builder 4 Profiler:如何发现导致已知内存增加的对象?
Posted
技术标签:
【中文标题】Flash Builder 4 Profiler:如何发现导致已知内存增加的对象?【英文标题】:Flash Builder 4 Profiler: how to spot what objects are causing a known memory increase? 【发布时间】:2011-06-24 22:24:22 【问题描述】:我知道分析器问题可能很笼统,但这里我有一个非常具体的问题和示例。
我知道在下面的代码中(取自Joshua's question),无限数量的circle 对象实例被添加到hostComponent。这显然会导致应用程序逐渐变慢。
我的问题是,当我运行 Flash Builder Profiler 时,我究竟在哪里看到了问题所在?
Running example of the app
要试用它,请创建一个新的 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>
【问题讨论】:
迫不及待地想看到这个问题的答案。我几乎没有运气破译分析器的输出。 +1 提出一个好问题。 【参考方案1】:-
使用 Profiler 运行应用程序(在询问时选择生成对象分配跟踪选项)
每隔几秒拍两张内存快照
选择两个内存快照并单击查找游荡对象
确保点击过滤,然后删除所有过滤器
按内存排序。 UIComponent 将在列表顶部/接近顶部
在 Loiting Objects 窗口中双击 UIComponent - 这将打开 Object References 窗口。
点击Instances下的一个UIComponent,查看它的Allocation Trace,这会让你知道
该 UIComponent 的创建位置(如果您双击 Allocation Trace 视图,它会在该视图中为您提供行号 - 在本例中为 30 - 它会在 Source 视图中打开该位置)。
现在你知道内存问题的根源了
要修复累积内存泄漏,请添加以下内容:
fadeEffect.play() 之后;添加
fadeEffect.addEventListener(EffectEvent.EFFECT_END, onEffectEnd);
并添加功能:
private function onEffectEnd(event:EffectEvent):void
trace(hostComponent.numChildren);
hostComponent.removeChild(event.target.target);
event.target.target = null;
【讨论】:
是的,比较内存快照功能通常很有帮助 我可能只是添加(否则我错过了一些东西) - 步骤 4 必须在步骤 2 之前完成,否则快照将被过滤并且不会包含所有对象。【参考方案2】:首先,我会在使用该应用程序后查看内存使用面板:
注意内存越来越多。 有一个强制 GC 的“运行垃圾收集器”按钮。但是,当您单击它时,内存不会减少。
下一步是找出罪魁祸首。为此,您可以使用 Live Objects 面板:
看起来像这样,分配了一些 Vector 实例,一切看起来都很好。 默认情况下,从活动对象数据网格中筛选出许多类。幸运的是,可以指定显示和隐藏哪些类。 默认情况下,flash.x.x 包中的所有类都是隐藏的。从过滤列表中删除它们会给表格带来一些有趣的东西:
注意 Graphics 行:871 个实例已经创建,它们都还在内存中!有了这些信息,您可以假设 Graphics 实例是导致应用程序变慢的原因。如果您还过滤掉 mx.* 类,您将看到有 871 个 UIComponents 实例。每次创建 UIComponent 时,都会实例化一个 Graphics 对象。
最后一步是在屏幕上不再需要每个 UIComponent 时将其删除,并查看是否有任何性能改进。
【讨论】:
+1 删除过滤提供了更多信息。在运行探查器配置选项中,勾选“生成对象分配跟踪”。拍两张内存快照,都选中,点击find Loiting Objects。使用分配跟踪查看 uiComponents 的创建时间(在计时器滴答时) - 这指向正确的方向。 稍后将发布如何找到确切罪魁祸首的屏幕截图。以上是关于Flash Builder 4 Profiler:如何发现导致已知内存增加的对象?的主要内容,如果未能解决你的问题,请参考以下文章
使用SparkSession.builder时如何设置profiler_cls?
Flash builder 4.6 Fake flex 错误