真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

如何才能讓HTML5性能發(fā)揮到極致

這篇文章將為大家詳細講解有關(guān)如何才能讓HTML5性能發(fā)揮到極致,小編覺得挺實用的,因此分享給大家做個參考,希望大家閱讀完這篇文章后可以有所收獲。

創(chuàng)新互聯(lián)公司堅持“要么做到,要么別承諾”的工作理念,服務(wù)領(lǐng)域包括:成都網(wǎng)站建設(shè)、網(wǎng)站設(shè)計、企業(yè)官網(wǎng)、英文網(wǎng)站、手機端網(wǎng)站、網(wǎng)站推廣等服務(wù),滿足客戶于互聯(lián)網(wǎng)時代的達日網(wǎng)站設(shè)計、移動媒體設(shè)計的需求,幫助企業(yè)找到有效的互聯(lián)網(wǎng)解決方案。努力成為您成熟可靠的網(wǎng)絡(luò)建設(shè)合作伙伴!

HTML5作為新興領(lǐng)域越來越熱。然而在移動設(shè)備硬件性能弱于PC的背景下,對性能的需求顯得更為重要,而HTML5性能優(yōu)化前與優(yōu)化后有著極大的差別,如何優(yōu)化才能提高性能,對此熟知的人很少。本文以LayaAir引擎為例,通過代碼示例詳細闡述如何利用引擎對HTML5作出性能的極致優(yōu)化。

 主題包括:

  •  代碼執(zhí)行基本原理

  •  基準測試

  •  內(nèi)存優(yōu)化

  •  圖形渲染性能

  •  減少CPU使用量

  •  其他優(yōu)化策略


 第1節(jié):代碼執(zhí)行基本原理

LayaAir引擎支持AS3、TypeScript、JavaScript三種語言開發(fā),然而無論是采用哪種開發(fā)語言,最終執(zhí)行的都是JavaScript代碼。所有看到的畫面都是通過引擎繪制出來的,更新頻率取決于開發(fā)者指定的FPS,例如指定幀頻率為60FPS,則運行時每個幀的執(zhí)行時間為六十分之一秒,所以幀速越高,視覺上感覺越流暢,60幀是滿幀。

由于實際運行環(huán)境是在瀏覽器中,因此性能還取決于JavaScript解釋器的效率,指定的FPS幀速在低性能解釋器中可能不會達到,所以這部分不是開發(fā)者能夠決定的,開發(fā)者能作的是盡可能通過優(yōu)化,在低端設(shè)備或低性能瀏覽器中,提升FPS幀速。

LayaAir引擎在每幀都會重繪,在性能優(yōu)化時,除了關(guān)注每幀執(zhí)行邏輯代碼帶來的CPU消耗,還需要注意每幀調(diào)用繪圖指令的數(shù)量以及GPU的紋理提交次數(shù)。

 第2節(jié):基準測試

LayaAir引擎內(nèi)置的性能統(tǒng)計工具可用于基準測試,實時檢測當前性能。開發(fā)者可以使用laya.utils.Stat類,通過Stat.show() 顯示統(tǒng)計面板。具體編寫代碼如下例所示:

Stat.show(0,0); //AS3的面板調(diào)用寫法       Laya.Stat.show(0,0); //TS與JS的面板調(diào)用寫法

 Canvas渲染的統(tǒng)計信息:

如何才能讓HTML5性能發(fā)揮到極致

WebGL渲染的統(tǒng)計信息:

如何才能讓HTML5性能發(fā)揮到極致

統(tǒng)計參數(shù)的意義:

FPS:

每秒呈現(xiàn)的幀數(shù)(數(shù)字越高越好)。

使用canvas渲染時,描述字段顯示為FPS(Canvas),使用WebGL渲染時,描述字段顯示為FPS(WebGL)。

Sprite:

渲染節(jié)點數(shù)量(數(shù)字越低越好)。

Sprite統(tǒng)計所有渲染節(jié)點(包括容器),這個數(shù)字的大小會影響引擎節(jié)點遍歷,數(shù)據(jù)組織和渲染的次數(shù)。

DrawCall:

