【问题标题】:AS3 large game performance degradation over timeAS3大型游戏性能随时间下降
【发布时间】:2009-09-21 21:15:01
【问题描述】:

我目前正在开发一个非常大型的 Flash 平台游戏(数百个课程),并且正在处理一个问题,即如果您将其打开足够长的时间,游戏就会慢慢停止。我没有编写游戏,所以我只是模糊地熟悉它的内部结构。一些神秘的症状包括,

  • 游戏会在一定时间内正常运行(在给定级别上),但突然间它会以指数方式开始泄漏内存。
  • 当屏幕上有更多精灵时,游戏达到指数级泄漏所需的时间会更短。
  • 即使屏幕上没有任何可见的渲染,游戏也会变慢。
  • 随着精灵碰撞的频繁发生,游戏速度变慢。
  • 完全禁用碰撞代码确实会减慢降级速度,但不会阻止游戏最终丢帧。

查看源代码并使用 Flex 分析器,我的主要嫌疑人是,

  • 游荡对象很多,尤其是WeakMethodClosure,占用大量内存。
  • 该程序极其广泛地使用弱事件侦听器(每帧调度数十个)。
  • 每次创建新精灵时都会复制 BitmapData。这些是 50x50 像素的精灵,每秒生成大约 8 个精灵。

我知道在没有看到源头的情况下告诉我问题几乎是不可能的,所以我只是在寻找可以帮助我缩小范围的花絮。有没有人在他们自己的项目中经历过这种回避的性能下降?你的情况是什么原因造成的?

【问题讨论】:

    标签: apache-flex actionscript-3 performance memory-leaks


    【解决方案1】:

    我最近完成了一个大型项目的优化。 我可以给你一些架构方面的建议:

    1. 主要原则 - 尽量少调用函数/事件
    2. 除掉一个 onEnterFrame / onInterval / onTimer 循环。做你想做的一切 需要一个一般事件调用。 您可能需要大量静态数组来存储已处理的对象 参考文献。
    3. 一个主循环中也做您的图形/渲染工作
    4. 尝试使用大的(可能是预渲染的)画布而不是小精灵/位图。 通常它可用于背景。但也适用于较小的物体 (如树木、平台等)
    5. 摆脱小的位图资源,将其组装到一个平铺纸上并绘制您的东西 直接从它,通过 source-rect 属性

    希望对你有帮助! 内存泄漏——这样的麻烦。

    附:在不同的浏览器、IE 中测试你的游戏——最容易泄露的,有时它不会在每次刷新后都清除内存。

    【讨论】:

    • 我认为这对于刚开始一个大型游戏项目并想知道如何最好地构建它的人来说是一个很好的建议。
    【解决方案2】:
    • 避免使用匿名方法 - 将它们更改为类级别的方法。
    • 在 addEventListener 中使用弱引用和/或确保在使用 removeChild 移除对象之前移除对象的所有侦听器
    • 确保删除所有精灵,而不是让它们飞离屏幕。此外,如果可能,请重复使用精灵而不是创建新精灵。

    【讨论】:

      【解决方案3】:

      如果您有大量的创建/销毁工作,您应该考虑对象池,尤其是对于像位图数据这样的重对象。

      Object Pool class

      【讨论】:

      • 一旦我确定了哪些资源导致了瓶颈,这是一个好主意。
      【解决方案4】:

      听起来您需要分析您的应用程序以查看发生了什么。

      这个帖子有一些建议,但最终,您只需要输入代码来帮助确定发生了什么。

      Profiling ActionScript-3 Code

      您可能想看看是否可以在一段时间内只运行一些较小的部分,看看是否会出现减速。

      您可能希望对应用程序进行单元测试,以便快速运行各个部分,查找内存泄漏。 一个框架是:http://asunit.org/,另一个是:http://opensource.adobe.com/wiki/display/flexunit/

      单元测试是我大量用于分析的东西,因此您可以在游戏的顶层进行测试,运行数千次,寻找问题,然后运行每个部分,看看哪个部分有问题,然后就可以工作了你下来。这是一个手动过程,但如果开头列出的 SO 线程中的两个想法没有帮助,这可能是您最好的方法。

      您是否使用了太多内存?还是你的cpu使用率太高了?

      【讨论】:

      • 问题提到了内存泄漏,所以我猜cpu使用率不是问题。
      • 我正在尝试看看除了他的猜测之外是否还有其他问题。不幸的是,当我猜到我的程序有问题的地方时,我往往是错的,这就是我如此依赖分析的原因。
      • 我想知道过多的垃圾收集是否会导致程序降级,因为生成的对象太多太快。
      【解决方案5】:

      首先确定您是否达到了内存或处理器限制。听起来是后者,似乎有很多对象在周围做事......可能那些额外的精灵没有被很好地释放。在这些事件中寻找对象/变量/任何东西之间的依赖关系,确保精灵被移除,注意 EnterFrame 的任何处理程序或重复事件。

      【讨论】:

        【解决方案6】:

        听起来你对处理器速度的限制比内存要大得多。您必须更加努力地对 Flash 应用程序进行内存限制。

        幸运的是,您可以做很多简单的事情来降低 CPU 的运行速度...

        1) 严格管理一切的事件监听器,尤其是鼠标监听器。你的所有精灵对象上都有 $texas 事件监听器吗?这可能是个问题。

        2) 使用 int 或 uint 而不是 Number 访问数组。这是巨大的,这是那些死水的 Adob​​e 技巧之一。使用 int 和 uint 访问数组对象比 Number 快得多,如果您进行大量迭代(听起来像您这样做),这可能会减少帧执行的宝贵毫秒数。

        3) 与 #2 一样,监控您的数学运算以及您对某些运算使用的类型。在 AS3 的数学运算中,您可以做的最慢的事情是重复转换(将 int 提供给返回 Number 的函数),或者对 Number 而不是 int 执行基本操作,例如加减法。

        在 Flash 中拥有这样一个 wtfhuge 程序的好处在于,即使是很小的优化更改也会对性能产生重大影响。我曾经在 AS3 中玩过一个光线追踪引擎,在其中我声明了一个额外的变量,它把我的 FPS 从 30 杀到了 23。

        【讨论】:

        • 我确信我的游戏至少在一些地方违反了这些规则。我希望就这么简单!
        【解决方案7】:
        Flash 有一个相当臭名昭著的问题(许多人认为这是一个错误),它会导致计时器的事件侦听器和 ENTER_FRAME 事件不会被垃圾收集,即使它们被弱引用。因此,即使使用弱引用事件是一种很好的做法,您仍然应该在不再需要所有事件侦听器时删除它们。

        【讨论】:

        • 在快速搜索 Event.ENTER_FRAME 后,我找到了 18 个匹配项,因此可以肯定地说问题也可能在这里。
        猜你喜欢
        • 2018-08-20
        • 1970-01-01
        • 2021-01-22
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2010-09-25
        • 2017-09-14
        相关资源
        最近更新 更多