我有这个空白项目,只是为了检查出System.totalMemory变量。 据我所看到的,我得到这个值:
3076
3092
3096
3088
3092
3096
3100
3104
3108
3112
3117
3121
3125
3129
3133
3137
3141
3145
3149
...
And so on
我没有打开Flash,没有互联网浏览器,闪光灯没有其他实例。
该项目是空白,只有一个静态文本,以及一个动态文本,被称为“记忆”。 其中*。作为文件,包含此代码:
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);
}
}
}
这些都是我的发布设置。
我在调试和已发布的* .swf文件,同样的结果进行测试。
我就这一个毫无头绪,所以请大家帮忙。
我觉得你有几件事情是错误的。
首先,你的痕迹显示totalMemory截断最后3位数字(因为你没有在代码中这样做,我想这是因为文本字段宽度)。 它生长是这样的:3076,3092,3096,等等,这些都是(大致)千字节,而不是字节。 然后,你对此有何评论:“totalMemory 2小时后:3887104.我的神”。 现在,如果通过3887104你的意思是3887104 KB,这将是约3.8 GB。 我怀疑是这样的话,让我们假设你的意思是3887104个字节。 这是3800 KB或3.8 MB。 没有那么多的内存,其实,更重要的是,迄今没有从最初的3076 KB。
我认为这实际上误导另一个海报觉得玩家是由4个字节,当它实际上是4096个字节,或4 KB的增量递增的内存使用情况。
其次,即使代码很简单,但它消耗的内存。 对于初学者来说,每个ENTER_FRAME分派事件时,事件对象,又包含对其他对象,字符串等的参考,将创建。 这需要内存。 那么你是一个数转换成字符串隐式(通过打印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;
}
}
}
我使用的4096个字节为单位的块(这就是为什么我做System.totalMemory >> 12只是一个奇特的方式说System.totalMemory / 4096)。 我认为这是更易于管理反正totalMemory总是返回4096个轮空或4KB倍数。 你可以阅读更多有关Flash的GC这里: https://developer.mozilla.org/en/MMgc 。 播放器的那部分是开源的,你甚至可以读到的资料,如果你是这样的倾向。
在代码跟踪内容的简短说明:
- 运行时间:自SWF开始运行秒钟以后
- 电流:通过System.totalMemory返回,以4 KB的块的内存量
- 以前:totalMemory先前的值
- DIFF:当前和以前的区别。 可能是负的。 这表明,如果你的内存使用量增加或相对于以前的值下降。
- 高峰:自我解释。 这是不是很重要。
- increaseCount:次目前数量是大于以前。 基本上,它告诉你totalMemory了多少次增加,至少1块。
- decreaseCount:次以前的数量比更大的电流。 这会告诉你多少次内存已被释放。
- accumIncrease:阳性差异的累计值。 将让你知道有多少块已被分配。
- accumDecrease:负差异的累计值。 将让你知道有多少块已被释放。
- maxIncrease:二环路内执行分配的块的最大数量。
- maxDecrease:二环路内执行释放块的最大数量。
现在,让我们来看看一些“快照”使用此代码拍摄。
这是一个早期的快照,当财富基金已经运行3秒拍摄。 只要注意,目前的读取760。
- 时间运行:3秒
- 电流:760
- 上一篇:759
- DIFF:1
- 高峰:760
- increaseCount:3
- decreaseCount:0
- accumIncrease:6
- accumDecrease:0
- maxIncrease:3
- maxDecrease:0
约10分钟后:
- 时间运行:574秒
- 电流:763
- 上一篇:762
- curDiff:1
- 高峰:834
- increaseCount:127
- decreaseCount:3
- accumIncrease:132
- accumDecrease:123
- maxIncrease:3
- maxDecrease:72
一对夫妇的注意事项:
- 约10分钟后,电流非常接近它是什么,在3秒:763 VS 760这意味着,现在,该totalMemory为3.052 MB; 在3秒,这是3040兆。
- 增加数很高,而且下降计数低。 这意味着玩家已分配的内存了很多次,但它释放非常谨慎。
- maxIncrease低,maxDecrease高。 即加入2)和你有一个野趣模式:玩家经常分配少量块。 它释放他们以很慢的速度; 当它,但是,它释放块的一个大数目。
- accumIncrease和accumDecrease非常接近了。
现在,让SWF运行一些时间。 50分钟运行后,快照看起来是这样的:
- 时间运行:2989秒
- 电流:931
- 上一篇:930
- DIFF:1
- 高峰:931
- increaseCount:690
- decreaseCount:8
- accumIncrease:699
- accumDecrease:522
- maxIncrease:3
- maxDecrease:163
在这一点上,你可能会认为有泄漏。 注意当前的内存是如何931,与最初的760。
但是看看3124秒〜52分钟会发生什么:
- 时间运行:3142秒
- 电流:767
- 上一篇:768
- DIFF:-1
- 高峰:962
- increaseCount:720
- decreaseCount:10
- accumIncrease:730
- accumDecrease:717
- maxIncrease:3
- maxDecrease:194
在GC踢之前,峰值上升到962,但在那之后,目前就下到767,再次,非常接近最初的760。
所以,把它包起来,该内存使用成长并不一定意味着有一个泄漏的事实。 你只需要应付的事实,玩家收集垃圾,而这个过程是不确定性的。 内存将eventualy在某些时候被回收(除非你有你的代码的泄漏,当然)。 你无法确定何时会出现这种情况。 当玩家决定有必要它会发生。 而在一般情况下,玩家知道更好。
这么说,我觉得要注意可能的泄漏在你的代码是很重要的。 但是,仅仅跟踪System.totalMemory是不会帮助您确定。 如果可以的话,使用工具如Flex Builder的内存设置,这是不完美的,但给你更多有用的信息。 并增加听众的阶段,并使用定时器,在Flash播放器的内存泄漏的罪魁祸首时要小心。
您可能要检查,看看你正在运行的Flash播放器版本。 如果你有IDE安装有你在播放器的调试版本中运行一个像样的机会 - 这往往不释放内存几乎经常(如果有的话)相比于普通球员。
如果您在调试播放器中运行,你可以强制GC扫 - System.gc()的;
据我所知,在每个循环中,调用System.totalMemory返回表示内存字节当前在使用由Flash量的UINT。 通过调用System.totalMemory返回的UINT存储在内存中(即您的RAM,而不是你已经标有“记忆”的文本框)。 然后,将参考memory.text被更新为指向由UINT占据存储器的空间。 老UINT仍然在内存中,但有它没有提及。 的uint是数据的32位(4个字节),所以你看到的,每次4个字节的内存占用量增加。 一旦垃圾收集器运行时,由现在derefrenced的uint占据内存空间应该得到释放,你应该看到内存下降。
然而,当我运行示例代码,我什么也没有这样。 它上升和下降,不会持续上去像你这样的,但我在OS X所以这是一个完全不同的球员。
由于在文本框的文本更改,Flash将在加载不同的字符内存来显示它们。 这可以解释的几百个字节增加你得到。
孑然一身,如何更大的不足迹得到什么?
UPDATE:有想过这个问题,我认为这是将要被Flash创建的呈现文本临时点阵图形做......虽然你不会想到与跟踪......虽然跟踪必须做一些内部的东西太多...
你有没有想过在FlexBuilder中运行呢? 具有分析工具,它会告诉你你的内存是怎么回事。
也许这是显而易见的,但要记住,System.totalMemory给你的内存由Flash Player(静态)的使用量。 如果您有其他Flash应用程序打开,这或许可以解释为什么你的内存增加。