如何减少我的flash游戏';s后台引擎600MB内存使用高峰?

如何减少我的flash游戏';s后台引擎600MB内存使用高峰?,flash,actionscript-3,memory,memory-management,background,Flash,Actionscript 3,Memory,Memory Management,Background,我正在用ActionScript3制作一个无限宇宙的flash游戏。由于宇宙是无限的,因此使用以下背景引擎动态创建背景: 背景引擎 使用的背景图像都大约30 KB小,但有些非常大: 我曾经将所有容器层转换为一个平面位图,但这似乎降低了性能。内存使用保持不变 问题是,当我在Flex 3中评测应用程序时,内存使用从20MB开始(即1个容器),当我开始移动更多的容器时,正在加载,而当旧容器被设置为null时,垃圾收集器没有立即从内存中删除它们,导致600MB内存峰值,之后,它返回到20MB并再次启动

我正在用ActionScript3制作一个无限宇宙的flash游戏。由于宇宙是无限的,因此使用以下背景引擎动态创建背景:

背景引擎

使用的背景图像都大约30 KB小,但有些非常大:

我曾经将所有容器层转换为一个平面位图,但这似乎降低了性能。内存使用保持不变

问题是,当我在Flex 3中评测应用程序时,内存使用从20MB开始(即1个容器),当我开始移动更多的容器时,正在加载,而当旧容器被设置为null时,垃圾收集器没有立即从内存中删除它们,导致600MB内存峰值,之后,它返回到20MB并再次启动。请注意,虽然我有一个64位操作系统的8GB RAM,但可能flash会根据您的内存以不同的时间间隔运行垃圾收集器


如果不是的话,我真的很感激你能帮我减少它使用的内存。图像已经非常优化(使用Photoshop)。

有一个技巧可以强制垃圾收集器

 try {
    new LocalConnection().connect('foo');
    new LocalConnection().connect('foo');
 } catch (e:*) {}
 // the GC will perform a full mark/sweep on the second call.


新的flash player在flash.system.system类中有一个静态gc()方法。但这只适用于调试版本。GC是一项繁重的操作,因此Flash播放器不会经常执行。如果您已经确保BitmapData可以是GC,就让它吧。FP将找到进行GC的正确时间

实际上,不建议手动控制或尝试控制GC,因为您永远无法在每个CPU/RAM组合上测试您自己的GC方法的性能结果(结果可能非常不同)


更新:

顺便说一句,您可以尝试对象池,这将:

  • 增加最小RAM使用量
  • 降低RAM使用的峰值
  • 降低GC频率(从而提高性能)

有关对象池的更多信息和开源类,请参阅和。

不要担心内存消耗。不管实际文件有多小,所有这些图形都会占用大量空间,在加载时会对其进行解压缩

这意味着32位的500x500映像将占用500x500x32=7.6mb的内存。所以,是的,你会经历很多记忆

问题是写垃圾收集器和内存管理的人比我们聪明。他们比我们更了解flash player的复杂性,所以请相信他们的判断。


Flash自然会使用尽可能多的内存,毕竟这就是内存的用途,如果一直都是空闲的,它就没有多大用处。因此,拥有8GB的ram将减少GC的运行频率

我可以提出其他答案中未涉及的几点

关于GC:关于GC的确切触发原因(我相信)没有公开发布,但我知道在某些环境中,它们会在计时器上自然发生(如果没有触发其他事件),并在闪存的内存使用量超过其可用总内存的某个百分比时触发。既然您在评论中提到,如果您强制使用GCs,您的总体内存使用率不会太高,那么我的第一个答案是,您应该停止担心内存使用率,直到您找到证据表明它在这个或那个环境中导致了问题。一般来说,如果Flash认为还有足够的内存,那么为了性能,它会避免使用GCs。因此,如果您看到使用率上升,但它不会影响系统性能,那么尝试“修复”这听起来像是过早优化——您的时间可能最好花在其他地方

关于您的代码:我只对您在这里所做的事情略感兴趣,但我注意到,您似乎没有在任何bitmapData对象上调用该方法。如果没有必要忽略这一点,但是如果您要自动收集任何BMD,请确保您正在处理它们

关于体系结构:我认为,如果您尝试使用“一个大位图”的方法来解决这个问题,您将看到总体内存使用率大大降低(并且可能会有更好的性能)。也就是说,您保留一个大的(屏幕大小)位图,每个帧都将其清空,并使用
copyPixels()。这可能比在游戏对象中使用displayObjects(如精灵)要快,尤其是当它们最初是位图且不需要旋转时(这似乎适用于您的情况)


与…相比。asker最终发现使用帧缓冲区的速度更快,并且作为额外的奖励,它应该有更可预测的内存使用,因为您不会创建和破坏位图或显示对象。(您创建和销毁的只是用于跟踪贴花位置的数据。)

这确实使其峰值达到50MB,这很好。然而,这确实是一个骗局,似乎也是一个无意的黑客行为。引用该链接的话:“同样,这只应该用作开发辅助工具。它永远不应该用于生产代码中!”-我希望有更好的解决方案。因为flash总是保存在服务器上,每次有人玩游戏时都会下载,为什么不坚持使用它呢,直到它被证明不再有效或者一个更好的解决方案出现。我想我必须这样做,除非还有其他解决方案。我将先等几天这样的解决办法。如果没有,您的将被接受。希望有人也能够回答这样一个问题:当您有更多内存时,flash是否会减少垃圾收集器的运行次数。“…当您有更多内存时,flash是否会减少垃圾收集器的运行次数”-我确信这在某些情况下是正确的(例如,对于某些版本的FP,在某些OSs上)-但我认为没有人能告诉你这到底是不是真的
//copies bitmap data and returns a new bitmap
        public static function copyDataToBitmap(bitmapData:BitmapData, transparency:Boolean = false, flatBackground:uint = 0x000000):Bitmap
        {
            var width:Number = bitmapData.width;
            var height:Number = bitmapData.height;
            var tmpBitmapData:BitmapData = new BitmapData(width, height, transparency, flatBackground);
            tmpBitmapData.copyPixels(bitmapData, new Rectangle(0, 0, width, height), new Point(0, 0));
            return new Bitmap(tmpBitmapData);
        }
 try {
    new LocalConnection().connect('foo');
    new LocalConnection().connect('foo');
 } catch (e:*) {}
 // the GC will perform a full mark/sweep on the second call.