DrawCall在canvas和WebGL渲染下代表不同的意義(越少越好)。

Canvas下表示每幀的繪制次數(shù),包括圖片、文字、矢量圖。盡量限制在100之下。

WebGL下表示渲染提交批次,每次準備數(shù)據(jù)并通知GPU渲染繪制的過程稱為1次DrawCall,在每1次DrawCall中除了在通知GPU的渲染上比較耗時之外,切換材質(zhì)與shader也是非常耗時的操作。 DrawCall的次數(shù)是決定性能的重要指標,盡量限制在100之下。

Canvas:

三個數(shù)值 —— 每幀重繪的畫布數(shù)量 / 緩存類型為“normal”類型的畫布數(shù)量 / 緩存類型為“bitmap”類型的畫布數(shù)量”。

CurMem:僅限WebGL渲染,表示內(nèi)存與顯存占用(越低越好)。

Shader:僅限WebGL渲染,表示每幀Shader提交次數(shù)。

無論是Canvas模式還是WebGL模式,我們都需要重點關(guān)注DrawCall,Sprite,Canvas這三個參數(shù),然后針對性地進行優(yōu)化。(參見“圖形渲染性能”)

  第3節(jié):內(nèi)存優(yōu)化

對象池

對象池,涉及到不斷重復(fù)使用對象。在初始化應(yīng)用程序期間創(chuàng)建一定數(shù)量的對象并將其存儲在一個池中。對一個對象完成操作后,將該對象放回到池中,在需要新對象時可以對其進行檢索。

由于實例化對象成本很高,使用對象池重用對象可減少實例化對象的需求。還可以減少垃圾**器運行的機會,從而提高程序的運行速度。

以下代碼演示使用

Laya.utils.Pool:

ar SPRITE_SIGN = 'spriteSign';var sprites = [];function initialize(){	for (var i = 0; i < 1000; i++)
	{		var sp = Pool.getItemByClass(SPRITE_SIGN, Sprite)
		sprites.push(sp);
		Laya.stage.addChild(sp);
	}
}
initialize();

 在initialize中創(chuàng)建大小為1000的對象池。

以下代碼在當單擊鼠標時,將刪除顯示列表中的所有顯示對象,并在以后的其他任務(wù)中重復(fù)使用這些對象:

Laya.stage.on("click", this, function(){	var sp;	for(var i = 0, len = sprites.length; i < len; i++)
	{
		sp = sprites.pop();
		Pool.recover(SPRITE_SIGN, sp);
		Laya.stage.removeChild(sp);
	}
});

 調(diào)用Pool.recover后,指定的對象會被**至池內(nèi)。

  使用Handler.create

在開發(fā)過程中,會經(jīng)常使用Handler來完成異步回調(diào)。Handler.create使用了內(nèi)置對象池管理,因此在使用Handler對象時應(yīng)使用Handler.create來創(chuàng)建回調(diào)處理器。以下代碼使用Handler.create創(chuàng)建加載的回調(diào)處理器:

Laya.loader.load(urls, Handler.create(this, onAssetLoaded));

 在上面的代碼中,回調(diào)被執(zhí)行后Handler將會被對象池收回。此時,考慮如下代碼會發(fā)生什么事:

Laya.loader.load(urls, Handler.create(this, onAssetLoaded), Handler.create(this, onLoading));

在上面的代碼中,使用Handler.create返回的處理器處理progress事件。此時的回調(diào)執(zhí)行一次之后就被對象池**,于是progress事件只觸發(fā)了一次,此時需要將四個名為once的參數(shù)設(shè)置為false:

Laya.loader.load(urls, Handler.create(this, onAssetLoaded), Handler.create(this, onLoading, null, false));

 釋放內(nèi)存

JavaScript運行時無法啟動垃圾**器。要確保一個對象能夠被**,請刪除對該對象的所有引用。Sprite提供的destory會幫助設(shè)置內(nèi)部引用為null。

例如,以下代碼確保對象能夠被作為垃圾**:

