Flex分析 - [enterFrameEvent]在做什么?

时间:2008-12-03 20:45:55

标签: flex profiling enterframeevent

我的任务是找到(并可能修复)一些传递给我们的Flex应用程序的严重性能问题。当应用程序处于空闲状态并且不应该执行任何操作时,应用程序将始终占用CPU的50%到100%。

我的第一步是运行FlexBuilder附带的分析器。我期望找到一些占用大部分时间的方法,向我展示瓶颈所在。但是,我有些意外。

前4种方法是:

  • [enterFrameEvent] - 84%累积,32%自我时间
  • [收获] - 20%累积和自我时间
  • [tincan] - 8%累积和自我时间
  • global.isNaN - 4%累积和自我时间

所有其他方法的累计和自我时间都不到1%。

从我在网上找到的内容中,[括号内的方法]是分析器在没有实际的Flex方法显示时列出的内容。我看到有人声称[tincan]是RTMP请求的处理,我认为[reap]是垃圾收集器。

有谁知道[enterFrameEvent]实际上在做什么?我认为它实际上是事件循环的“主要”功能,因此预计会有很高的累积时间。但为什么自我时间如此之高?究竟发生了什么?我没想到玩家内部会花费这么多时间,特别是因为应用程序中实际上没有发生任何事情(并且没有UI更新)。

有没有什么好方法可以找到正在发生的事情?我知道正在发生的事情不应该是(看起来必须有某种忙碌的等待或其他失控循环),但是探查器没有给我任何我期待的结果。我的下一步是开始在各个地方添加调试跟踪语句,以尝试跟踪实际发生的情况,但我觉得必须有更好的方法。

7 个答案:

答案 0 :(得分:5)

通常会在flex项目中的enterframe Handler上发生一些事情。有些事情要注意

  1. 手动< mycomponent enterFrame =“”>事件响应或通过component.addEventListener手动添加的事件响应(Event.ENTER_FRAME,myfunc)

  2. callLater()调用,这些在框架中发生ALOT并且可以是跳过任意数量的兔子漏洞的副产品,开发人员倾向于使用这些来解决与时间相关的问题,有时候糟糕的代码会导致这些问题继续下去呼唤每一帧。例如,最新的flex sdk版本中有大约120次出现calllater()。

  3. 最后,我不能保证[enterframeEvent]只处理enterframe特定的事件回调,而不是定时器,鼠标​​等事件,因为在主事件循环期间发生了enterframe,你可能会看到从主事件池触发的所有事件的累积结果。我不是说这是发生了什么事,但我不能说这也不是什么事情发生,我对那里的内部结构还不太了解。

  4. /编辑也如前所述,[enterFrameEvent]技术上应该在每个帧的开头内部触发,但它不应该做任何事情,除非事件已经显式附加到它以执行用户代码。

答案 1 :(得分:3)

一些更新: 除了监听事件和使用绑定之外,我们没有在应用程序中执行任何操作...意思是,没有ChangeWatchers,没有手动轮询......只是等待事件。我们整个时间都连接到FMS,因此有一些开销,但它是最小的。 Flex中的绑定不是非常有效,我们发现将[Bindable]元数据关键字直接添加到类(大批量,有很多类)中并不好。我们没有做太多这样的事情,但它是一种从应用程序中挤出更多性能的方法。如果您使用[Bindable(event =“usersUpdated”)],那么您可以控制绑定,它只会在您从类中的函数中调度事件(新事件(“usersUpdated”))时触发,即您的“用户”的设定者。

任何在Flex或AIR中使用System.gc()的人都会告诉你Flex垃圾收集是一个笑话。它是部分实现的功能,没有人信任它。这也有一些技巧......叫它两次,等一帧,再打电话给它。它可能会清理你的旧物体,但不要交叉你的手指...... Flex会做它想做的事。

此外,使用临时对象减少触发的绑定数量。而不是......

myUser.location = new Location(); myUser.location.state =“CO”; myUser.location.city =“丹佛”;

...做

var tempLoc:Location = new Location(); tempLoc.state =“CO”; tempLoc.city =“丹佛”; myUser.location = tempLoc;

前者触发绑定到位置的任何东西的3个绑定。*,而后者应该只触发1个绑定(实际上由于Flex处理它的方式,它通常是额外的。)

