AS3遊戲中可視對象上限及位圖相干的內存耗損實測

前些天持續做了一些測試,以減深對AS3的┞菲握戰正在項目中洞課戲機能、效率劣化圓裏的一些處理,有許多測試實踐意義沒有年夜,皆不外是證實一些猜念是正確的,除此出有甚麼。

但前天停止的一戲誦測試中,有一些洞課戲開發中的內存佔趺,CPU佔趺圓裏又供意義,我籌算逐步寫幾篇會商性的文┞仿取各人同享。
因爲最遠正在做的是2D的等距視角遊轄爆局部接納的位圖處理,取3D無閉,以是存眷的也是那圓裏的問題,思索問題的動身面也是那些圓裏,因而存眷裏仍是比力狹小的。

  1、先從那類2D遊戲中經常使用的對象類型的簡單測試去開端看AS3的蹬鰱是如何撐持
那隻能是管窺一斑,我也只能是據囪碰面推測,至於AS3蹬鰱到底如何完成,年夜可沒必要來弄的很分明,但測試的成果仍由以正在我們寫代碼時,做到胸有定見。

先去看測試函數代碼private function compareDisplayObject():void
{
        len1 = System.totalMemory;
        _txt.text = "測試前總內存鉅細爲:" + len1.toString();
        
        var sprite:Sprite = new Sprite();
        len2 = System.totalMemory;
        _txt.appendText("\nnew Sprite後總內存鉅細爲:" + len2.toString());
        _txt.appendText("\nnew Sprite後增長的內存爲:" + (len2 - len1).toString());
        
        var bmp:Bitmap = new Bitmap();
        len1 = System.totalMemory;
        _txt.appendText("\n\nnew Bitmap後總內存鉅細爲:" + len1.toString());
        _txt.appendText("\nnew Bitmap後增長的內存爲:" + (len1 - len2).toString());
        
        var shape:Shape = new Shape();
        len2 = System.totalMemory;
        _txt.appendText("\n\nnew Shape後總內存鉅細爲:" + len2.toString());
        _txt.appendText("\nnew Shape後增長的內存爲:" + (len2 - len1).toString());
        
        var rect:Rectangle = new Rectangle(0, 0, 200, 100);
        len1 = System.totalMemory;
        _txt.appendText("\n\nnew Rectangle,鉅細爲200*100後總內存鉅細爲:" + len1.toString());
        _txt.appendText("\nnew Rectangle,鉅細爲200*100後增長的內存爲:" + (len1 - len2).toString());
        
        //正文失落上面冶,零丁測試將sprite、bmp、shape三個空對象加減到隱示列表。
        sprite.graphics.drawRect(0, 0, 200,100);
        len2 = System.totalMemory;
        _txt.appendText("\n\nsprite畫造200*100的矩形後總內存鉅細爲:" + len2.toString());
        _txt.appendText("\nsprite畫造200*100的矩形後增長的內存爲:" + (len2 - len1).toString());
        shape.graphics.drawRect(0,0,200,100)
        len1 = System.totalMemory;
        _txt.appendText("\n\nshape畫造200*100的矩形後總內存鉅細爲:" + len1.toString());
        _txt.appendText("\nshape畫造200*100的矩形後增長的內存爲:" + (len1 - len2).toString());
        
        this.addChild(sprite);
        len2 = System.totalMemory;
        _txt.appendText("\n\n將sprite加減到舞臺後總內存鉅細爲:" + len2.toString());
        _txt.appendText("\nsprite加減到舞臺後增長的內存爲:" + (len2 - len1).toString());
        this.addChild(bmp);
        len1 = System.totalMemory;
        _txt.appendText("\n\n將bmp加減到舞臺後總內存鉅細爲:" + len1.toString());
        _txt.appendText("\nbmp加減到舞臺後增長的內存爲:" + (len1 - len2).toString());
        this.addChild(shape);
        len2 = System.totalMemory;
        _txt.appendText("\n\n將shape加減到舞臺後總內存鉅細爲:" + len2.toString());
        _txt.appendText("\nshape加減到舞臺後增長的內存爲:" + (len2 - len1).toString());
}
 

