Actionscript 3 AS3内存管理逆向工程
有人知道AS3实际上是如何处理垃圾收集的吗?在我正在开发的游戏中,我在释放内存方面遇到了很多问题 制作了一个小演示:Actionscript 3 AS3内存管理逆向工程,actionscript-3,flash,garbage-collection,Actionscript 3,Flash,Garbage Collection,有人知道AS3实际上是如何处理垃圾收集的吗?在我正在开发的游戏中,我在释放内存方面遇到了很多问题 制作了一个小演示: public class MemoryTesting extends Sprite { static protected var list:Array = null; public function onKeyDown(event:KeyboardEvent):void { if( event.keyCode == 65 ){ //A key -
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();
}
}
}
public类MemoryTesting扩展了Sprite
{
静态保护变量列表:Array=null;
公用函数onKeyDown(事件:KeyboardEvent):无效{
如果(event.keyCode==65){//A键-添加内存
if(list==null){
列表=[];
对于(var指数:int=0;指数<10000000;++指数){
list.push(新矩阵x3d());
}
}
}
否则{//任何其他键都会删除内存。
如果(列表){
变量大小:int=list.length;
对于(变量索引:int=0;索引
在Windows 7中运行Flash Player调试器单机版11.4r402。观察任务管理器,没有按下任何键,调试器在11000 K时处于空闲状态
按a键(添加10Mil Matrix3D类)将占用962000K的空间
按另一个键(删除对矩阵的引用并将数组置零)取决于我按它的次数
- 我们第一次调用GC-下降到255000k
- 第二个GC调用-92000 K
- 第三名-52000 K
- 福斯-42000 K
- 第五-39000 K
- 第六次和在38000 K下坐下后的任何连续时间
这适用于最初需要962000 K RAM的数据。这是90MB奇怪的内部闪存GC内存。更不用说忽略它永远不会将内存返回给操作系统(没有显式的GC调用) Actionscript的GC很奇怪,没什么可说的 如果您尝试使用类似的方法,它会很有帮助(我刚刚测试过,GC在第一次尝试(按键)时会清除内存),只是将数组更改为向量以更快地测试,同样的情况也应该发生在数组中。在这种情况下,我的环境是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)
}
}
}
以下是freat的文章:
这样的东西让我想回到C++。至少我们有控制权。应该始终可以选择关闭语言的GC并手动执行操作。出于价值考虑,Adobe福音派倾向于建议不要使用
System.GC()
。首先,它只能在某些情况下工作(请参阅live docs),其次,当需要更多内存时,Flash会释放内存。整个系统将自动运行,而不是手动运行;您应该将该索引第一个列表中的对象清空[i]=null;list.pop();,所以这可能是你的内存泄漏。可以为空的对象越多越好。此外,System.gc()只能在播放器的调试版本中调用,生产版本将忽略它。@Jono这意味着当您为普通用户发布SWF时,他们将始终看到1G的使用量。来自C++的你理解GC的重要性,但是AS3你试图改变那些不被程序员改变的东西。这种语言最初是为了设计者而编写的,尽管在较新的版本(as3)中,它更像是一种传统语言,但它仍然源于AS1。大多数人说AS3是一头猪,它占用了很多资源,但这确实很重要。您的示例限制了1G的ram,但并没有释放它。至少这是你被引导去相信的。仅仅因为GC没有,并不意味着1G是不可用的,它只是意味着flash正在保留它。当flash播放器感觉需要释放内存时,它会释放内存,这是因为你正确地标记了GCG的所有内容。当使用3 GCs时,它会使用参考计数、标记和扫描。标记和扫描速度很慢,这是您试图通过将对象设置为null并删除事件侦听器和对该对象的所有引用来避免的。玩家在正常情况下不会释放内存,因为分配内存是昂贵的,只有在有理由释放内存时才会这样做。调用System.gc()只是强制执行不需要执行的清理。我的总体观点是做好你的工作,正确地编程你的应用程序,播放器会完成它的工作,并在需要时清除内存。
try {
new LocalConnection().connect('foo');
new LocalConnection().connect('foo');
} catch (e:*) {}