为什么Sytem.totalMemory不断增加?(Why Sytem.totalMemory ke

2019-07-29 01:10发布

我有这个空白项目,只是为了检查出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文件,同样的结果进行测试。

我就这一个毫无头绪,所以请大家帮忙。

Answer 1:

我觉得你有几件事情是错误的。

首先,你的痕迹显示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

一对夫妇的注意事项:

  1. 约10分钟后,电流非常接近它是什么,在3秒:763 VS 760这意味着,现在,该totalMemory为3.052 MB; 在3秒,这是3040兆。
  2. 增加数很高,而且下降计数低。 这意味着玩家已分配的内存了很多次,但它释放非常谨慎。
  3. maxIncrease低,maxDecrease高。 即加入2)和你有一个野趣模式:玩家经常分配少量块。 它释放他们以很慢的速度; 当它,但是,它释放块的一个大数目。
  4. 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播放器的内存泄漏的罪魁祸首时要小心。



Answer 2:

您可能要检查,看看你正在运行的Flash播放器版本。 如果你有IDE安装有你在播放器的调试版本中运行一个像样的机会 - 这往往不释放内存几乎经常(如果有的话)相比于普通球员。

如果您在调试播放器中运行,你可以强制GC扫 - System.gc()的;



Answer 3:

据我所知,在每个循环中,调用System.totalMemory返回表示内存字节当前在使用由Flash量的UINT。 通过调用System.totalMemory返回的UINT存储在内存中(即您的RAM,而不是你已经标有“记忆”的文本框)。 然后,将参考memory.text被更新为指向由UINT占据存储器的空间。 老UINT仍然在内存中,但有它没有提及。 的uint是数据的32位(4个字节),所以你看到的,每次4个字节的内存占用量增加。 一旦垃圾收集器运行时,由现在derefrenced的uint占据内存空间应该得到释放,你应该看到内存下降。

然而,当我运行示例代码,我什么也没有这样。 它上升和下降,不会持续上去像你这样的,但我在OS X所以这是一个完全不同的球员。



Answer 4:

由于在文本框的文本更改,Flash将在加载不同的字符内存来显示它们。 这可以解释的几百个字节增加你得到。

孑然一​​身,如何更大的不足迹得到什么?

UPDATE:有想过这个问题,我认为这是将要被Flash创建的呈现文本临时点阵图形做......虽然你不会想到与跟踪......虽然跟踪必须做一些内部的东西太多...

你有没有想过在FlexBuilder中运行呢? 具有分析工具,它会告诉你你的内存是怎么回事。



Answer 5:

也许这是显而易见的,但要记住,System.totalMemory给你的内存由Flash Player(静态)的使用量。 如果您有其他Flash应用程序打开,这或许可以解释为什么你的内存增加。



文章来源: Why Sytem.totalMemory keeps increasing?