Actionscript 3:服务器轮询演示应用程序中的内存泄漏

发布于 2024-08-22 11:54:59 字数 1456 浏览 4 评论 0原文

我正在 AS3 中构建一个远程演示工具。简而言之,一个用户(演示者)可以访问“目录”HTML 页面,其中包含演示文稿中每张幻灯片的链接,并且任意数量的观众可以在另一个页面上观看演示文稿,而该页面又在SWF 的形式,每秒轮询服务器以确保其位于正确的幻灯片上。每当管理员单击目录中的幻灯片链接时,数据库就会更新,并且在下一个请求时,演示文稿 swf 会将当前显示的幻灯片的标签与从服务器获得的响应进行比较。如果响应与当前标签不同,则 swf 会遍历时间线,直到找到正确的帧标签;否则,它不执行任何操作并等待下一个轮询结果(一秒钟后)。

每张幻灯片都包含一个影片剪辑,该影片剪辑具有自己的嵌套时间线,只要幻灯片显示,该时间线就会循环播放。没有动作脚本控制任何嵌套的影片剪辑,除了每个关键帧(每个关键帧都是演示文稿中的一张幻灯片)上的 stop(); 之外,主时间线上也没有任何动作脚本。

一切都已构建并完美运行。唯一令人不安的是,如果演示文稿 swf 打开足够长的时间(例如 20 分钟),轮询就会开始对任何给定幻灯片上的动画影片剪辑的帧速率产生明显影响。也就是说,每一秒,动画的帧率都会明显下降,持续约十分之三秒,这是非常明显的(因此对整个演示套件来说是一个破坏性的事情!)。

我知道 AS3 在内存管理方面存在问题,并且我努力重复使用对象和事件侦听器。代码本身非常简单;有一个 Timer 实例每秒触发一次,它会触发 URLLoader 加载一个 new URLRequestURLLoader 在每次调用中都会被重用,而 URLRequest 则不然(它每次都需要使用新的缓存终止值进行初始化,该值是从对 的调用中检索的)代码>new Date().time)。整个类中唯一实例化的对象是 TimerURLLoader、各种 URLRequests(应该被垃圾收集)和只有事件侦听器位于 Timer(添加一次)、URLLoader(添加一次)以及在时间轴中前后滑动以找到正确幻灯片的例程上(一旦找到正确的幻灯片,它们就会被删除)。

我一直在使用 mr doob 的统计数据包来监控内存使用情况,这绝对是随着时间的推移,数据会不断增长,所以一定有地方存在泄漏(经过一些清理和大约 25 分钟的正常运行时间后,它从最初的约 30 MB 增长到 > 200 MB)。

有人对可能导致性能问题的原因有任何想法吗?

更新:我不完全确定性能问题是否与内存直接相关;我运行了演示文稿 swf 的一个实例大约 15 分钟,尽管内存使用量仅攀升至 70 MB 左右(并保持在该水平),但每隔一秒就会出现明显的停顿,与轮询调用同时发生(通过 Firebug 的网络面板进行跟踪) )。还有哪些因素可能会导致影片剪辑出现卡顿?

I'm building a remote presentation tool in AS3. In a nutshell, one user (the presenter) has access to a "table of contents" HTML page with links for each slide in the presentation, and an arbitrary number of viewers can watch the presentation on another page, which in turn is in the form of a SWF that polls the server every second to ensure that it's on the right slide. Whenever the admin clicks a slide link in the TOC, the database gets updated, and on its next request the presentation swf compares the label of the slide it's currently displaying to the response it got from the server. If the response differs from the current label, the swf scrubs through the timeline until it finds the right frame label; otherwise, it does nothing and waits for the next poll result (a second later).

Each slide consists of a movieclip with its own nested timeline that loops as long as the slide is displayed. There's no actionscript controlling any of the nested movieclips, nor is there any actionscript on the main timeline except the stop();s on each keyframe (each of which is a slide in the presentation).

Everything is built and working perfectly. The only thing that's troubling is that if the presentation swf is open for long enough (say, 20 minutes), the polling starts to have a noticeable effect on the framerate of the movieclips animating on any given slide. That is, every second, there's a noticeable drop in the framerate of the animations that lasts about three-tenths of a second, which is quite noticeable (and hence is a deal-breaker for the whole presentation suite!).

