讓人頭疼的婚戀交友原始碼效能優化,該如何解決?

雲豹科技程式設計師發表於2021-12-09
無論開發什麼軟體效能優化都是老生常談的話題,所以婚戀交友原始碼的開發自然也不能避免。實現效能優化的手段有很多種,今天我們只列舉其中的一部分進行分析,希望能給大家提供一些思路。

一、減少重繪重排

婚戀交友原始碼瀏覽器渲染過程
1、解析HTML生成DOM樹。 2、解析CSS生成CSSOM規則樹。 3、解析JS,操作 DOM 樹和 CSSOM 規則樹。 4、將DOM樹與CSSOM規則樹合併在一起生成渲染樹。 5、遍歷渲染樹開始佈局,計算每個節點的位置大小資訊。 6、瀏覽器將所有圖層的資料傳送給GPU,GPU將圖層合成並顯示在螢幕上。
讓人頭疼的婚戀交友原始碼效能優化,該如何解決?

重排
當改變 DOM 元素位置或大小時,會導致婚戀交友原始碼瀏覽器重新生成渲染樹,這個過程叫重排。
重繪
當重新生成渲染樹後,就要將渲染樹每個節點繪製到螢幕,這個過程叫重繪。不是婚戀交友原始碼所有的動作都會導致重排,例如改變字型顏色,只會導致重繪。記住,重排會導致重繪,重繪不會導致重排 。 重排和重繪這兩個操作都是非常昂貴的,因為 JavaScript 引擎執行緒與 GUI 渲染執行緒是互斥,它們同時只能一個在工作。
什麼操作會導致重排?
1、新增或刪除可見的 DOM 元素 2、元素位置改變 3、元素尺寸改變 4、內容改變 5、瀏覽器視窗尺寸改變
如何減少重排重繪?
1、用 JavaScript 修改婚戀交友原始碼樣式時,最好不要直接寫樣式,而是替換 class 來改變樣式。 2、如果要對 DOM 元素執行一系列操作,可以將 DOM 元素脫離文件流,修改完成後,再將它帶回文件。推薦使用隱藏元素(display:none)或文件碎片(DocumentFragement),都能很好的實現這個方案。

二、使用事件委託

事件委託利用了事件冒泡,只指定一個事件處理程式,就可以管理某一型別的所有事件。所有用到按鈕的事件(多數滑鼠事件和鍵盤事件)都適合採用事件委託技術, 使用事件委託可以節省婚戀交友原始碼記憶體。
<ul>
  <li>蘋果</li>
  <li>香蕉</li>
  <li>鳳梨</li>
</ul>
// good
document.querySelector('ul').onclick = (event) => {
  const target = event.target
  if (target.nodeName === 'LI') {
    console.log(target.innerHTML)
  }
}
// bad
document.querySelectorAll('li').forEach((e) => {
  e.onclick = function() {
    console.log(this.innerHTML)
  }
})

三、注意程式的區域性性

一個編寫良好的婚戀交友原始碼常常具有良好的區域性性,它們傾向於引用最近引用過的資料項附近的資料項,或者最近引用過的資料項本身,這種傾向性,被稱為區域性性原理。有良好區域性性的程式比區域性性差的程式執行得更快。
區域性性通常有兩種不同的形式:
1、時間區域性性:在一個具有良好時間區域性性的婚戀交友原始碼中,被引用過一次的記憶體位置很可能在不遠的將來被多次引用。 2、空間區域性性 :在一個具有良好空間區域性性的婚戀交友原始碼中,如果一個記憶體位置被引用了一次,那麼程式很可能在不遠的將來引用附近的一個記憶體位置。
時間區域性性示例
function sum(arry) {
	let i, sum = 0
	let len = arry.length
	for (i = 0; i < len; i++) {
		sum += arry[i]
	}
	return sum
}
在這個例子中,變數sum在每次迴圈迭代中被引用一次,因此,對於sum來說,具有良好的時間區域性性
空間區域性性示例
具有良好空間區域性性的程式
// 二維陣列 
function sum1(arry, rows, cols) {
	let i, j, sum = 0
	for (i = 0; i < rows; i++) {
		for (j = 0; j < cols; j++) {
			sum += arry[i][j]
		}
	}
	return sum
}
空間區域性性差的程式
// 二維陣列 
function sum2(arry, rows, cols) {
	let i, j, sum = 0
	for (j = 0; j < cols; j++) {
		for (i = 0; i < rows; i++) {
			sum += arry[i][j]
		}
	}
	return sum
}
看一下上面的兩個空間區域性性示例,像示例中從每行開始按順序訪問陣列每個元素的方式,稱為具有步長為1的引用模式。 如果在陣列中,每隔k個元素進行訪問,就稱為步長為k的引用模式。 一般而言,隨著步長的增加,空間區域性性下降。 這兩個例子有什麼區別?區別在於第一個示例是按行掃描陣列,每掃描完一行再去掃下一行;第二個示例是按列來掃描陣列,掃完一行中的一個元素,馬上就去掃下一行中的同一列元素。 陣列在婚戀交友原始碼記憶體中是按照行順序來存放的,結果就是逐行掃描陣列的示例得到了步長為 1 引用模式,具有良好的空間區域性性;而另一個示例步長為 rows,空間區域性性極差。
效能測試
執行環境:
  • cpu: i5-7400
  • 瀏覽器: chrome 70.0.3538.110
