Actionscript 3 垃圾收集器在每个帧上占用所有cpu时间的原因

Actionscript 3 垃圾收集器在每个帧上占用所有cpu时间的原因,actionscript-3,memory-management,air,garbage-collection,Actionscript 3,Memory Management,Air,Garbage Collection,有时我的AdobeAIR应用程序会变得非常慢,因为垃圾收集器开始在每个帧上连续工作,占用了超过800%的预算。它持续几分钟甚至更长时间。这个问题只会偶尔出现在iPhone4/4s上,重新启动设备后一段时间一切正常 也许有人也有这种情况,并知道如何防止它 更新:已实施对象池和其他分配预防方法。所以,没有什么真正需要收集的,GC只是白白地花费CPU。当这结束时,内存使用仍然相同。而且,即使使用相同的输入和场景,也不会每次都发生这种情况。因此,我假设存在一些“不幸运”的情况,分配的堆位于某个阈值附近,

有时我的AdobeAIR应用程序会变得非常慢,因为垃圾收集器开始在每个帧上连续工作,占用了超过800%的预算。它持续几分钟甚至更长时间。这个问题只会偶尔出现在iPhone4/4s上,重新启动设备后一段时间一切正常

也许有人也有这种情况,并知道如何防止它

更新:已实施对象池和其他分配预防方法。所以,没有什么真正需要收集的,GC只是白白地花费CPU。当这结束时,内存使用仍然相同。而且,即使使用相同的输入和场景,也不会每次都发生这种情况。因此,我假设存在一些“不幸运”的情况,分配的堆位于某个阈值附近,空气决定在从系统中取出另一块之前进行清理。然后它发现要处理的对象很少,并且不再需要新的块。在下一帧中,创建的对象很少(很少),场景也会重复


尝试使用对象池以便回收对象。我假设您创建了大量对象,然后GC尝试释放内存,如果您回收对象,则您将不会创建新对象,也不需要收集旧对象。如果我的假设是正确的,那么使用其对象池路径将提高应用程序性能,并可能解决您的问题。

请记住以下几点:

  • 垃圾收集仅在应用程序请求内存时启动;Flash将尝试从应用程序中恢复一些内存,然后再从操作系统请求另一个内存页(大约1MB的分配)。因为你的垃圾收集非常频繁,这表明你的应用程序占用的内存比你想象的要多
  • GC基于引用工作:
    var s:Sprite=new Sprite()
    创建对
    Sprite
    的引用<代码>变量s2:Sprite=s创建另一个引用。对于
    Sprite
    用于垃圾收集的内存,
    s
    s2
    都需要设置为null。如果它们是局部变量,则当它们超出范围时(例如,如果它们在函数中声明,则在函数末尾)会自动发生这种情况
  • 一旦清除了对对象的所有引用,就可以恢复分配的内存。但是,有时,您可能会遇到循环引用的问题—两个对象持有对另一个对象的引用,但没有任何对象具有对它们的引用
  • 为了解决这个问题,GC通常有两个阶段:标记阶段和扫描阶段。标记阶段将从应用程序的根(阶段)开始,并尝试触摸它可以触摸的每一个对象。所有未被触摸的东西都被认为是死的,可以收集起来。所有“死”对象都将在扫描阶段清理
  • 标记阶段非常慢,因此您希望尽量避免它,基本上保持内存使用静态
要帮助GC:

  • 清除事件侦听器,或使用弱侦听器(不添加引用)
  • 清除显式引用-实现一个
    destroy()
    或一个
    dispose()
    方法,当您想要清除某个对象时调用该方法,并
    null
    所有对象
  • 如前所述,使用对象池重用对象
  • 某些对象,如
    BitmapData
    XML
    ,可以立即销毁(
    BitmapData.dispose()
    System.disposeXML()
    )。如果它仅用于安装,或者可以重新加载,请将其删除。注意:如果您使用的是Starling,并且您从
    位图创建
    纹理
    ,那么您可能不需要原始的,除非您想处理丢失的上下文,但您可能只需要将所有内容加载回
  • 小心隐藏的分配:
    cacheAsBitmap
    正在后台分配位图,与
    过滤器的分配相同<代码>数组。splice()正在创建新数组等
  • 注意循环中发生的任何对象创建等
几年前我写了一个类来帮助跟踪内存泄漏(),但是您应该能够使用Scout获得更深入的信息——拍摄内存快照,玩一玩,然后再拍摄一个;您可以比较这两者并高亮显示任何创建的对象,包括(我认为)它们创建的位置


要记住的另一点是,如果你的设备实际上有足够的内存来运行你的应用程序,例如,如果你的应用程序(假设一切都经过优化等)占用100MB的内存,但你只有80MB的可用内存,GC将持续运行,以尝试分配最后20个

我认为您应该检查并确保正确释放在整个应用程序中添加的所有事件侦听器,否则它最终会像您看到的那样出错。您是否在任何地方调用
System.GC()
?您可以在空中使用该方法手动调用垃圾收集,但强烈建议您不要这样做。无论如何,如果没有看到某种代码,我认为我们在这里帮不了什么忙。应用程序使用了多少内存?(iOS有一些限制)您提到创建的每个帧都有一些小对象这些对象是否正确释放(删除事件处理程序)您也可以为这些对象使用池吗?如果您使用的是FlashBuilder,那么有一个内存分析器可以提供帮助。如果使用内存分析器,堆中是否有许多对象?这是一个非常好的答案。我绝对赞成。为了进一步补充这一点,我建议阅读这些文章并使用前Flash福音传道者格兰特·斯金纳(Grant Skinner)创建的工具。