绑定不会杀死你的应用程序,直到你在视觉丰富的应用程序中有很多它们....绑定和渲染似乎是Flex最慢的工作。

另一个有趣的事情是:在Flex Builder中创建一个全新的Flex3应用程序并在浏览器中运行它。我们的测试显示,MacBookPro上的CPU保持在8-10%之间(当应用程序空闲时,浏览器窗口隐藏)。 我们的应用程序现在稳定运行~20%,虽然它为了处理视图更改等而高峰,但它总是返回到接近20%的水平。我们最初担心的是有一个内存泄漏或者某些东西逃跑会使CPU占用很高的水平并使其徘徊在40-50%左右(再次,在MBP上...相对于这台机器而言)。我们拿出了所有对Degrafa的引用,虽然我们注意到性能提升了很多,但它没有考虑到所有内容。空的Flex应用程序虽然很有启发性 - 但即使在空闲时,Flex也一直占用8-10%的CPU。

还有另一个发现......如果使用Mate,请注意如何处理切换视图。通过在MXML中使用注入器和绑定,可以轻松获得可用资源,只需隐藏和禁用它们,但在隐藏/禁用内容时,Flex并不是非常聪明。最好是动态创建视图,并在完成后将其销毁。即使初始创建可能需要更多时间并且视图之间会有更长的等待,使用一些显示魔术(进度条,旋转磁盘等)来指示视图正在切换,等待视图上的creationComplete,然后淡入它。

此外,远离ViewStack以获得视觉效果丰富的应用。管理自己的堆栈。

到目前为止,这个线程已经解决了任何语言常见的基本性能问题,但Flex在很多方面都是一个非常特殊的小男孩(“特殊”并不总是被认为是积极的事情)。有无数的陷阱,因为它建立在一个非常直观的平台上,但它是为RIA构建的,所以虽然Flash Player可能会优化视频,动画等,但它不会优化Flex应用程序。不要指望Flex应用程序与Flash应用程序执行相同的操作。 ASM和AS3的AVM(ActionScript虚拟机)之间也存在很大差异。

这只是表面上的性能问题以及Flex应用程序的潜在收益。这是一种黑暗的艺术,很容易理解为什么。

Code on,ninjas。

答案 2 :(得分:3)

对于这篇文章的更新,任何人都会在将来遇到它......

几个月后,EffectiveUI的一些同事在他们的应用程序中遇到了这个确切的问题,所以重新访问了它。有人发现,当使用Flash制作视觉资产,使用STATEFUL SKINS,并使用Flash / Flex资产工具包将它们导出到SWC时,你会得到失控的Flash电影(可能是实现这种方式的内部因素,比如忘记放置帧中的stop()命令)。

除了进入并移除所有有状态的皮肤之外,显然没有什么可以做的。可以在这里找到一篇好的文章:

http://patrickhansen.com/blog/index.php/2009/03/05/flex-stateful-skins-vs-stateless?blog=3

可用于将有状态皮肤转换为无状态皮肤的JSFL脚本:

http://patrickhansen.com/blog/index.php/2009/04/08/stateful-to-stateless-jsfl-flash-command?blog=3

希望这有助于某人!这是一个非常讨厌,神秘的错误,但你可以解决它!

干杯

答案 3 :(得分:1)

我认为你的问题出在其他地方。之所以会发生这种情况,是因为Flex构建在Flash之上,Flash会像帧速率一样频繁地触发该事件(因此每秒20-30次)。

http://www.adobe.com/support/flash/action_scripts/actionscript_dictionary/actionscript_dictionary546.html

编辑:我不是说你的解决方案是降低帧速率。只有当你注意到的事件是问题时,这才有效。我不相信这实际上是导致你减速的原因。它可能是调用导致问题的函数......但该事件本身不是它。它本应该发射很多。

答案 4 :(得分:1)

此链接解释了性能分析器中描述的每个[功能]:

http://livedocs.adobe.com/flex/gumbo/html/WS6f97d7caa66ef6eb1e63e3d11b6c4d0d21-7edf.html

答案 5 :(得分:1)

答案 6 :(得分:0)

贾斯汀,谢谢你的回复。 问题不在于执行enterFrame,而是在每次迭代中尝试做太多。

仅供参考:巧合的是,原始海报和我正在处理相同的应用程序。我们决定删除所有Degrafa资源,转而使用ProgrammaticSkins。我们完成此工作后,我会在此报告调查结果。