14

我的任务是发现(并可能修复)交付给我们的 Flex 应用程序的一些严重性能问题。当应用程序只是空闲并且不应该做任何事情时,它会持续占用 50% 到 100% 的 CPU。

我的第一步是运行 FlexBuilder 附带的分析器。我希望找到一些占用大部分时间的方法,告诉我瓶颈在哪里。然而,我得到了一些意想不到的东西。

排名前 4 位的方法是:

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

所有其他方法的累积时间和自身时间都小于 1%。

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

有谁知道 [enterFrameEvent] 实际上在做什么?我认为它本质上是事件循环的“主要”功能,因此预计会有很高的累积时间。但是为什么自拍时间这么高呢?究竟发生了什么?我没想到播放器内部会占用这么多时间,尤其是因为应用程序中实际上没有发生任何事情(并且没有进行 UI 更新)。

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

4

7 回答 7

5

在 flex 项目中的 enterframe 处理程序上通常会发生一些事情。需要注意的一些事项

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

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

  3. 最后,我不能保证 [enterframeEvent] 只处理特定于 enterframe 的事件回调,而不是计时器、鼠标等事件,因为 enterframes 发生在主事件循环期间,您可能会看到所有事件触发的累积结果来自主赛事池。我不是说这是正在发生的事情,但我也不能说这不是正在发生的事情,我对那里的内部结构知之甚少,无法确定。

/edit 也如前所述,从技术上讲,[enterFrameEvent] 应该在每个帧开始时在内部触发,但它不应该做任何事情,除非事件已明确附加到它以执行用户代码。

于 2008-12-08T23:03:38.727 回答
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

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

干杯

于 2009-04-16T18:27:22.803 回答
3

一些更新:除了监听事件和使用绑定之外,我们在应用程序中没有做任何事情......意思是,没有 ChangeWatchers,没有手动轮询......只是等待事件。我们一直连接到 FMS,因此有一些开销,但它是最小的。绑定在 Flex 中的效率不是很高,我们发现直接将 [Bindable] 元数据关键字添加到类(量很大,有很多类)是不好的。我们并没有做太多这方面的工作,但这是从您的应用中挤出更多性能的一种方式。如果您使用 [Bindable(event="usersUpdated")] 那么您可以控制绑定,并且它只会在您从类中的函数中 dispatchEvent(new Event("usersUpdated")) 时触发,即您的'用户'的设置器。

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

此外,使用临时对象来减少触发的绑定数量。代替...

myUser.location = 新位置();myUser.location.state = "CO"; myUser.location.city = "丹佛";

做...

var tempLoc:位置=新位置();tempLoc.state =“一氧化碳”;tempLoc.city = "丹佛"; myUser.location = tempLoc;

前者会触发 3 个绑定到任何绑定到 location.* 的东西,而后者应该只触发 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 应用程序相同。AS2 和 AS3 的 AVM(ActionScript 虚拟机)之间也有很大的不同。

这只是触及了 Flex 应用程序的性能问题和潜在收益的表面。这是一门黑暗的艺术,很容易看出原因。

代码,忍者。

于 2008-12-05T18:10:50.097 回答
1

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

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

于 2009-07-22T22:09:27.043 回答
1

我认为您的问题出在其他地方。发生这种情况是因为 Flex 构建在 Flash 之上,而 Flash 触发该事件的频率与帧速率一样多(例如每秒 20-30 次)。

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

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

于 2008-12-04T21:02:42.687 回答
1

更新的 livedocs 链接:

http://help.adobe.com/en_US/flashbuilder/using/WS6f97d7caa66ef6eb1e63e3d11b6c4d0d21-7edf.html

于 2010-06-14T01:46:17.890 回答
0

Justin, thanks for the reply. The issue is not with enterFrame executing, but rather with it trying to do too much in each iteration.

FYI: Coincidentally, the original poster and I are dealing with the same application. We have decided to remove all Degrafa resources in favor of ProgrammaticSkins. I'll report the findings here when we have completed this.

于 2008-12-04T21:32:24.390 回答