Jor*_*jon 7 memory flash actionscript actionscript-3
我有这个空白项目,只是为了检查System.totalMemory变量.据我所知,我得到这个值:
3076
3092
3096
3088
3092
3096
3100
3104
3108
3112
3117
3121
3125
3129
3133
3137
3141
3145
3149
...
And so on
Run Code Online (Sandbox Code Playgroud)
我没有打开Flash,没有Internet浏览器,没有其他闪存实例.
该项目为空白,只有一个静态文本和一个动态文本,称为"内存".一个*.as文件,包含以下代码:
package{
import flash.display.Sprite;
import flash.events.Event;
import flash.system.System;
import flash.text.TextField;
public class Test extends Sprite {
public function Test() {
this.addEventListener(Event.ENTER_FRAME,Loop);
}
public function Loop(e:Event) {
memory.text = String(System.totalMemory);
}
}
}
Run Code Online (Sandbox Code Playgroud)
这些是我的发布设置.

我在Debug和Published*.swf中测试了相同的结果.
我对此没有任何线索,所以请帮忙.
Jua*_*ano 25
我觉得你有一些错误.
首先,您的跟踪显示totalMemory截断最后3位数字(因为您没有在代码中执行此操作,我认为这是因为TextField宽度).它像这样增长:3076,3092,3096等.这些是(大致)千字节,而不是字节.然后你评论:"2小时后的总记忆:3887104.我的上帝".现在,如果用3,887,104表示3,887,104 Kb,则约为3.8 Gb.我怀疑是这种情况,所以我们假设你的意思是3,887,104字节.那大概是3,800 Kb或3.8 Mb.实际上并没有那么多记忆,更重要的是,距你最初的3,076 Kb还不远.
我认为这实际上误导了另一张海报,认为玩家将内存使用量增加了4个字节,实际上它增加了4,096字节或4 Kb.
其次,即使代码非常简单,它也会消耗内存.对于初学者,每次调度ENTER_FRAME事件时,都会创建一个Event对象,该对象又包含对其他对象,字符串等的引用.这需要记忆.然后,您将隐式地将数字转换为字符串(通过打印totalMemory).无论你是否进行显式转换,这都会占用内存(如果你创建一个跟踪而不是使用文本字段,则同样适用).最重要的是,从"动作"的角度来看,肯定还有其他的东西是不明显的.
现在,我认为问题的一部分是你只是追踪当前的totalMemory.看着它,它似乎一直在缓慢但稳定地增长.这是事实,但你可能会错过的是,以较慢的速度,GC开始并释放大量已经积累的内存.
如果您修改代码以计算一些内容,则更明显.
package{
import flash.display.Sprite;
import flash.events.Event;
import flash.system.System;
import flash.text.TextField;
import flash.utils.getTimer;
import flash.text.TextField;
import flash.text.TextFormat;
public class Test extends Sprite {
private var peak:int = 0;
private var prev:int = 0;
private var cur:int = 0;
private var diff:int = 0;
private var decreaseCount:int = 0;
private var increaseCount:int = 0;
private var accumIncrease:int = 0;
private var accumDecrease:int = 0;
private var maxIncrease:int = 0;
private var maxDecrease:int = 0;
private var initTime:Number = 0;
private var elapsed:Number = 0;
private var time:TextField;
private var info:TextField;
public function Test() {
initTime = getTimer();
var tf:TextFormat = new TextFormat("Courier New",12);
time = new TextField();
time.defaultTextFormat = tf;
time.width = 250;
addChild(time);
info = new TextField();
info.defaultTextFormat = tf;
info.y = 15;
info.width = 250;
info.height = 250;
addChild(info);
addEventListener(Event.ENTER_FRAME,Loop);
}
public function Loop(e:Event) {
cur = System.totalMemory >> 12;
elapsed = (getTimer() - initTime) / 1000;
time.text = "time running: " + elapsed;
if(cur == prev) {
return;
}
if(cur > peak) {
peak = cur;
}
if(cur > prev && prev > 0) {
diff = cur - prev;
if(diff > maxIncrease) {
maxIncrease = diff;
}
accumIncrease += diff;
increaseCount++;
} else if(cur < prev) {
diff = prev - cur;
if(diff > maxDecrease) {
maxDecrease = diff;
}
accumDecrease += diff;
diff = -diff;
decreaseCount++;
}
info.text = "current: " + cur + "\n"
+ "previous: " + prev + "\n"
+ "diff: " + diff + "\n"
+ "peak: " + peak + "\n"
+ "increaseCount: " + increaseCount + "\n"
+ "decreaseCount: " + decreaseCount + "\n"
+ "accumIncrease: " + accumIncrease + "\n"
+ "accumDecrease: " + accumDecrease + "\n"
+ "maxIncrease: " + maxIncrease + "\n"
+ "maxDecrease: " + maxDecrease;
prev = cur;
}
}
}
Run Code Online (Sandbox Code Playgroud)
我使用4096字节的块作为单位(这就是为什么我在做System.totalMemory >> 12.只是一种奇特的方式来说System.totalMemory/4096).我认为它更易于管理,无论如何,totalMemory总是返回4096 byes或4kb的倍数.您可以在此处阅读有关Flash GC的更多信息:https://developer.mozilla.org/en/MMgc.播放器的那部分是开源的,如果你这么倾向,你甚至可以阅读这些资源.
关于代码跟踪的简要说明:
现在,让我们看看使用此代码拍摄的一些"快照".
这是早期快照,当swf运行3秒钟时拍摄.请注意,目前读取760.
大约10分钟后:
有几点需要注意:
现在,让瑞士法郎再跑一段时间.运行50分钟后,快照如下所示:
此时你可能会认为有泄漏.注意当前内存是931,而不是最初的760.
但看看3124秒,52分钟发生的事情:
在GC开始之前,峰值增长到962.但在那之后,当前下降到767,再次非常接近最初的760.
因此,为了将其包装起来,内存使用量增长的事实并不一定意味着存在泄漏.你只需要处理玩家被垃圾收集的事实,而且这个过程是不确定的.记忆最终会在某个时候被回收(当然,除非你的代码确实存在泄漏).您无法确定何时会发生这种情况.当玩家确定有必要时会发生这种情况.一般来说,玩家会更清楚.
也就是说,我认为注意代码中可能存在的泄漏非常重要.但只是跟踪System.totalMemory不会帮助您确定.如果可以,请使用Flex Builder的内存分析器等工具,这不是完美的,但会为您提供更多有用的信息.在向舞台添加监听器和使用计时器时要小心,闪存播放器中内存泄漏的最大罪魁祸首.