轉載註明盛世遊戲:http://www.shengshiyouxi.com 

再去看輸出成果:
//------------------------------------------------>
  測試前總內存鉅細爲:3162112
new Sprite後總內存鉅細爲:3162112
new Sprite後增長的內存爲:0

new Bitmap後總內存鉅細爲:3162112
new Bitmap後增長的內存爲:0

new Shape後總內存鉅細爲:3170304
new Shape後增長的內存爲:8192

new Rectangle,鉅細爲200*100後總內存鉅細爲:3182592
new Rectangle,鉅細爲200*100後增長的內存爲:12288

sprite畫造200*100的矩形後總內存鉅細爲:3190784
sprite畫造200*100的矩形後增長的內存爲:8192

shape畫造200*100的矩形後總內存鉅細爲:3198976
shape畫造200*100的矩形後增長的內存爲:8192

將sprite加減到舞臺後總內存鉅細爲:3207168
sprite加減到舞臺後增長的內存爲:8192

將bmp加減到舞臺後總內存鉅細爲:3211264
bmp加減到舞臺後增長的內存爲:4096

將shape加減到舞臺後總內存鉅細爲:3215360
shape加減到舞臺後增長的內存爲:4096
  [color=ize:13px]//------------------------------------------------>
  前天測試時,每次運轉FP,第一次根本上new Sprite,Bitmap,Shape後增長的內存皆沒有爲0,前兩者皆是4096,Shape是8192,但明天每次從頭運轉前裏兩個對象new 後內存增長皆是0。

運轉當前,屢次挪用那個函數,輸出的內容能夠看到內存每次反覆挪用時皆正在之前根底梢減,但那寂new 操做以後,內存的增長經常0,而Shape爲0的時分很少,大都是4096,偶然是8192。

我推測,那該當實了止時環境以爲new 出去的式昌,出有利用,而且援用計數也是0,以是被收受接管了,那從輸出內容的前面一些部門(對象被加減到隱示列表中),所隱示的內存增長一直年夜於0能夠看出去。

可是重複挪用那個函數時,將sprite式昌加減到隱示列表中,使得增長的內村卻經常正在4096戰8192之間變更,那讓我感應很是疑惑,念沒有到公道的解釋。

  2、對sprite,bitmap,shape  new 一批空對象,及將一批空對象加減到隱示列表的內存佔趺測試
那裏說的空對象沒有是指null的無值狀況,而是僅指new以後,沒有減任那邊理或賦值的狀況。

先去看測試代碼:private function compareMultiDisplayObject():void
{
        //每類對象new的個數
        var num:uint = 1000;                        
        
        len1 = System.totalMemory;
        _txt.text = "每匆汛建" + num.toString() + "個同類對象,測試前總內存鉅細爲:" + len1.toString();
        
        var i:uint;
        var sprite:Sprite;
        var bmp:Bitmap;
        var shape:Shape;
        
        for (i = 0; i < num; i++)
        {
                sprite = new Sprite();
               
                //恢復以下正文,讓new出去的對象有援用計數,躲免對象被以爲無利用而被收受接管
                //arr.push(sprite);
        }
        len2 = System.totalMemory;
        _txt.appendText("\nnew Sprite後總內存鉅細爲:" + len2.toString());
        _txt.appendText("\nnew Sprite後增長的內存爲:" + (len2 - len1).toString() + " || 均勻每一個增長:" + ((len2 - len1)/num).toString());
        
        
        for (i = 0; i < num; i++)
        {
                bmp = new Bitmap();
                //arr.push(bmp);
        }                        
        len1 = System.totalMemory;
        _txt.appendText("\n\nnew Bitmap後總內存鉅細爲:" + len1.toString());
        _txt.appendText("\nnew Bitmap後增長的內存爲:" + (len1 - len2).toString() + " || 均勻每一個增長:" + ((len1 - len2)/num).toString());
        
        for (i = 0; i < num; i++)
        {
                shape = new Shape();
                //arr.push(shape);
        }                        
        len2 = System.totalMemory;
        _txt.appendText("\n\nnew Shape後總內存鉅細爲:" + len2.toString());
        _txt.appendText("\nnew Shape後增長的內存爲:" + (len2 - len1).toString() + " || 均勻每一個增長:" + ((len2 - len1)/num).toString());
        
        _txt.appendText("\n\n================以下爲創立並加減到隱示列表================");
        
        for (i = 0; i < num; i++)
        {
                sprite = new Sprite();
                this.addChild(sprite);
        }
        len1 = System.totalMemory;
        _txt.appendText("\nnew Sprite後總內存鉅細爲:" + len1.toString());
        _txt.appendText("\nnew Sprite後增長的內存爲:" + (len1 - len2).toString() + " || 均勻每一個增長:" + ((len1 - len2)/num).toString());
        
        
        for (i = 0; i < num; i++)
        {
                bmp = new Bitmap();
                this.addChild(bmp);
        }                        
        len2 = System.totalMemory;
        _txt.appendText("\n\nnew Bitmap後總內存鉅細爲:" + len2.toString());
        _txt.appendText("\nnew Bitmap後增長的內存爲:" + (len2 - len1).toString() + " || 均勻每一個增長:" + ((len2 - len1)/num).toString());
        
        for (i = 0; i < num; i++)
        {
                shape = new Shape();
                this.addChild(shape);
        }                        
        len1 = System.totalMemory;
        _txt.appendText("\n\nnew Shape後總內存鉅細爲:" + len1.toString());
        _txt.appendText("\nnew Shape後增長的內存爲:" + (len1 - len2).toString() + " || 均勻每一個增長:" + ((len1 -len2)/num).toString());
}
    

