簡體   English   中英

Array.map() 的箭頭函數,.bind 還是 argThis? 垃圾收集 + 性能

[英]Arrow functions, .bind or argThis for Array.map()? garbage collection + performance

我正在從事一個每天處理數十億個請求的項目,並且非常關注性能和內存使用情況。

昨天我在每分鍾執行很多次的代碼中實現了一些更改,並且我使用了箭頭函數進行了一些映射,但是團隊要求我在使用 .map 時總是使用 argsThis,我不明白為什么,所以我做了很多基准測試,結果恰恰相反。

基准測試(綁定 vs 箭頭函數 vs ArgsThis)

他們的論點是垃圾收集在使用箭頭函數時是最糟糕的,並且這些情況並未顯示真實場景,因為它具有非常淺的上下文。

在此處輸入圖片說明

基准測試表明箭頭函數要快得多,我有什么需要考慮的嗎?
謝謝!

編輯:

問題是對於我們需要來自上層上下文的變量的情況,例如:

function doSomething() {
    const someUpperContextValue = 5;
    [1, 2, 3].map((currentValue) => calculateValues(someOutterContextValue, currentValue));
}

免責聲明:只要知道您的低於現實世界的基准可能不會顯示全貌,但我不會在這里討論。

我們可以非常基本地了解 JavaScript 引擎如何調用函數。 請注意,我不是 JS 運行時如何工作的專家,所以請糾正我的錯誤或不完整的地方。

每當執行函數時,都會創建一個“調用范圍”並將其添加到堆棧中。 對於普通/經典函數(非箭頭函數),引擎創建一個新的上下文,它有自己的“閉包”和變量范圍。 在此上下文中是一些隱式創建的變量,例如引擎放置在那里的thisarguments

function foo() {
  const self = this;
  function bar(...args) {
    console.log(this === self); //-> false
    console.log(arguments); //-> { length: 1, 0: 'barg' }
    console.log(args); //-> [ 'barg' ]
  }
  bar('barg');
  console.log(arguments); //-> { length: 1, 0: 'farg' }
} 
foo('farg');

箭頭函數的工作方式與常規函數非常相似,但沒有額外的閉包和額外的變量。 密切關注日志結果的差異:

function foo() {
  const self = this;
  const bar = (...args) => {
    console.log(this === self); //-> true
    console.log(arguments); //-> { length: 1, 0: 'farg' }
    console.log(args); //-> [ 'barg' ]
  }
  bar('barg');
  console.log(arguments); //-> { length: 1, 0: 'farg' }
} 
foo('farg');

有了這個非常熱門的......幾乎是膚淺的......知識,你可以看到引擎在創建箭頭函數時做了“更少的工作”。 有理由認為箭頭函數本質上更快。 此外,我認為箭頭函數不會比常規函數( 有用的鏈接)引入更多潛在的內存泄漏或垃圾收集。

編輯:

值得一提的是,每次聲明一個函數時,都會定義一個占用內存空間的新變量。 JavaScript 引擎還必須為每個函數保留“上下文”,以便在“父”作用域中定義的變量在函數執行時仍然可用。 例如,任何時候在上面調用foo ,都會在內存中創建一個新的bar變量,可以訪問其父“foo”調用范圍的完整上下文。 JS 引擎很擅長弄清楚何時不再需要上下文並在垃圾收集期間將其清理干凈,但要知道如果垃圾很多,即使垃圾收集也會很慢。

此外,引擎有一個優化層(參見Turbofan ),它非常智能且不斷發展。 為了說明這一點,請考慮您提供的示例:

function doSomething() {
    const someUpperContextValue = 5;
    [1, 2, 3].map((currentValue) => calculateValues(someOutterContextValue, currentValue));
}

在不太了解 JS 引擎內部的情況下,我可以看到引擎優化doSomething函數,因為someUpperContextValue變量的靜態值為5 如果將該值更改為Math.random()類的值,現在引擎不知道該值將是什么並且無法優化。 由於這些原因,很多人會告訴你問“哪個更快”是在浪費時間,因為你永遠不知道什么時候一個小的無害變化會完全扼殺你的表現。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM