有没有人想出AS3如何实际处理垃圾收集?在我正在开发的游戏中,我有很多问题释放内存。
做了一个小演示:
public class MemoryTesting extends Sprite
{
static protected var list:Array = null;
public function onKeyDown(event:KeyboardEvent):void {
if( event.keyCode == 65 ){ //A key - adds memory
if( list == null ){
list = [];
for( var index:int = 0; index < 10000000; ++index ){
list.push(new Matrix3D());
}
}
}
else{ //Any other key removes memory.
if( list ){
var size:int = list.length;
for( var index:int = 0; index < size; ++index ){
list.pop();
}
list.length = 0;
list = null;
}
System.gc();
}
}
}
在Windows 7中运行Flash Player调试器独立11.4r402。在没有按键的情况下观察任务管理器,调试器闲置在11,000 K.
按a(添加10Mil Matrix3D类)可将其提升至962,000 K.
按另一个键(删除对矩阵的引用并使数组无效)取决于我按下它的次数。
我听到有人在谈论GC等待收集的“适当时机”。但这是一个空的应用程序,甚至不是一个enter_frame事件,没有多少时间你可以让它空闲,以便删除剩余的27,000 K(38,000 - 11,000)。
坐在新的低点,如果我们重新添加矩阵,我们会回升到975,000 K.
也就是说,比第一次增加13,000 K.如果我重复这个添加/删除,它会保持不变,最高可达975,000 K,最低可达38,000 K.
请记住,此应用程序中没有任何内容。我的实际应用程序有650mb的原始位图数据,更不用说100mb的SWF解析和500mb的XML类,我只在初始化代码中使用。
我多次读过,即使手动调用GC也不好,更不用说6次了。但如果不这样做,Matrix3D都不会发布。
有人怎么办?我应该在初始化结束时调用GC 6次吗?
修改
我在发布模式下测试差异以及是否在没有System.gc()调用的情况下,如果它没有从闪存释放内存,至少重新使用它。它最终确实如此,但具有更高的占地面积。完整列表位于990,000 K,清除它需要1,050,000 K.
这适用于最初花费我们962,000 K RAM的数据。这是90MB奇怪的内部闪存GC内存。更别说忽略它不会将内存返回给操作系统(没有显式的GC调用)。
答案 0 :(得分:1)
Actionscript的GC很奇怪,无话可说,
如果您尝试使用这样的东西,它会有所帮助(我刚刚测试过并且GC在第一次尝试时清除了内存(按键点击)),只需将Array更改为Vector以便更快地测试,就像这样也应该与Array一起发生。在这种情况下,我的环境是FlashCC。
package
{
import flash.display.Sprite;
import flash.events.KeyboardEvent;
import flash.geom.Matrix3D;
import flash.net.LocalConnection;
import flash.system.System;
import flash.utils.setTimeout;
public class MemoryTesting extends Sprite
{
var list:Vector.<Matrix3D> = null;
function MemoryTesting()
{
stage.addEventListener(KeyboardEvent.KEY_DOWN, onKeyDown);
}
public function onKeyDown(event:KeyboardEvent):void
{
var matrx:Matrix3D;
var index:int
if (event.keyCode == 13)
{
trace(System.totalMemory, "starting to fill...")
if (list == null)
{
list = new Vector.<Matrix3D>
for (index = 0; index < 1000000; ++index)
{
matrx = new Matrix3D();
list.push(matrx);
}
}
trace(System.totalMemory, " done...")
}
else
{
if (list)
{
trace(System.totalMemory, " preparing to delete...")
list.splice(0, list.length);
list = null;
}
//force GC to work normally, it really helps (at least in my case)
try
{
new LocalConnection().connect('foo');
new LocalConnection().connect('foo');
}
catch (e:*)
{
}
setTimeout(function()
{
trace(System.totalMemory, " deleted")
}, 50)
}
}
}
}
这个奇怪的片段对大多数情况都有帮助
try {
new LocalConnection().connect('foo');
new LocalConnection().connect('foo');
} catch (e:*) {}
这是一篇有趣的文章: http://gskinner.com/blog/archives/2006/08/as3_resource_ma_2.html