轉載註明盛世遊戲:http://www.shengshiyouxi.com


   前一部分測試是創建一批空對象,不作任何其他的操作,那麼這些對象的引用計數應該是0
後面一部分測試是創建一批空對象,並將創建的每個對象隨後添加到了顯示列表,那麼這批對象就同時有了引用計數,也即不對這些對象進行其他處理情況下的內存佔用。但對Bitmap對象還是略有不同,因爲並有爲其new 一個bitmapData對象實例,所以bitmap所佔內存這裏輸出的要比實際的低

下面來看測試輸出:
  [color=ize:13px]//------------------------------------------------------------------------------->
  每次創建1000個同類對象,測試前總內存大小爲:3158016
new Sprite後總內存大小爲:3665920
new Sprite後增加的內存爲:507904 || 平均每個增加:507.904

new Bitmap後總內存大小爲:3788800
new Bitmap後增加的內存爲:122880 || 平均每個增加:122.88

new Shape後總內存大小爲:4141056
new Shape後增加的內存爲:352256 || 平均每個增加:352.256

================以下爲創建並添加到顯示列表================
new Sprite後總內存大小爲:3760128
new Sprite後增加的內存爲:-380928 || 平均每個增加:-380.928

new Bitmap後總內存大小爲:4505600
new Bitmap後增加的內存爲:745472 || 平均每個增加:745.472

new Shape後總內存大小爲:4886528
new Shape後增加的內存爲:380928 || 平均每個增加:380.928
  [color=ize:13px]//-------------------------------------------------------------------------------->
  可以看到輸出中的這段:
  [color=ize:13px]//------------------------------------------------------------->
  new Sprite後總內存大小爲:3760128
new Sprite後增加的內存爲:-380928
  [color=ize:13px]//------------------------------------------------------------->
  內存增加是負值,如果看作是之前new 出的一批對象實例被回收了,重新創建一批Sprite實例,並添加到顯示列表中,比之前僅創建Sprite而不添加到顯示列表的內存“new Sprite後總內存大小爲:3665920”相比來說,還算是比較合理的。

所以這個負值也就不意外了。
另外,從這個測試函數內的源碼註釋部分,可以看到“arr.push(sprite);”這樣幾行,是當時測試new 出來的這一批對象,不添加到顯示列表,僅僅增加引用計數而進行的測試,可以與添加到顯示列表的內存開銷進行一下對比。
  [color=ize:13px]//-------------------------------------------------------------------------------->
  每次創建1000個同類對象,測試前總內存大小爲:3158016
