注意:如果可以的話,我會檢查Mike Brandt的答案,因爲他在死/活像素比率上發現了我的愚蠢錯誤。但肯得到一般好的建議。Javascript中執行時間不一致
我試圖在Canvas元素中調試Conway的生活遊戲中的一些性能問題,我遇到了一些非常奇怪的性能問題。
我得到約4-12 FPS和繪圖功能的基準測試表明,整體性能應該能夠達到60 FPS。
以下是Canvas繪圖代碼。 updateBgCanvas被RequestAnimationFrame以大約30FPS的速度調用。整個事情正在Chrome 28.0.1500.70中運行並進行全面測試。
(爲亂碼我的道歉,我一直在黑客的代碼爲較小的亞單位獲得的性能分析器更大的粒度沒有更多考慮到良好的編碼技術)
不出所料,畫布繪製功能( fillDead和fillLive是最大的CPU豬,但在這裏它變得奇怪。fillLive佔用CPU時間的5-6%(大約是我所期望的fillRect基準測試的結果),fillDead佔用了CPU的36-38%除了1或0的條件測試外,這些功能是相同的。
我試過在父函數和正在使用的顏色中調用調用順序對於填充和填充,DeadDead始終需要的時間比幾乎相同的fillLive長6-7倍。我完全不知道爲什麼會這樣。
有什麼建議嗎?
window.bgVars = {
"about": "The background is the famous Conway Game of Life",
"_Canvas": {},
"_Ctx": {},
"xBlockSize": 5,
"yBlockSize": 5,
"xBlocks": 0,
"yBlocks": 0,
"bornVals": [3],
"stayAliveVals": [2, 3],
"cGrid": [],
"cGrid2": [],
"cL": 0,
"initBgVars" : function(iCanvas, iCtx){
console.log(this.xBlockSize);
this._Canvas = iCanvas;
this._Ctx = iCtx;
this.cGrid = [];
this.cGrid2 = [];
this.xBlocks = Math.round(myCanvas.width/this.xBlockSize) + 1;
this.yBlocks = Math.round(myCanvas.height/this.yBlockSize) + 1;
for(var rep=0;rep<(this.xBlocks * this.yBlocks);rep++){
this.cGrid.push(Math.round(Math.random()*0.8));
}
this.cGrid2.length = this.cGrid.length;
},
"cirInd": function(index){
//returns modulus, array-wrapping value to implement circular array
if(index<0){index+=this.cGrid.length;}
return index%this.cGrid.length;
},
"calcNeighbors": function(rep){
var foo = this.xBlocks;
var neighbors = this.cGrid[this.cirInd(rep-foo-1)] + this.cGrid[this.cirInd(rep-foo)] + this.cGrid[this.cirInd(rep-foo+1)] + this.cGrid[this.cirInd(rep-1)] + this.cGrid[this.cirInd(rep+1)] + this.cGrid[this.cirInd(rep+foo-1)] + this.cGrid[this.cirInd(rep+foo)] + this.cGrid[this.cirInd(rep+foo+1)];
return neighbors;
},
"refreshGrid": function(){
for(var rep=0;rep<this.cGrid.length;rep++){
if(Math.random()<0.0002){this.cGrid2[rep] = 1;}
this.cGrid[rep] = this.cGrid2[rep];
}
},
"lifeRules": function(rep, neighbors){
if(this.cGrid[rep] == 1){ //stay alive rules
for(var rep2=0;rep2<this.stayAliveVals.length;rep2++){
if(neighbors==this.stayAliveVals[rep2]){this.cGrid2[rep] = 1;}
}
}
if(this.cGrid[rep] == 0){ //'born' rules
for(var rep2=0;rep2<this.bornVals.length;rep2++){
if(neighbors==this.bornVals[rep2]){this.cGrid2[rep] = 1;}
}
}
},
"fillDead": function(){
for(var rep=0;rep<this.cGrid.length;rep++){
if(this.cGrid[rep] == 0){
this._Ctx.fillRect((rep%this.xBlocks)*this.xBlockSize, Math.floor(rep/this.xBlocks)*this.yBlockSize, this.xBlockSize, this.yBlockSize);
}
}
},
"fillLive": function(){
for(var rep=0;rep<this.cGrid.length;rep++){
if(this.cGrid[rep] == 1){
this._Ctx.fillRect((rep%this.xBlocks)*this.xBlockSize, Math.floor(rep/this.xBlocks)*this.yBlockSize, this.xBlockSize, this.yBlockSize);
}
}
},
"updateBgCanvas": function(){
//fill live squares
this._Ctx.fillStyle = 'rgb(130, 0, 0)';
this.fillLive();
//fill dead squares
this._Ctx.fillStyle = 'rgb(100, 0, 0)';
this.fillDead();
//calculate next generation to buffer
for(var rep=0;rep<this.cGrid.length;rep++){
//add up the live squares in the 8 neighbor blocks
var neighbors = this.calcNeighbors(rep);
this.cGrid2[rep] = 0;
//implement GoL ruleset
this.lifeRules(rep, neighbors);
}
//seed with random noise to keep dynamic and copy to display buffer
this.refreshGrid();
}
}
編輯由Ken建議的數學函數,複製父對象瓦爾到本地變量,得到約16%PERF增益在數學函數,約4%的整體:
"cirInd": function(index, mod){
//returns modulus, array-wrapping value to implement circular array
if(index<0){index+=mod;}
return index%mod;
},
"calcNeighbors": function(rep){
var foo = this.xBlocks;
var grid = this.cGrid;
var mod = grid.length;
var neighbors = grid[this.cirInd(rep-foo-1, mod)] + grid[this.cirInd(rep-foo, mod)] + grid[this.cirInd(rep-foo+1, mod)] + grid[this.cirInd(rep-1, mod)] + grid[this.cirInd(rep+1, mod)] + grid[this.cirInd(rep+foo-1, mod)] + grid[this.cirInd(rep+foo, mod)] + grid[this.cirInd(rep+foo+1, mod)];
return neighbors;
},
你是否已經統計了在每種情況下實際執行條件代碼的次數(即cGrid是否包含明顯比0更多的0)?我認爲只有當cGrid具有大致相等的1和0的數字時,你纔會期望兩個函數的性能相同。 –
這是可能的。在分析時間窗口期間,我正在觀察死/活像素比例,它看起來非常平均,但它可能只是一種視錯覺。我會做一個快速檢查.. – DanHeidel
是的,我的眼睛很髒,髒兮兮的騙子。死像素比例僅爲4:1,但似乎可能是原因。謝謝! – DanHeidel