var sp = new Sprite();
sp.destroy();

 當對象設(shè)置為null,不會立即將其從內(nèi)存中刪除。只有系統(tǒng)認為內(nèi)存足夠低時,垃圾**器才會運行。內(nèi)存分配(而不是對象刪除)會觸發(fā)垃圾**。

垃圾**期間可能占用大量CPU并影響性能。通過重用對象,嘗試限制使用垃圾**。此外,盡可能將引用設(shè)置為null,以便垃圾**器用較少時間來查找對象。有時(比如兩個對象相互引用),無法同時設(shè)置兩個引用為null,垃圾**器將掃描無法被訪問到的對象,并將其清除,這會比引用計數(shù)更消耗性能。

資源卸載

游戲運行時總會加載許多資源,這些資源在使用完成后應(yīng)及時卸載,否則一直殘留在內(nèi)存中。

下例演示加載資源后對比資源卸載前和卸載后的資源狀態(tài):

var assets = [];
assets.push("res/apes/monkey0.png");
assets.push("res/apes/monkey1.png");
assets.push("res/apes/monkey2.png");
assets.push("res/apes/monkey3.png");

Laya.loader.load(assets, Handler.create(this, onAssetsLoaded));function onAssetsLoaded(){	for(var i = 0, len = assets.length; i < len; ++i)
	{		var asset = assets[i];		console.log(Laya.loader.getRes(asset));
		Laya.loader.clearRes(asset);		console.log(Laya.loader.getRes(asset));
	}
}

  關(guān)于濾鏡、遮罩

嘗試盡量減少使用濾鏡效果。將濾鏡(BlurFilter和GlowFilter)應(yīng)用于顯示對象時,運行時將在內(nèi)存中創(chuàng)建兩張位圖。其中每個位圖的大小與顯示對象相同。將第一個位圖創(chuàng)建為顯示對象的柵格化版本,然后用于生成應(yīng)用濾鏡的另一個位圖:

如何才能讓HTML5性能發(fā)揮到極致

應(yīng)用濾鏡時內(nèi)存中的兩個位圖

當修改濾鏡的某個屬性或者顯示對象時,內(nèi)存中的兩個位圖都將更新以創(chuàng)建生成的位圖,這兩個位圖可能會占用大量內(nèi)存。此外,此過程涉及CPU計算,動態(tài)更新時將會降低性能(參見“圖形渲染性能 – 關(guān)于cacheAs)。

ColorFiter在Canvas渲染下需要計算每個像素點,而在WebGL下的GPU消耗可以忽略不計。

最佳的做法是,盡可能使用圖像創(chuàng)作工具創(chuàng)建的位圖來模擬濾鏡。避免在運行時中創(chuàng)建動態(tài)位圖,可以幫助減少CPU或GPU負載。特別是一張應(yīng)用了濾鏡并且不會在修改的圖像。

 第4節(jié):圖形渲染性能

  優(yōu)化Sprite

1.盡量減少不必要的層次嵌套,減少Sprite數(shù)量。

2.非可見區(qū)域的對象盡量從顯示列表移除或者設(shè)置visible=false。

3.對于容器內(nèi)有大量靜態(tài)內(nèi)容或者不經(jīng)常變化的內(nèi)容(比如按鈕),可以對整個容器設(shè)置cacheAs屬性,能大量減少Sprite的數(shù)量,顯著提高性能。如果有動態(tài)內(nèi)容,最好和靜態(tài)內(nèi)容分開,以便只緩存靜態(tài)內(nèi)容。

4.Panel內(nèi),會針對panel區(qū)域外的直接子對象(子對象的子對象判斷不了)進行不渲染處理,超出panel區(qū)域的子對象是不產(chǎn)生消耗的。

  優(yōu)化DrawCall

1.對復(fù)雜靜態(tài)內(nèi)容設(shè)置cacheAs,能大量減少DrawCall,使用好cacheAs是游戲優(yōu)化的關(guān)鍵。

2.盡量保證同圖集的圖片渲染順序是挨著的,如果不同圖集交叉渲染,會增加DrawCall數(shù)量。

3.盡量保證同一個面板中的所有資源用一個圖集,這樣能減少提交批次。

  優(yōu)化Canvas