new Sprite後總內存大小爲:3670016
new Sprite後增加的內存爲:512000 || 平均每個增加:512

new Bitmap後總內存大小爲:4444160
new Bitmap後增加的內存爲:774144 || 平均每個增加:774.144

new Shape後總內存大小爲:4796416
new Shape後增加的內存爲:352256 || 平均每個增加:352.256

================以下爲創建並添加到顯示列表================
new Sprite後總內存大小爲:5373952
new Sprite後增加的內存爲:577536 || 平均每個增加:577.536

new Bitmap後總內存大小爲:6160384
new Bitmap後增加的內存爲:786432 || 平均每個增加:786.432

new Shape後總內存大小爲:6500352
new Shape後增加的內存爲:339968 || 平均每個增加:339.968
  [color=ize:13px]//---------------------------------------------------------------------------------->
  看兩段輸出,很清楚,可以對比着看,不解釋。

  三、對圖片加載和位圖常用操作的對比測試

先看測試函數,這個函數寫的還早,測試的還早,所以對輸出文字的處理跟前面兩個有點不一樣。private function compareBitmap():void
{
        var loader:Loader = new Loader();
        var path:String = "1.png";
        
        var url:URLRequest = new URLRequest(path);
        loader.contentLoaderInfo.addEventListener(Event.COMPLETE, imageLoader_Complete);
        len2 = System.totalMemory;
        _txt.text = "載入圖片前總內存大小爲:" + len2.toString();
        loader.load(url);
}

private function imageLoader_Complete(e:Event):void
{
        var text:String;
        len1 = System.totalMemory;
        text = _txt.text + "\n載入圖片後總內存大小爲:" + len1.toString();
        
        text += "\n載入後增加的內存大小爲:" + (len1 - len2).toString();
        
        var loader:Loader = e.target.loader as Loader;
        var bmp:Bitmap = loader.content as Bitmap;
        text += "\n\nloader的總字節數爲:" + loader.contentLoaderInfo.bytesTotal.toString();
        text += "\nBitmap的總字節數爲:" + bmp.loaderInfo.bytesTotal.toString();
        
        text += "\n當前總內存大小爲:" + System.totalMemory.toString();
        
        var bmpData:BitmapData = bmp.bitmapData;
        len2 = System.totalMemory;
        text += "\n\nBitmapData賦值後的總內存大小爲:" + len2.toString();
        bmpData.copyPixels(bmp.bitmapData, new Rectangle(0,0,bmp.width,bmp.height), new Point(0, 0));
        len1 = System.totalMemory;
        text += "\ncopyPixels位圖對象的bitmapData後的總內存大小爲:" + len1.toString();
        bmpData.draw(bmp);
        len2 = System.totalMemory;
        text += "\nbitmapData.draw()位圖對象後的總內存大小爲:" + len2.toString();
        var bmp1:Bitmap = new Bitmap();
        text += "\nnew一個Bitmap空對象bmp1後的總內存大小爲:" + System.totalMemory.toString();
        bmp1.bitmapData = bmpData;
        text += "\n對bmp1.bitmapData賦值後的總內存大小爲:" + System.totalMemory.toString();
        var bmp2:Bitmap = new Bitmap(bmpData);
        text += "\n使用得到的bmpData對象生成bmp2後的總內存大小爲:" + System.totalMemory.toString();
        this.addChild(bmp1);
        text += "\n將bmp1添加到顯示列表後的總內存大小爲:" + System.totalMemory.toString();
        this.addChild(bmp2);
        text += "\n將bmp2添加到顯示列表後的總內存大小爲:" + System.totalMemory.toString();
        
        bmp1.x = 300;
        bmp1.y = 0;
        bmp2.x = 400;
        bmp2.y = bmp2.height + 10;
        
        text += "\n\n圖片寬度=" + bmp.width.toString() + ",高度=" + bmp.height.toString();
        text += "\n按PNG圖片像素內存佔用<ARGB*width*height>\n來計算,則純像素佔內存= 4 * " + bmp.width.toString() + " * " + bmp.height.toString() + " =" + (4 * bmp.width * bmp.height).toString();;
        
        len2 = System.totalMemory;
        text += "\n\n當前總內存大小爲:" + len2;
        bmpData = bmp.bitmapData.clone();
        len1 = System.totalMemory;
        text += "\n克隆位圖對象的bitmapData後的總內存大小爲:" + len1.toString();
        text += "\n克隆後增加的內存大小爲:" + (len1 - len2).toString();
        
        var num:uint = 1000;
        var j:uint;
        var tempBMP:Bitmap;
        var rect:Rectangle = new Rectangle(0, 0, bmp.width, bmp.height);
        var vertex:Point = new Point(0, 0);
        var dt:int = getTimer();
        len2 = System.totalMemory;
        text += "\n\nnum=" + num.toString() + " || 當前總內存大小爲:" + len2;                        
        for (j = 0; j < num; j++)
        {
                tempBMP = new Bitmap();
                //tempBMP.bitmapData = bmp.bitmapData;
                tempBMP.bitmapData = new BitmapData(bmp.width, bmp.height);
                tempBMP.bitmapData.copyPixels(bmp.bitmapData, rect, vertex);
               
                this.addChild(tempBMP);
                tempBMP.x = j + 300;
                tempBMP.y = j;
        }
        len1 = System.totalMemory;
        dt = getTimer() - dt;
        text += "\n生成num個位圖並添加到顯示列表中後的總內存大小爲:" + len1.toString();
        text += "\n生成num個位圖並添加到顯示列表中後增加的內存大小爲:" + (len1 - len2).toString();
        text += "\n花費時間:" + dt.toString() + "毫秒 || 平均操作每個對象需時:" + (dt / num).toString();
        _txt.text = text;
}
   轉載註明盛世遊戲:http://www.shengshiyouxi.com
