成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

你的函數有多快?使用 Performance 監控前端性能

安全 應用安全
良好的性能更容易好的用戶體驗,而好的用戶體驗更能留住用戶。研究表明,由于性能問題,在88%的在線消費者對用戶體驗不滿意后,他們不太可能會二次使用。

 [[334541]]

要比較兩個函數哪個性能更好,一個直觀且公平的方法就是計算兩個函數分別執行完的時間。

良好的性能更容易好的用戶體驗,而好的用戶體驗更能留住用戶。研究表明,由于性能問題,在88%的在線消費者對用戶體驗不滿意后,他們不太可能會二次使用。

這也是為什么要提高性能的一個重要原因。特別是使用 JS 開發時,編寫的每一行 JS 都可能會阻塞DOM,因為它是單線程語言。

本次分享,我們主要介紹如何計算函數的性能。

Performance.now

Performance是一個做前端性能監控離不開的API,最好在頁面完全加載完成之后再使用,因為很多值必須在頁面完全加載之后才能得到。最簡單的辦法是在window.onload事件中讀取各種數據。

performance.now()方法返回一個精確到毫秒的 DOMHighResTimeStamp 。

根據 MDN :

這個時間戳實際上并不是高精度的。為了降低像Spectre這樣的安全威脅,各類瀏覽器對該類型的值做了不同程度上的四舍五入處理。(Firefox從Firefox 59開始四舍五入到2毫秒精度)一些瀏覽器還可能對這個值作稍微的隨機化處理。這個值的精度在未來的版本中可能會再次改善;瀏覽器開發者還在調查這些時間測定攻擊和如何更好的緩解這些攻擊。

因為,要計算一個函數的執行時間,分別比較函數執行前和執行后的兩次 performance.now()的值即可,如下所示:

  1. const t0 = performance.now(); 
  2. for (let i = 0; i < array.length; i++)  
  3.   // some code 
  4. const t1 = performance.now(); 
  5. console.log(t1 - t0, 'milliseconds'); 

 

在這里,我們可以看到 Firefox 中的結果與 Chrome 完全不同。這是因為從版本60開始,Firefox 將performance API的精度降低到2ms。

performance API 不當當只有返回時間戳這個功能,還有很多實用方法,大家可以根據需要到 MDN 查詢相關的文檔。

然而,對于我們的用例,我們只想計算單個函數的性能,因此時間戳就足夠了。

performance.now() 和 Date.now一樣嗎?

你可能會想,嘿,我也可以使用Date.now來做?

是的,你可以,但這有缺點。

Date.now返回自Unix紀元(1970-01-01T00:00:00Z)以來經過的時間(以毫秒為單位),并取決于系統時鐘。這不僅意味著它不夠精確,而且還不總是遞增。WebKit工程師(Tony Gentilcore)的解釋如下:

基于系統時間的日期可能不太會被采用,對于實際的用戶監視也不是理想的選擇。大多數系統運行一個守護程序,該守護程序定期同步時間。通常每15至20分鐘將時鐘調整幾毫秒。以該速率,大約10秒間隔的1%將是不準確的。

Performance.mark 和 Performance.measure

除了Performance.now函數外,還有一些函數可以讓我們度量代碼不同部分的時間,并將它們作為性能測試工具(如Webpagetest)中的自定義度量。

Performance.mark

先來看看MDN中關于mark方法的定義:

  • The mark() method creates a timestamp in the browser's performance entry buffer with the given name.

這段話可以分解出三個關鍵詞。首先timestamp,這里的timestamp指的是高精度時間戳(千分之一毫秒),其次是performance entry buffer。

performance entry buffer指的是存儲performance實例對象的區域,初始值為空。

最后就是given name,表示生成的每一個timestamp都有相應的名稱。

所以這句話就可以理解成,在瀏覽器的performance entry buffer中,根據名稱生成高精度時間戳。也就是很多人說過的**“打點”**。

就像Performance.now一樣,此函數的精度分數高達5µs。

  1. performance.mark('name'); 

標記 的 performance entry將具有以下屬性值:

  • entryType - 設置為 "mark".
  • name - 設置為mark被創建時給出的 "name"
  • startTime - 設置為 mark() 方法被調用時的 timestamp 。
  • duration - 設置為 "0" (標記沒有持續時間).

Performance.measure

同樣先來看看 MDN 上關于 measure 的定義:

這段定義和上面 mark 的定義有些類似,其最核心的不同點在于這句話 between two specified marks。所以measure是指定兩個mark點之間的時間戳。如果說mark可以理解為**"打點"的話,measure就可以理解為"連線"**。

  1. performance.measure(name, startMark, endMark); 

計算兩個mark之間的時長,創建一個DOMHighResTimeStamp保存在資源緩存數據中,可通過performance.getEntries()等相關接口獲取。

  • entryType 為字符串 measure
  • name 為創建時設置的值
  • startTime為調用 measure 時的時間
  • duration為兩個 mark 之間的時長

從導航開始測量

  1. performance.measure('measure name'); 

導航開始到標記

  1. performance.measure('measure name', undefined, 'mark-2'); 

從標記到標記

  1. performance.measure('measure name''mark-1''mark-2'); 

資源性能數據

從 performance entry buffer 獲取數據

在上面的函數中,總是提到結果存儲在performance entry buffer,但是如何訪問其中的內容呢?

performance API有3個函數可以用來訪問該數據:

performance.getEntries()

獲取一組當前頁面已經加載的資源PerformanceEntry對象。接收一個可選的參數options進行過濾,options支持的屬性有name,entryType,initiatorType。

  1. let entries = window.performance.getEntries(); 

performance.getEntriesByName

根據參數name,type獲取一組當前頁面已經加載的資源數據。name的取值對應到資源數據中的name字段,type取值對應到資源數據中的entryType字段。

  1. let entries = window.performance.getEntriesByName(name, type); 

performance.getEntriesByType

根據參數type獲取一組當前頁面已經加載的資源數據。type取值對應到資源數據中的entryType字段。

  1. var entries = window.performance.getEntriesByType(type); 

