前些天連續做了一些測試,以加深對AS3的掌握和在項目中對 遊戲 性能、效率優化方面的一些處理,有很多測試實際意義不大,都不過是證明一些猜想是正确的,除此沒有什麼。
但前天進行的一系列測試中,有一些對遊戲開發中的記憶體占用,CPU占用方面有些意義,我打算逐漸寫幾篇讨論性的文章與大家共享。
由于最近在做的是2D的等距視角遊戲,全部采用的位圖處理,與3D無關,是以關注的也是這方面的問題,考慮問題的出發點也是這些方面,是以關注面還是比較狹窄的。
一、先從這類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());
}
再來看輸出結果:
//------------------------------------------------>
測試前總記憶體大小為: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
//------------------------------------------------>
前天測試時,每次運作FP,第一次基本上new Sprite,Bitmap,Shape後增加的記憶體都不為0,前二者都是4096,Shape是8192,但今天每次重新運作前面兩個對象new 後記憶體增加都是0。
運作以後,多次調用這個函數,輸出的内容可以看到記憶體每次重複調用時都在之前基礎上增加,但這幾個new 操作之後,記憶體的增加經常0,而Shape為0的時候很少,多數是4096,偶爾是8192。
我猜測,這應該是運作時環境認為new 出來的執行個體,沒有使用,并且引用計數也是0,是以被回收了,這從輸出内容的後面一些部分(對象被添加到顯示清單中),所顯示的記憶體增加始終大于0可以看出來。
但是反複調用這個函數時,将sprite執行個體添加到顯示清單中,使得增加的記憶體數卻經常在4096和8192之間變動,這讓我感到很是疑惑,想不到合理的解釋。
二、對sprite,bitmap,shape new 一批空對象,及将一批空對象添加到顯示清單的記憶體占用測試
這裡說的空對象不是指null的無值情況,而是僅指new之後,不加任何處理或指派的情況。
先來看測試代碼:
[javascript] view plaincopyprint?
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());
}
前一部分測試是建立一批空對象,不作任何其他的操作,那麼這些對象的引用計數應該是0
後面一部分測試是建立一批空對象,并将建立的每個對象随後添加到了顯示清單,那麼這批對象就同時有了引用計數,也即不對這些對象進行其他處理情況下的記憶體占用。但對Bitmap對象還是略有不同,因為并有為其new 一個bitmapData對象執行個體,是以bitmap所占記憶體這裡輸出的要比實際的低
下面來看測試輸出:
//------------------------------------------------------------------------------->
每次建立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
//-------------------------------------------------------------------------------->
可以看到輸出中的這段:
//------------------------------------------------------------->
new Sprite後總記憶體大小為:3760128
new Sprite後增加的記憶體為:-380928
//------------------------------------------------------------->
記憶體增加是負值,如果看作是之前new 出的一批對象執行個體被回收了,重新建立一批Sprite執行個體,并添加到顯示清單中,比之前僅建立Sprite而不添加到顯示清單的記憶體“new Sprite後總記憶體大小為:3665920”相比來說,還算是比較合理的。
是以這個負值也就不意外了。
另外,從這個測試函數内的源碼注釋部分,可以看到“arr.push(sprite);”這樣幾行,是當時測試new 出來的這一批對象,不添加到顯示清單,僅僅增加引用計數而進行的測試,可以與添加到顯示清單的記憶體開銷進行一下對比。
//-------------------------------------------------------------------------------->
每次建立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
//---------------------------------------------------------------------------------->
看兩段輸出,很清楚,可以對比着看,不解釋。
三、對圖檔加載和位圖常用操作的對比測試
先看測試函數,這個函數寫的還早,測試的還早,是以對輸出文字的處理跟前面兩個有點不一樣。
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;
}
對上面這段代碼裡面的for循環裡面部分,以循環1000次為例,我進行三種測試。
for (j = 0; j < num; j++)
{
tempBMP = new Bitmap(bmp.bitmapData);
this.addChild(tempBMP);
tempBMP.x = j + 300;
tempBMP.y = j;
}
上面這種測試由載入的bitmapData直接生成要使用的位圖,以友善添加到顯示清單中使用。
上面這種測試輸出是:
//------------------------------------------------------------------------->
載入圖檔前總記憶體大小為: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個位圖并添加到顯示清單中後的總記憶體大小為:4452352
生成num個位圖并添加到顯示清單中後增加的記憶體大小為:663552
花費時間:103毫秒 || 平均操作每個對象需時:0.103
//----------------------------------------------------------------------------->
再來看将for中代碼修改為new出一個空bitmap之後,對其bitmapData指派的做法,有沒有不同。
[javascript] view plaincopyprint?
for (j = 0; j < num; j++)
{
tempBMP = new Bitmap();
tempBMP.bitmapData = bmp.bitmapData;
this.addChild(tempBMP);
tempBMP.x = j + 300;
tempBMP.y = j;
}
請看輸出:
//-------------------------------------------------------------------------------->
載入圖檔前總記憶體大小為: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
//------------------------------------------------------------------------------->
我之前試了很多次,這種處理,會比上面一種生成時直接以bitmapData來生成bitmap花費的時間要長一點,記憶體也多一點,不知這次如何,我修改代碼後運作直接把輸出複制過來了,也沒細看。
送出以後看到前一次的輸出,時間好久,喜歡動手的下載下傳下面的RAR檔案自己多測試幾次吧,有時候測試效果不穩定,這很無奈。
下面來看另一種情況,new 出來bitmap後再new 出來一個bitmapData不填充值的對象,然後再利用其CopyPixels函數來處理,在看代碼和效果前,一定明白這樣相當于這個bitmap采用了一張新的位圖,而CopyPixels函數,隻是把另外一張位圖中的資料重新指向過來。看完修改的代碼和輸出後,下面再細說。
[javascript] view plaincopyprint?
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;
}
請看輸出:
//------------------------------------------------------------------------------------>
載入圖檔前總記憶體大小為: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
//------------------------------------------------------------------------------------>
看看上面輸出結果的最後兩行,是不是很讓人驚奇,好大的記憶體增加,以及好長的時間花費,CPU占用還好,我第一次測試時,num=10000,最後超過預設的15秒不響應限制,也沒有出來結果,但CPU占用一直穩定在25%(僅FP,還是在debug模式下),而且作業系統提示虛拟記憶體不足。
從最後一個測試可以看出,我們要盡量少用new BitmapData()這個函數,如果使用了這個函數,基本相當于引入了一張新位圖圖檔。
四、結論和我的猜測
結論将是由以上測試總結出的可驗證的判斷,但我的猜測就不行了,将僅僅是這些結論往前回溯性的猜測,是以可能被我蒙中了,也可能根本就是瞎猜,看到的各位,可以算做抛磚引玉,由此讨論,但不要就此擡扛。
1、通過前面對CopyPixels函數的測試,可以看到,這個函數是極節省記憶體的。與直接使用一個位圖的bitmapData資料生成一個新的bitmap基本沒有差别。而且速度也很不錯。
//--------------------------------------------------------------->
num=1000 || 目前總記憶體大小為:3788800
生成num個位圖并添加到顯示清單中後的總記憶體大小為:4452352
生成num個位圖并添加到顯示清單中後增加的記憶體大小為:663552
花費時間:103毫秒 || 平均操作每個對象需時:0.103
//--------------------------------------------------------------->
這段輸出是對循環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張,無論是矢量存儲載入後轉位圖,還是直接就是位圖。而這個位圖資源的上限公式,可以作為一個遊戲項目的主策劃用來限制随意策劃的一個測量标尺。參考資料:http://www.shengshiyouxi.com
//---------------------------------------------------------------------------------------------------------------------->
以下是我猜測性的推論,請審慎視之
1、從記憶體增量上來看,使用已載入的位圖資源資料來new 出一個新的位圖,應該僅是生成了一個位圖對象,而實際的位圖資料還是指向原始的位圖資源。
2、人為的在代碼中調用垃圾回收機制,既沒必要,也不需要,反而徒增系統資源的浪費。
3、普通對象的引用計數清除很重要,這關系到這些對象占用記憶體的回收。
4、位圖類對象的位圖資料,調用銷毀函數很有必要,在不使用某個位圖資源時,将某個位圖資源手動銷毀,垃圾回收并不起作用。
5、bitmapData相比普通的類對象,要特别一點,特别之處有二,一是該對象引用指向的對象實際資料區,需要手動銷毀才能退出占用的記憶體;另一是對該對象引用指向的實際資料,在進行資料修改,以讓其顯示的位圖有不同的顯示效果時,該修改并不是直接在實際的原始資料上進行修改的。
6、從bitmapData的特别之處,可以看到,流布于一些AS3效率優化文章内的慎用濾鏡等之類的看法,應該也是這個問題的延伸。