對上面這段代碼裏面的for循環裏面部分,以循環1000次爲例,我進行三種測試。for (j = 0; j < num; j++)
{
        tempBMP = new Bitmap(bmp.bitmapData);
        
        this.addChild(tempBMP);
        tempBMP.x = j + 300;
        tempBMP.y = j;
}
  
上面這種測試由載入的bitmapData直接生成要使用的位圖,以方便添加到顯示列表中使用。

上面這種測試輸出是:
  [color=ize:13px]//------------------------------------------------------------------------->
  載入圖片前總內存大小爲:3174400
載入圖片後總內存大小爲:3526656
載入後增加的內存大小爲:352256

loader的總字節數爲:61831
Bitmap的總字節數爲:61831
當前總內存大小爲:3526656

BitmapData賦值後的總內存大小爲:3526656
copyPixels位圖對象的bitmapData後的總內存大小爲:3526656bitmapData.draw()位圖對象後的總內存大小爲:3526656
new一個Bitmap空對象bmp1後的總內存大小爲:3526656
對bmp1.bitmapData賦值後的總內存大小爲:3526656
使用得到的bmpData對象生成bmp2後的總內存大小爲:3526656
將bmp1添加到顯示列表後的總內存大小爲:3526656
將bmp2添加到顯示列表後的總內存大小爲:3526656

圖片寬度=256,高度=255
按PNG圖片像素內存佔用<ARGB*width*height>
來計算,則純像素佔內存= 4 * 256 * 255 =261120

當前總內存大小爲:3526656
克隆位圖對象的bitmapData後的總內存大小爲:3788800
克隆後增加的內存大小爲:262144

num=1000 || 當前總內存大小爲:3788800
生成num個位圖並添加到顯示列表中後的總內存大小爲:4452352
生成num個位圖並添加到顯示列表中後增加的內存大小爲:663552
花費時間:103毫秒 || 平均操作每個對象需時:0.103
  [color=ize:13px]//----------------------------------------------------------------------------->

  再來看將for中代碼修改爲new出一個空bitmap之後,對其bitmapData賦值的做法,有沒有不同。for (j = 0; j < num; j++)
{
        tempBMP = new Bitmap();
        tempBMP.bitmapData = bmp.bitmapData;
        
        this.addChild(tempBMP);
        tempBMP.x = j + 300;
        tempBMP.y = j;
}
   
  請看輸出:
  [color=ize:13px]//-------------------------------------------------------------------------------->
  載入圖片前總內存大小爲:3174400