結合事例:

  1. performance.mark('mark-1'); 
  2. // some code 
  3. performance.mark('mark-2'
  4. performance.measure('test''mark-1''mark-2'
  5. console.log(performance.getEntriesByName('test')[0].duration); 

Console.time

這個 API確實易于使用。當需要統計一段代碼的執行時間時,可以使用console.time方法與console.timeEnd方法,其中console.time方法用于標記開始時間,console.timeEnd方法用于標記結束時間,并且將結束時間與開始時間之間經過的毫秒數在控制臺中輸出。這兩個方法的使用方法如下所示。

  1. console.time('test'); 
  2. for (let i = 0; i < array.length; i++) { 
  3.   // some code 
  4. console.timeEnd('test'); 

 

輸出的結果與Performance API非常相似。

console.time的優點是易于使用,因為它不需要手動計算兩個時間戳之間的差。

減少時間精度

如果在不同的瀏覽器中使用上面提到的 api 測量函數,你可能會注意到結果是不同的。

這是由于瀏覽器試圖保護用戶免受時序攻擊(timing attack)和指紋采集(Fingerprinting ),如果時間戳過于準確,黑客可以使用它們來識別用戶。

例如,Firefox等瀏覽器試圖通過將精度降低到2ms(版本60)來防止這種情況發生。

注意事項

現在,我們已經知道了要測量JavaScript函數的速度所需方法。但是,最好還要避免一些陷阱:

分而治之

開發過程中,我們可能會我發現有些模塊執行速度很慢,但是我們不知道具體問題出在哪里。解決一個方法是,使用上面提到的這些函數來測量它,而不是胡亂猜測代碼的哪一部分比較慢。

要對其進行跟蹤,首先將console.time語句放在執行比較慢的代碼塊周圍。然后測量它們不同部分的表現。如果一個比另一個慢,那就繼續往下走,直到發現問題所在。

注意輸入值

在實際應用中,給定函數的輸入值可能會發生很大變化。僅針對任意隨機值測量函數的速度并不能提供我們可以實際使用的任何有價值的數據。

確保使用相同的輸入值運行代碼。

多次運行該函數

假設你有一個函數,它的功是遍歷一個數組,對數組的每個值進行一些計算,然后返回一個帶有結果的數組。你想知道是forEach循環還是簡單的for循環性能更好。

  1. function testForEach(x) { 
  2.   console.time('test-forEach'); 
  3.   const res = []; 
  4.   x.forEach((value, index) => { 
  5.     res.push(value / 1.2 * 0.1); 
  6.   }); 
  7.  
  8.   console.timeEnd('test-forEach'
  9.   return res; 
  10.  
  11. function testFor(x) { 
  12.   console.time('test-for'); 
  13.   const res = []; 
  14.   for (let i = 0; i < x.length; i ++) { 
  15.     res.push(x[i] / 1.2 * 0.1); 
  16.   } 
  17.  
  18.   console.timeEnd('test-for'
  19.   return res; 

然后這樣測試它們:

  1. const x = new Array(100000).fill(Math.random()); 
  2. testForEach(x); 
  3. testFor(x); 

如果在 Firefox 中運行上述函數,結果:

 

看起來forEach慢多了,對吧?

那如果是相同的輸入,運行兩次呢:

  1. testForEach(x); 
  2. testForEach(x); 
  3. testFor(x); 
  4. testFor(x); 

 

如果我們第二次調用forEach測試,它的執行效果和for循環一樣好。考慮到初始值較慢,在一些性能要求極高的項目,可能就不適合使用forEach。

在多個瀏覽器中測試

如果我們在Chrome中運行上述代碼,結果又會不一樣:

 

這是因為Chrome和Firefox具有不同的JavaScript引擎,它們具有不同類型的性能優化。

在本例中,Firefox 在對相同輸入的forEach進行優化方面做得更好。

for在兩個引擎上的性能都更好,因此在一些性能要求極高的項目就需要使用for循環。

這是為什么要在多個引擎中進行測量的一個很好的例子。如果僅使用Chrome進行測量,你可能會得出結論,與for相比,forEach并不那么糟糕。

限制的 CPU

我們在本地測試值是不能代表用戶在瀏覽器使用的情況,因為 我們開發的電腦一般都會比大部分的用戶好很多。

瀏覽器有一個特性可以限制CPU性能,我們通過設置可以更貼切一些真實情況。

總結

在本文中,我們看到了一些JavaScript API,我們可以使用它們來衡量性能,以及如何在真實的項目中使用它們。對于簡單的測量,我發現使用console.time更容易。如果要將測量與性能測量工具集成在一起,則可能需要使用performance.mark和performance.measure。

譯者:前端小智 作者:Felix Gerschau 來源:felixgerschau 原文:https://felixgerschau.com/measuring-the-performance-of-java-script-functions

本文轉載自微信公眾號「大遷世界」,可以通過以下二維碼關注。轉載本文請聯系大遷世界公眾號。

 

責任編輯:武曉燕 來源: 大遷世界
相關推薦

2023-04-26 10:21:04

2024-01-30 13:53:40

前端性能Chrome

2023-09-04 11:55:49

性能前端開發

2019-07-29 10:39:39

前端性能優化緩存

2020-08-25 18:56:19

前端開發技術

2023-03-01 09:07:44

前端監控異常

2019-04-08 16:50:33

前端性能監控

2023-08-02 08:14:33

監控MTS性能

2013-01-08 11:02:03

.NET.NET性能調優ANTS

2021-05-11 10:03:06

性能優化工具Performance

2024-02-02 15:21:08

工具頁面性能

2021-05-31 08:30:50

監控網站性能

2020-10-27 09:18:19

性能測試查詢

2021-07-16 10:32:33

前端元編程代碼

2021-10-11 08:14:17

CPU系統數據

2020-07-14 09:50:01

5G網絡技術

2021-04-06 11:36:47

Starlink網速互聯網

2017-08-11 19:13:01

LinuxNmon系統監控工具

2020-11-10 09:19:23

Spring BootJava開發

2020-03-16 09:45:09

前端docker代碼
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 国产精品一区在线观看 | 亚洲成人在线免费 | 国产激情毛片 | 欧美日韩一 | 国产精品亚洲一区二区三区在线 | 国产亚洲成av人在线观看导航 | 欧美成人a | caoporn国产| 日本不卡免费新一二三区 | 久久久精| h视频免费看 | 国产精品a一区二区三区网址 | 中文二区| www精品美女久久久tv | 精品久久久久一区二区国产 | 国产一级视频免费播放 | 国产午夜精品久久久久 | 亚洲男人网 | 亚洲精品免费在线 | 国产乱码久久久久久 | 91精品国产高清一区二区三区 | 久久综合一区 | 亚洲男人的天堂网站 | 国产永久免费 | 国产日韩在线观看一区 | 久久久黑人 | 久久久精彩视频 | 亚洲欧美国产毛片在线 | 天天夜天天操 | 久久国产精品免费 | 中文成人在线 | 亚洲狠狠爱 | 日韩午夜网站 | 久久中文字幕视频 | 四虎在线观看 | 国产专区在线 | 中文字幕乱码亚洲精品一区 | 超碰最新在线 | 免费一区二区三区 | 婷婷久久一区 | 免费观看一区二区三区毛片 |