對一個長度為9000的二維陣列(子陣列長度也為9000)進行10次空間區域性性測試,時間(毫秒)取平均值,結果如下: 所用示例為上述兩個空間區域性性示例
讓人頭疼的婚戀交友原始碼效能優化,該如何解決?
從以上測試結果來看,步長為 1 的陣列執行時間比步長為 9000 的陣列快了一個數量級。
總結:
1、重複引用相同變數的婚戀交友原始碼具有良好的時間區域性性 2、對於具有步長為 k 的引用模式的程式,步長越小,空間區域性性越好;而在記憶體中以大步長跳來跳去的婚戀交友原始碼空間區域性性會很差

四、 if-else 對比 switch

當判斷條件數量越來越多時,越傾向於使用 switch 而不是 if-else。
if (color == 'blue') {
} else if (color == 'yellow') {
} else if (color == 'white') {
} else if (color == 'black') {
} else if (color == 'green') {
} else if (color == 'orange') {
} else if (color == 'pink') {
}
switch (color) {
    case 'blue':
        break
    case 'yellow':
        break
    case 'white':
        break
    case 'black':
        break
    case 'green':
        break
    case 'orange':
        break
    case 'pink':
        break
}
像上面的這種情況,從可讀性來說,使用 switch 是比較好的(js 的 switch 語句不是基於雜湊實現,而是迴圈判斷,所以說 if-else、switch 從效能上來說是一樣的)。

五、查詢表

當婚戀交友原始碼條件語句特別多時,使用 switch 和 if-else 不是最佳的選擇,這時不妨試一下查詢表。查詢表可以使用陣列和物件來構建。
switch (index) {
    case '0':
        return result0
    case '1':
        return result1
    case '2':
        return result2
    case '3':
        return result3
    case '4':
        return result4
    case '5':
        return result5
    case '6':
        return result6
    case '7':
        return result7
    case '8':
        return result8
    case '9':
        return result9
    case '10':
        return result10
    case '11':
        return result11
}
可以將這個 switch 語句轉換為查詢表
const results = [result0,result1,result2,result3,result4,result5,result6,result7,result8,result9,result10,result11]
return results[index]
如果條件語句不是數值而是字串,可以用物件來建立查詢表
const map = {
  red: result0,
  green: result1,
}
return map[color]

六、避免頁面卡頓

60fps 與裝置重新整理率
目前大多數裝置的螢幕重新整理率為 60次/秒。因此,如果在頁面中有一個動畫或漸變效果,或者使用者正在滾動頁面,那麼瀏覽器渲染動畫或頁面的每一幀的速率也需要跟裝置螢幕的重新整理率保持一致。
其中每個幀的預算時間僅比 16 毫秒多一點 (1 秒/ 60 = 16.66 毫秒)。但實際上,瀏覽器有整理工作要做,因此婚戀交友原始碼的所有工作需要在 10 毫秒內完成。如果無法符合此預算,幀率將下降,並且內容會在螢幕上抖動。 此現象通常稱為卡頓,會對使用者體驗產生負面影響。
讓人頭疼的婚戀交友原始碼效能優化,該如何解決?

假如你用 JavaScript 修改了 DOM,並觸發樣式修改,經歷重排重繪最後畫到螢幕上。如果這其中任意一項的執行時間過長,都會導致渲染這一幀的時間過長,平均幀率就會下降。假設這一幀花了 50 ms,那麼此時的幀率為 1s / 50ms = 20fps,頁面看起來就像卡頓了一樣。
對於一些長時間執行的 JavaScript,我們可以使用定時器進行切分,延遲執行。
for (let i = 0, len = arry.length; i < len; i++) {
	process(arry[i])
}
假設上面的迴圈結構由於 process() 複雜度過高或陣列元素太多,甚至兩者都有,可以嘗試一下切分。
const todo = arry.concat()setTimeout(function() {
	process(todo.shift())
	if (todo.length) {
		setTimeout(arguments.callee, 25)
	} else {
		callback(arry)
	}}, 25)
本文轉載自網路,轉載僅為分享乾貨知識,如有侵權歡迎聯絡雲豹科技進行刪除處理 原文連結:


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/69996194/viewspace-2846757/,如需轉載,請註明出處,否則將追究法律責任。

相關文章