載入圖片後總內存大小爲:3526656
載入後增加的內存大小爲:352256

loader的總字節數爲:61831
Bitmap的總字節數爲:61831
當前總內存大小爲:3526656

BitmapData賦值後的總內存大小爲:3526656
copyPixels位圖對象的bitmapData後的總內存大小爲:3526656
bitmapData.draw()位圖對象後的總內存大小爲:3526656
new一個Bitmap空對象bmp1後的總內存大小爲:3526656
對bmp1.bitmapData賦值後的總內存大小爲:3526656
使用得到的bmpData對象生成bmp2後的總內存大小爲:3526656
將bmp1添加到顯示列表後的總內存大小爲:3526656
將bmp2添加到顯示列表後的總內存大小爲:3526656

圖片寬度=256,高度=255
按PNG圖片像素內存佔用<ARGB*width*height>
來計算,則純像素佔內存= 4 * 256 * 255 =261120

當前總內存大小爲:3526656
克隆位圖對象的bitmapData後的總內存大小爲:3788800
克隆後增加的內存大小爲:262144

num=1000 || 當前總內存大小爲:3788800
生成num個位圖並添加到顯示列表中後的總內存大小爲:4456448
生成num個位圖並添加到顯示列表中後增加的內存大小爲:667648
花費時間:17毫秒 || 平均操作每個對象需時:0.017
  [color=ize:13px]//------------------------------------------------------------------------------->
  我之前試了很多次,這種處理,會比上面一種生成時直接以bitmapData來生成bitmap花費的時間要長一點,內存也多一點,不知這次如何,我修改代碼後運行直接把輸出複製過來了,也沒細看。
提交以後看到前一次的輸出,時間好久,喜歡動手的下載下面的RAR文件自己多測試幾次吧,有時候測試效果不穩定,這很無奈。

下面來看另一種情況,new 出來bitmap後再new 出來一個bitmapData不填充值的對象,然後再利用其CopyPixels函數來處理,在看代碼和效果前,一定明白這樣相當於這個bitmap採用了一張新的位圖,而CopyPixels函數,只是把另外一張位圖中的數據重新指向過來。看完修改的代碼和輸出後,下面再細說。for (j = 0; j < num; j++)
{
        tempBMP = new Bitmap();
        tempBMP.bitmapData = new BitmapData(bmp.width, bmp.height);
        tempBMP.bitmapData.copyPixels(bmp.bitmapData, rect, vertex);
        
        this.addChild(tempBMP);
        tempBMP.x = j + 300;
        tempBMP.y = j;
}
   
  請看輸出:
  [color=ize:13px]//------------------------------------------------------------------------------------>
  載入圖片前總內存大小爲:3174400
載入圖片後總內存大小爲:3530752
載入後增加的內存大小爲:356352

loader的總字節數爲:61831
Bitmap的總字節數爲:61831
當前總內存大小爲:3530752

BitmapData賦值後的總內存大小爲:3530752
copyPixels位圖對象的bitmapData後的總內存大小爲:3530752
bitmapData.draw()位圖對象後的總內存大小爲:3530752
new一個Bitmap空對象bmp1後的總內存大小爲:3530752
對bmp1.bitmapData賦值後的總內存大小爲:3530752
使用得到的bmpData對象生成bmp2後的總內存大小爲:3530752
將bmp1添加到顯示列表後的總內存大小爲:3530752
將bmp2添加到顯示列表後的總內存大小爲:3530752

圖片寬度=256,高度=255
按PNG圖片像素內存佔用<ARGB*width*height>
來計算,則純像素佔內存= 4 * 256 * 255 =261120

當前總內存大小爲:3530752
克隆位圖對象的bitmapData後的總內存大小爲:3792896
克隆後增加的內存大小爲:262144

num=1000 || 當前總內存大小爲:3792896
生成num個位圖並添加到顯示列表中後的總內存大小爲:266907648
生成num個位圖並添加到顯示列表中後增加的內存大小爲:263114752
花費時間:1236毫秒 || 平均操作每個對象需時:1.236
  [color=ize:13px]//------------------------------------------------------------------------------------>
  看看上面輸出結果的最後兩行,是不是很讓人驚奇,好大的內存增加,以及好長的時間花費,CPU佔用還好,我第一次測試時,num=10000,最後超過默認的15秒不響應限制,也沒有出來結果,但CPU佔用一直穩定在25%(僅FP,還是在debug模式下),而且操作系統提示虛擬內存不足。

從最後一個測試可以看出,我們要儘量少用new BitmapData()這個函數,如果使用了這個函數,基本相當於引入了一張新位圖圖片。

[color=ize:16px]四、結論和我的猜測
結論將是由以上測試總結出的可驗證的判斷,但我的猜測就不行了,將僅僅是這些結論往前回溯性的猜測,所以可能被我蒙中了,也可能根本就是瞎猜,看到的各位,可以算做拋磚引玉,由此討論,但不要就此擡扛。

  1、通過前面對CopyPixels函數的測試,可以看到,這個函數是極節省內存的。與直接使用一個位圖的bitmapData數據生成一個新的bitmap基本沒有差別。而且速度也很不錯。
//--------------------------------------------------------------->
  num=1000 || 當前總內存大小爲:3788800
生成num個位圖並添加到顯示列表中後的總內存大小爲:4452352
生成num個位圖並添加到顯示列表中後增加的內存大小爲:663552
花費時間:103毫秒 || 平均操作每個對象需時:0.103
  [color=ize:16px]//--------------------------------------------------------------->
  這段輸出是對循環1000次,先給bitmapData賦值,再調用CopyPixels的測試輸出,看內存的增加與,跟去掉CopyPixels操作之後基本沒有差別。
  
  2、在使用位圖資源時,儘可能的少用new BitmapData來生成位圖,因爲這相當於載入了一張新位圖。

  3、位圖資源無論文件本身如何壓縮,如何小,但載入內存後,其佔用的內存空間,基本可按<ARGB*width*height>來計算,當然實際結果會比這個數值略大,這可以從測試中的Clon()函數的調用內存增加看出。

4、由結論3,可以推導出一個遊戲的flash客戶端中,究竟可以引入多少位圖資源,按照webgame的內存佔用率一半,CPU等計算資源30%的原則來算佔用的最大內存,單獨一個web game的內存佔用量上限可考慮300MB~600MB,以輕量級的web game 上限內存300MB來算,那就是1024*1024分辯率的圖片JPG之類無alpha通道的圖片100張,PNG格式有alpha通道的圖片75張,無論是矢量存儲載入後轉位圖,還是直接就是位圖。而這個位圖資源的上限公式,可以作爲一個遊戲項目的主策劃用來限制隨意策劃的一個測量標尺。

  //---------------------------------------------------------------------------------------------------------------------->
  以下是我猜測性的推論,請審慎視之
1、從內存增量上來看,使用已載入的位圖資源數據來new 出一個新的位圖,應該僅是生成了一個位圖對象,而實際的位圖數據還是指向原始的位圖資源。

2、人爲的在代碼中調用垃圾回收機制,既沒必要,也不需要,反而徒增系統資源的浪費。

3、普通對象的引用計數清除很重要,這關係到這些對象佔用內存的回收。

4、位圖類對象的位圖數據,調用銷燬函數很有必要,在不使用某個位圖資源時,將某個位圖資源手動銷燬,垃圾回收並不起作用。

5、bitmapData相比普通的類對象,要特別一點,特別之處有二,一是該對象引用指向的對象實際數據區,需要手動銷燬才能退出佔用的內存;另一是對該對象引用指向的實際數據,在進行數據修改,以讓其顯示的位圖有不同的顯示效果時,該修改並不是直接在實際的原始數據上進行修改的。

6、從bitmapData的特別之處,可以看到,流佈於一些AS3效率優化文章內的慎用濾鏡等之類的看法,應該也是這個問題的延伸。

發佈了25 篇原創文章 · 獲贊 1 · 訪問量 2萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章