I know that AS3 has issues with memory management, and I've tried to be diligent in my re-use of objects and event listeners. The code itself is dead simple; there's a Timer instance that fires every second, which triggers a new URLRequest to be loaded by a URLLoader. The URLLoader is reused from call to call, while the URLRequest is not (it needs to be initialized with a new cache-killing value each time, retrieved from a call to new Date().time). The only objects instantiated in the entire class are the Timer, the URLLoader, the various URLRequests (which should be garbage-collected), and the only event listeners are on the Timer (added once), the URLLoader (added once), and on the routines that scrub backwards and forwards in the timeline to find the right slide (and they're removed once the correct slide is found).

I've been using mr doob's stats package to monitor memory usage, which definitely grows over time, so there's gotta be a leak somewhere (it grows from ~30 MB initially to > 200 MB after some scrubbing and about 25 minutes of uptime).

Does anyone have any ideas as to what might be causing the performance problems?

UPDATE: I'm not entirely sure the performance troubles are tied directly to memory; I ran an instance of the presentation swf for about 15 minutes and although memory usage only climbed to around 70 MB (and stayed there), a noticeable hiccup started appearing at one-second intervals, coinciding with the polling calls (tracked via Firebug's Net panel). What else might cause stuttering movieclips?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

枫以 2024-08-29 11:54:59

我知道这有点晚了,但我经常使用 Flash Builder 的分析器,我发现的一件事是由计时器类生成的 TimerEvent

  1. 单独占用了相当多的内存,并且
  2. 似乎在垃圾收集期间无法正确释放(即使您停止了计时器并删除了对它的所有引用)。

每个Timer 滴答都会生成一个新事件。我使用 setInterval 来代替,尽管一些 AS3 布道者似乎不建议这样做。我不知道为什么。 setInterval 仍然会生成计时器事件,但它们似乎会随着时间的推移而被正确地进行垃圾收集。

因此,一种策略可能是

  1. 您用对 setInterval() 的调用来替换计时器...无论如何,这可以说是更健壮的代码,并且
  2. (注意)在每个幻灯片擦洗上强制进行垃圾收集(但不是在每个幻灯片上进行垃圾收集)轮询)。有关优缺点的更多详细信息,请参阅此问题

第二个建议只是权宜之计。我真的鼓励您使用分析工具来查找泄漏。 Flash Builder Pro 提供 60 天试用期,可能会有所帮助。

最后,当移动到全新的幻灯片 SWF(不是当前幻灯片中的新时间线位置)时,如何确保上一张幻灯片 SWF 已正确卸载?或者我误解了你的设置并且只有一张实际的幻灯片 SWF?

I know this is coming a bit late, but I have been using Flash Builder's profiler frequently and one thing I found is that the TimerEvent generated by the timer class

  1. uses up quite a bit of memory individually and
  2. seems to not get released properly during garbage collection (even if you stopped the timer and removed all references to it).

A new event is generated for each Timer tick. I use setInterval instead, even though a few AS3 evangelists seem to recommend against that. I don't know why. setInterval still generates timer events, but they appear to be garbage-collected properly over time.

So one strategy may be that

  1. you replace the Timer with a call to setInterval() ... which is arguably more robust code anyway and
  2. (CAUTION) force garbage collection on each slide scrub (but not on each poll). See this question for more details on the pros and cons.

The second suggestion is only a stop-gap measure. I really encourage you to use the profiling tools to find the leak. Flash Builder Pro has a 60-day trial that might help.

Finally, when moving to a completely new slide SWF (not a new timeline position in the current slide), how are you making sure that the previous slide SWF got unloaded properly? Or am I misunderstanding your setup and there is only one actual slide SWF?

逐鹿 2024-08-29 11:54:59

我想到的只有两件事:

  • 根据 Flash 播放器的版本和 CPU 使用情况,垃圾收集有时在消耗 250 MB(甚至更多)内存之前不会启动。
  • Moviesclips、Sprites、Loader 以及任何具有 Eventlistener 侦听功能的内容都不会被垃圾收集杀死。

所以我相信你的问题是,幻灯片或装载机在使用后没有正确清洁,因此它们被保留在内存中。

开始阅读的一个好点: http://www.gskinner.com /blog/archives/2006/06/as3_resource_ma.html

Just two things that came into my mind:

  • Depending on the version of the Flash player and the cpu usage the garbage collections sometimes does not start before 250 MB (or even more) memory are consumed.
  • Moviesclips, Sprites, Loader and whatever that has an Eventlistener listening will not be killed by the garbage collection.

So I believe your problem is, that either the slides or the loader are not cleaned correctly after you used them, so the were keept in memory.

A good point to start reading: http://www.gskinner.com/blog/archives/2006/06/as3_resource_ma.html

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文