在對Canvas優(yōu)化時,我們需要注意,在以下場合不要使用cacheAs:

1.對象非常簡單,比如一個字或者一個圖片,設(shè)置cacheAs=bitmap不但不提高性能,反而會損失性能。

2.容器內(nèi)有經(jīng)常變化的內(nèi)容,比如容器內(nèi)有一個動畫或者倒計時,如果再對這個容器設(shè)置cacheAs=bitmap,會損失性能。

可以通過查看Canvas統(tǒng)計信息的第一個值,判斷是否一直在刷新Canvas緩存。

  關(guān)于cacheAs

設(shè)置cacheAs可將顯示對象緩存為靜態(tài)圖像,當cacheAs時,子對象發(fā)生變化,會自動重新緩存,同時也可以手動調(diào)用reCache方法更新緩存。 建議把不經(jīng)常變化的復(fù)雜內(nèi)容,緩存為靜態(tài)圖像,能極大提高渲染性能,cacheAs有”none”,”normal”和”bitmap”三個值可選。

1.默認為”none”,不做任何緩存。

2.當值為”normal”時,canvas下進行畫布緩存,webgl模式下進行命令緩存。

3.當值為”bitmap”時,canvas下進行依然是畫布緩存,webGL模式下使用renderTarget緩存。這里需要注意的是,webGL下renderTarget緩存模式有2048大小限制,超出2048會額外增加內(nèi)存開銷。另外,不斷重繪時開銷也比較大,但是會減少drawcall,渲染性能最高。 webGL下命令緩存模式只會減少節(jié)點遍歷及命令組織,不會減少drawcall,性能中等。

設(shè)置cacheAs后,還可以設(shè)置staticCache=true以阻止自動更新緩存,同時可以手動調(diào)用reCache方法更新緩存。

cacheAs主要通過兩方面提升性能。一是減少節(jié)點遍歷和頂點計算;二是減少drawCall。善用cacheAs將是引擎優(yōu)化性能的利器。

下例繪制10000個文本:

Laya.init(550, 400, Laya.WebGL);
Laya.Stat.show();var textBox = new Laya.Sprite();var text;for (var i = 0; i < 10000; i++)
{
    text = new Laya.Text();
    text.text = (Math.random() * 100).toFixed(0);
    text.color = "#CCCCCC";

    text.x = Math.random() * 550;
    text.y = Math.random() * 400;

    textBox.addChild(text);
}

Laya.stage.addChild(textBox);

 下面是筆者電腦上的運行時截圖,F(xiàn)PS穩(wěn)定于52上下。


如何才能讓HTML5性能發(fā)揮到極致

當我們對文字所在的容器設(shè)置為cacheAs之后,如下面的例子所示,性能獲得較大的提升,F(xiàn)PS達到到了60幀。

// …省略其他代碼… var textBox = new Laya.Sprite();textBox.cacheAs = "bitmap"; // …省略其他代碼…

如何才能讓HTML5性能發(fā)揮到極致

  文字描邊

在運行時,設(shè)置了描邊的文本比沒有描邊的文本多調(diào)用一次繪圖指令。此時,文本對CPU的使用量和文本的數(shù)量成正比。因此,盡量使用替代方案來完成同樣的需求。

對于幾乎不變動的文本內(nèi)容,可以使用cacheAs降低性能消耗,參見“圖形渲染性能 – 關(guān)于cacheAs”。

對于內(nèi)容經(jīng)常變動,但是使用的字符數(shù)量較少的文本域,可以選擇使用位圖字體。

  跳過文本排版,直接渲染

大多數(shù)情況下,很多文本都不需要復(fù)雜的排版,僅僅簡單地顯示一行字。為了迎合這一需求,Text提供的名為changeText的方法可以直接跳過排版。

var text = new Text();
text.text = "text";
Laya.stage.addChild(text);//后面只是更新文字內(nèi)容,使用changeText能提高性能text.changeText("text changed.");

 Text.changeText會直接修改繪圖指令中該文本繪制的最后一條指令,這種前面的繪圖指令依舊存在的行為會導(dǎo)致changeText只使用于以下情況:

文本始終只有一行。

文本的樣式始終不變(顏色、粗細、斜體、對齊等等)。

即使如此,實際編程中依舊會經(jīng)常使用到這樣的需要。

 第5節(jié):減少CPU使用量

  減少動態(tài)屬性查找

JavaScript中任何對象都是動態(tài)的,你可以任意地添加屬性。然而,在大量的屬性里查找某屬性可能很耗時。如果需要頻繁使用某個屬性值,可以使用局部變量來保存它:

function foo(){
    var prop = target.prop;
    // 使用prop    process1(prop);
    process2(prop);
    process3(prop);
}

 計時器

LayaAir提供兩種計時器循環(huán)來執(zhí)行代碼塊。

    1.  Laya.timer.frameLoop執(zhí)行頻率依賴于幀頻率,可通過Stat.FPS查看當前幀頻。

    2.  Laya.timer.loop執(zhí)行頻率依賴于參數(shù)指定時間。

    當一個對象的生命周期結(jié)束時,記得清除其內(nèi)部的Timer:

    Laya.timer.frameLoop(1, this, animateFrameRateBased);
    Laya.stage.on("click", this, dispose);function dispose() {
        Laya.timer.clear(this, animateFrameRateBased);
    }

      獲取顯示對象邊界的做法

    在相對布局中,很經(jīng)常需要正確地獲取顯示對象的邊界。獲取顯示對象的邊界也有多種做法,而其間差異很有必要知道。

    1.使用getBounds/ getGraphicBounds。

    var sp = new Sprite();
    sp.graphics.drawRect(0, 0, 100, 100, "#FF0000");var bounds = sp.getGraphicBounds();
    Laya.stage.addChild(sp);

     getBounds可以滿足多數(shù)多數(shù)需求,但由于其需要計算邊界,不適合頻繁調(diào)用。

    2.設(shè)置容器的autoSize為true。

    var sp = new Sprite();
    sp.autoSize = true;
    sp.graphics.drawRect(0, 0, 100, 100, "#FF0000");
    Laya.stage.addChild(sp);

     上述代碼可以在運行時正確獲取寬高。autoSize在獲取寬高并且顯示列表的狀態(tài)發(fā)生改變時會重新計算(autoSize通過getBouDNS計算寬高)。所以對擁有大量子對象的容器應(yīng)用autoSize是不可取的。如果設(shè)置了size,autoSize將不起效。

    使用loadImage后獲取寬高:

    var sp = new Sprite();
    sp.loadImage("res/apes/monkey2.png", 0, 0, 0, 0, Handler.create(this, function(){	console.log(sp.width, sp.height);
    }));
    Laya.stage.addChild(sp);

    loadImage在加載完成的回調(diào)函數(shù)觸發(fā)之后才可以正確獲取寬高。

    3.直接調(diào)用size設(shè)置:

    Laya.loader.load("res/apes/monkey2.png", Handler.create(this, function(){	var texture = Laya.loader.getRes("res/apes/monkey2.png");	var sp = new Sprite();
    	sp.graphics.drawTexture(texture, 0, 0);
    	sp.size(texture.width, texture.height);
    	Laya.stage.addChild(sp);
    }));

     使用Graphics.drawTexture并不會自動設(shè)置容器的寬高,但是可以使用Texture的寬高賦予容器。毋庸置疑,這是最高效的方式。

    注:getGraphicsBounds用于獲取矢量繪圖寬高。

      根據(jù)活動狀態(tài)改變幀頻

    幀頻有三種模式,Stage.FRAME_SLOW維持FPS在30;Stage.FRAME_FAST維持FPS在60;Stage.FRAME_MOUSE則選擇性維持FPS在30或60幀。

    有時并不需要讓游戲以60FPS的速率執(zhí)行,因為30FPS已經(jīng)能夠滿足多數(shù)情況下人類視覺的響應(yīng),但是鼠標交互時,30FPS可能會造成畫面的不連貫,于是Stage.FRAME_MOUSE應(yīng)運而生。

    下例展示以Stage.FRAME_SLOW的幀率,在畫布上移動鼠標,使圓球跟隨鼠標移動:

    Laya.init(Browser.width, Browser.height);
    Stat.show();
    Laya.stage.frameRate = Stage.FRAME_SLOW;var sp = new Sprite();
    sp.graphics.drawCircle(0, 0, 20, "#990000");
    Laya.stage.addChild(sp);
    
    Laya.stage.on(Event.MOUSE_MOVE, this, function(){
    	sp.pos(Laya.stage.mouseX, Laya.stage.mouseY);
    });

    如何才能讓HTML5性能發(fā)揮到極致

    此時FPS顯示30,并且在鼠標移動時,可以感覺到圓球位置的更新不連貫。設(shè)置Stage.frameRate為Stage.FRAME_MOUSE:

    Laya.stage.frameRate = Stage.FRAME_MOUSE;

    如何才能讓HTML5性能發(fā)揮到極致

    此時在鼠標移動后FPS會顯示60,并且畫面流暢度提升。在鼠標靜止2秒不動后,F(xiàn)PS又會恢復(fù)到30幀。

      使用callLater

    callLater使代碼塊延遲至本幀渲染前執(zhí)行。如果當前的操作頻繁改變某對象的狀態(tài),此時可以考慮使用callLater,以減少重復(fù)計算。

    考慮一個圖形,對它設(shè)置任何改變外觀的屬性都將導(dǎo)致圖形重繪:

    var rotation = 0,
    	scale = 1,
    	position = 0;function setRotation(value){	this.rotation = value;
    	update();
    }function setScale(value){	this.scale = value;
    	update();
    }function setPosition(value){	this.position = value;
    	update();
    }function update(){	console.log('rotation: ' + this.rotation + '\tscale: ' + this.scale + '\tposition: ' + position);
    }

     調(diào)用以下代碼更改狀態(tài):

    setRotation(90); setScale(2); setPosition(30);

    setRotation(90); setScale(2); setPosition(30);

    控制臺的打印結(jié)果是

    rotation: 90 scale: 1 position: 0

    rotation: 90 scale: 2 position: 0

    rotation: 90 scale: 2 position: 30

    update被調(diào)用了三次,并且最后的結(jié)果是正確的,但是前面兩次調(diào)用都是不需要的。

    嘗試將三處update改為:

    Laya.timer.callLater(this, update);

     此時,update只會調(diào)用一次,并且是我們想要的結(jié)果。

      圖片/圖集加載

    在完成圖片/圖集的加載之后,引擎就會開始處理圖片資源。如果加載的是一張圖集,會處理每張子圖片。如果一次性處理大量的圖片,這個過程可能會造成長時間的卡頓。

    在游戲的資源加載中,可以將資源按照關(guān)卡、場景等分類加載。在同一時間處理的圖片越少,當時的游戲響應(yīng)速度也會更快。在資源使用完成后,也可以予以卸載,釋放內(nèi)存。

     第6節(jié):其他優(yōu)化策略

    1.減少粒子使用數(shù)量,在移動平臺Canvas模式下,盡量不用粒子;

    2.在Canvas模式下,盡量減少旋轉(zhuǎn),縮放,alpha等屬性的使用,這些屬性會對性能產(chǎn)生消耗。(在WebGL模式可以使用);

    3.不要在timeloop里面創(chuàng)建對象及復(fù)雜計算;

    4.盡量減少對容器的autoSize的使用,減少getBounds()的使用,因為這些調(diào)用會產(chǎn)生較多計算;

    5.盡量少用try catch的使用,被try catch的函數(shù)執(zhí)行會變得非常慢;

    關(guān)于如何才能讓HTML5性能發(fā)揮到極致就分享到這里了,希望以上內(nèi)容可以對大家有一定的幫助,可以學(xué)到更多知識。如果覺得文章不錯,可以把它分享出去讓更多的人看到。


    文章題目:如何才能讓HTML5性能發(fā)揮到極致
    文章地址:http://weahome.cn/article/gcogho.html

    其他資訊

    在線咨詢

    微信咨詢

    電話咨詢

    028-86922220(工作日)

    18980820575(7×24)

    提交需求

    返回頂部