您好,登錄后才能下訂單哦!
這篇文章主要介紹了JavaScript函數的性能各種方式對比,具有一定借鑒價值,感興趣的朋友可以參考下,希望大家閱讀完這篇文章之后大有收獲,下面讓小編帶著大家一起了解一下。
JavaScript是一種直譯式的腳本語言,其解釋器被稱為JavaScript引擎,是瀏覽器的一部分,JavaScript是被廣泛用于客戶端的腳本語言,最早是在HTML網頁上使用,用來給HTML網頁增加動態功能。
測量執行一個函數所需的時間總是一個很好的辦法,證明某些實現比另一個實現的性能更好。這也是一個很好的方法,可以確保性能沒有在某些改變后受到影響,也可以追蹤瓶頸。
良好的性能有助于獲得良好的用戶體驗,良好的用戶體驗會讓用戶回頭客。一項研究顯示,88%的在線消費者因為性能問題,在用戶體驗不佳后用戶回來的可能性較小。
這就是為什么能夠識別代碼中的瓶頸并測量改進的原因。尤其是在為瀏覽器開發JavaScript時,要注意到你寫的每一行JavaScript都有可能阻塞DOM,因為它是一種單線程語言。
在這篇文章中,我將解釋你如何測量你的功能的性能,以及如何處理你從它們中得到的結果。
performance API通過其功能performance.now()提供對DOMHighResTimeStamp的訪問,該函數返回自頁面加載以來經過的時間(以毫秒為單位),精度最高為5μs(以分數為單位)。
所以在實踐中,你需要取兩個時間戳,保存在一個變量中,然后讓第二個時間戳減去第一個時間戳。
const t0 = performance.now(); for (let i = 0; i < array.length; i++) { // some code } const t1 = performance.now(); console.log(t1 - t0, 'milliseconds');
Chrome輸出
0.6350000001020817 "milliseconds"
Firefox輸出
1 milliseconds
在這里,我們可以看到Firefox中的結果與Chrome完全不同,這是因為Firefox版本從60開始將 performance API 的精度降低到2ms。
performance API提供的功能遠比只返回時間戳要多得多,它能夠測量導航計時、用戶計時或資源計時。請看這篇文章,里面有更詳細的解釋。
但是,對于我們的用例,我們只想測量單個函數的性能,因此時間戳就足夠了。
那不是和Date.now一樣嗎?
現在你可能會想:我也可以用Date.now來做這個啊。
是的,可以,但是有缺點。
Date.now以毫秒為單位返回從Unix紀元("1970-01-01-01T00:00:00:00Z")開始的時間,并且取決于系統時鐘。這不僅意味著它沒有那么精確,而且也不一定會遞增。WebKit工程師(Tony Gentilcore)的解釋如下:
也許較少考慮到的是,基于系統時間的Date也不是真正的用戶監控的理想選擇。大多數系統都會運行一個守護進程來定期同步時間。通常情況下,時鐘每隔15-20分鐘就會調整幾毫秒。在這個速度下,大約有1%的10秒的時間間隔是不準確的。
該API確實易于使用,只需將console.time放在你要測量的代碼前面,將console.timeEnd放在要測量的代碼后面,即可使用相同的string參數調用該函數,一頁上最多可以同時使用10,000個計時器。
精度與 performance API 相同,但這又取決于瀏覽器。
console.time('test'); for (let i = 0; i < array.length; i++) { // some code } console.timeEnd('test');
這樣會自動生成易于理解的輸出,如下所示:
Chrome輸出
test: 0.766845703125ms
Firefox輸出
test: 2ms - timer ended
這里的輸出又與Performance API非常相似。
console.time的優點是易于使用,因為它不需要手動計算兩個時間戳之間的差。
如果你在不同的瀏覽器中使用上面提到的API來測量你的函數,你可能會發現結果會有差異。
這是由于瀏覽器試圖保護用戶免受定時攻擊和指紋攻擊, 如果時間戳太準確,黑客可以使用它來識別用戶。
例如,Firefox之類的瀏覽器試圖通過將精度降低到2ms(版本60)來防止這種情況。
現在,你已經擁有測量JavaScript函數的速度所需的工具。但是,最好避免一些陷阱。
你注意到在過濾一些結果時有些東西很慢,但是你不知道瓶頸在哪里。
與其胡亂猜測代碼中哪一部分是慢的,不如用上述這些函數來測量。
要追蹤它,首先把你的console.time語句放在慢的代碼塊周圍。然后測量它們的不同部分是如何執行的,如果其中一個部分比其他部分慢,那么就繼續下去,每次深入到那里,直到找到瓶頸。
這些語句之間的代碼越少,跟蹤不感興趣的內容的可能性就越小。
在實際應用中,給定函數的輸入值可能會發生很大變化。僅針對任意隨機值測量函數的速度并不能提供我們可以實際使用的任何有價值的數據。
確保使用相同的輸入值運行代碼。
假設你有一個函數對一個數組進行迭代,對每個數組的值進行一些計算,并返回一個數組的結果。你想知道是forEach還是簡單的for循環更有效。
這是函數:
function testForEach(x) { console.time('test-forEach'); const res = []; x.forEach((value, index) => { res.push(value / 1.2 * 0.1); }); console.timeEnd('test-forEach') return res; } function testFor(x) { console.time('test-for'); const res = []; for (let i = 0; i < x.length; i ++) { res.push(x[i] / 1.2 * 0.1); } console.timeEnd('test-for') return res; }
你可以這樣測試它們:
const x = new Array(100000).fill(Math.random()); testForEach(x); testFor(x);
如果你在Firefox中運行上述函數,你將獲得類似以下的輸出:
test-forEach: 27ms - timer ended
test-for: 3ms - timer ended
看起來forEach變慢了,對吧?
讓我們看看是否使用相同的輸入兩次運行相同的函數:
testForEach(x);
testForEach(x);
testFor(x);
testFor(x);
test-forEach: 13ms - timer ended
test-forEach: 2ms - timer ended
test-for: 1ms - timer ended
test-for: 3ms - timer ended
如果我們第二次調用forEach測試,它的性能與for循環一樣好。鑒于初始值較慢,可能無論如何都不值得使用forEach。
如果我們在Chrome中運行上述代碼,結果會突然看起來不同:
test-forEach: 6.156005859375ms
test-forEach: 8.01416015625ms
test-for: 4.371337890625ms
test-for: 4.31298828125ms
這是因為Chrome和Firefox具有不同的JavaScript引擎,并且具有不同類型的性能優化。意識到這些差異是一件好事。
在這種情況下,Firefox在相同輸入的情況下,對forEach的使用進行了較好的優化。
for在兩個引擎上的性能都更好,因此最好堅持使用for循環。
這是為什么要在多個引擎中進行測量的一個很好的例子。如果僅使用Chrome進行測量,您可能會得出結論,與for相比,forEach并不那么糟糕。
這些數值看起來并不高。要知道,你的開發機器通常比你的網站所使用的普通手機瀏覽速度要快得多。
為了感受一下這個樣子,瀏覽器有一個功能,可以讓你節流你的CPU性能。
有了這個,那些10或50ms很快就變成了500ms。
這些原始結果實際上不僅僅取決于你的硬件,還取決于你的CPU和你的JavaScript線程的當前負載。盡量關注你的測量結果的相對改進,因為下次重啟電腦時,這些數字可能會看起來很不一樣。
感謝你能夠認真閱讀完這篇文章,希望小編分享的“JavaScript函數的性能各種方式對比”這篇文章對大家有幫助,同時也希望大家多多支持億速云,關注億速云行業資訊頻道,更多相關知識等著你來學習!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。