摘要:原文作者譯文如何百倍加速引入惰性計算譯者我一直以為像這樣的庫已經不能再快了,畢竟它們已經足夠快了。函數返回價格低于的所有元素。延遲執行和惰性計算一起使用的是延遲執行。懶惰計算并不是行業里的新理念。
原文:How to Speed Up Lo-Dash ×100? Introducing Lazy Evaluation.
作者: Filip Zawada
譯文:如何百倍加速 Lo-Dash?引入惰性計算
譯者:justjavac
我一直以為像 Lo-Dash 這樣的庫已經不能再快了,畢竟它們已經足夠快了。
Lo-Dash 幾乎完全混合了各種 JavaScript 奇技淫巧(YouTube)來壓榨出最好的性能。
但似乎我錯了 - 其實 Lo-Dash 可以運行的更快。
你需要做的是,停止思考那些細微的優化,并開始找出更加適用的算法。
例如,在一個典型的循環中,我們往往傾向于去優化單次迭代的時間:
var len = getLength(); for(var i = 0; i < len; i++) { operation(); // <- 10毫秒 - 如何優化到9毫秒?! }
代碼說明:取得數組的長度,然后重復執行 N 遍 operation() 函數。譯注 by @justjavac
但是,這(優化 operation() 執行時間)往往很難,而且對性能提升也非常有限。
相反,在某些情況下,我們可以優化 getLength() 函數。
它返回的數字越小,則每個 10 毫秒循環的執行次數就越少。
這就是 Lo-Dash 使用惰性計算的思想。
這是減少周期數,而不是減少每個周期的執行時間。
讓我們看看下面的例子:
function priceLt(x) { return function(item) { return item.price < x; }; } var gems = [ { name: "Sunstone", price: 4 }, { name: "Amethyst", price: 15 }, { name: "Prehnite", price: 20 }, { name: "Sugilite", price: 7 }, { name: "Diopside", price: 3 }, { name: "Feldspar", price: 13 }, { name: "Dioptase", price: 2 }, { name: "Sapphire", price: 20 } ]; var chosen = _(gems).filter(priceLt(10)).take(3).value();
代碼說明:gems 保存了 8 個對象,名字和價格。priceLt(x) 函數返回價格低于 x 的所有元素。譯注 by @justjavac
我們把價格低于 10 美元的前 3 個 gems 找出來。
常規 Lo-Dash 方法(嚴格計算)是過濾所有 8 個 gems,然后返回過濾結果的前 3 個。
不難看出來,這種算法是不明智的。
它處理了所有的 8 個元素,而實際上我們只需要讀取其中的 5 個元素就能得到我們想要的結果。
與此相反,使用惰性計算算法,只需要處理能得到結果的最少數量就可以了。
如圖所示:
我們輕而易舉就獲得了 37.5% 的性能提升。
但是這還不是全部,其實很容易找到能獲得 1000 倍以上性能提升的例子。
讓我們一起來看看:
// 99,999 張照片 var phoneNumbers = [5554445555, 1424445656, 5554443333, … ×99,999]; // 返回包含 "55" 的照片 function contains55(str) { return str.contains("55"); }; // 取 100 張包含 "55" 的照片 var r = _(phoneNumbers).map(String).filter(contains55).take(100);
在這個例子中,map 和 filter 用來處理 99,999 個元素。
不過我們只需要它的一個子集就可以得到想要的結果了,例如 10,000 個,
性能提升也是非常大的(基準測試):
惰性計算帶來了另一個好處,我稱之為 "Pipelining"。
它可以避免鏈式方法執行期間創建中間數組。
取而代之,我們在單個元素上執行所有操作。
所以,下面的代碼:
var result = _(source).map(func1).map(func2).map(func3).value();
將大致翻譯為如下的常規 Lo-Dash(嚴格計算)
var result = [], temp1 = [], temp2 = [], temp3 = []; for(var i = 0; i < source.length; i++) { temp1[i] = func1(source[i]); } for(i = 0; i < source.length; i++) { temp2[i] = func2(temp1[i]); } for(i = 0; i < source.length; i++) { temp3[i] = func3(temp2[i]); } result = temp3;
如果我們使用惰性計算,它會像下面這樣執行:
var result = []; for(var i = 0; i < source.length; i++) { result[i] = func3(func2(func1(source[i]))); }
不使用臨時數組可以給我們帶來非常顯著的性能提升,特別是當源數組非常大時,內存訪問是昂貴的資源。
延遲執行和惰性計算一起使用的是延遲執行。
當你創建一個鏈,我們并不立即計算它的值,直到 .value() 被顯式或者隱式地調用。
這種方法有助于先準備一個查詢,隨后我們使用最新的數據來執行它。
var wallet = _(assets).filter(ownedBy("me")) .pluck("value") .reduce(sum); $json.get("/new/assets").success(function(data) { assets.push.apply(assets, data); // 更新我的資金 wallet.value(); // 返回我錢包的最新的總額 });
在某些情況下,這樣做也可以加速執行時間。我們可以在前期創建復雜的查詢,然后當時機成熟時再執行它。
Wrap up懶惰計算并不是行業里的新理念。它已經包含在了許多庫里面,例如 LINQ、Lazy.js 等等。我相信 Lo-Dash 和這些庫最主要的區別是,你可以在一個更新的、更強大的引擎里面使用原有的 Underscore API。不需要學習新的庫,不需要修改代碼,只是簡單升級。
但是,即使你不打算使用 Lo-Dash,我希望這篇文章啟發了你。
現在,當你發現你的應用程序存在性能瓶頸,不要僅僅是去 jsperf.com 以 try/fail 風格優化它。
而是去喝杯咖啡,并開始考慮算法。
最重要的是創意,但良好的數學背景會讓你如魚得水(book)。祝你好運!
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/78316.html
摘要:本文將講述源碼中,惰性求值的原理和實現。惰性求值中的參數直到需要時才會進行計算。執行的示例圖如下惰性求值做法普通的做法存在一個問題每個方法各做各的事,沒有協調起來浪費了很多資源。 前言 lodash受歡迎的一個原因,是其優異的計算性能。而其性能能有這么突出的表現,很大部分就來源于其使用的算法——惰性求值。本文將講述lodash源碼中,惰性求值的原理和實現。 一、惰性求值的原理分析 惰性...
摘要:我用替換已經有一段時間了。更快,支持,并且擁有所缺乏的特性。這真是太棒了同樣聲稱類似,但是使用惰性求值,并發布了一些令人印象深刻的速度比較。如果你使用,不管在哪里使用包括,你應該花上幾分鐘切換到。 我用Lo-Dash替換Underscore已經有一段時間了。Lo-Dash更快,支持AMD,并且擁有Underscore所缺乏的特性。同時,Lo-Dash和Underscore是100%兼容...
摘要:原文可觀察量是一種能惰性推送的集合,他可以包含多個值。是一種惰性計算方式,會在迭代中同步的返回到無限個可能的話返回值。使用一種處理方法,最終可能會或可能不會返回一個值。無論是同步方式還是異步方式,都可以擇其一來傳遞返回值。 原文:http://reactivex.io/rxjs/manu... Observable 可觀察量是一種能惰性推送的集合,他可以包含多個值。下面的表格對比了推送...
摘要:然而學習布局,你只要學習幾個手機端頁面自適應解決方案布局進階版附源碼示例前端掘金一年前筆者寫了一篇手機端頁面自適應解決方案布局,意外受到很多朋友的關注和喜歡。 十分鐘學會 Fiddler - 后端 - 掘金一.Fiddler介紹 Fiddler是一個http抓包改包工具,fiddle英文中有欺騙、偽造之意,與wireshark相比它更輕量級,上手簡單,因為只能抓http和https數據...
摘要:譯文地址譯唯快不破應用的個優化步驟前端的逆襲知乎專欄原文地址時過境遷,應用比以往任何時候都更具交互性。使用負載均衡方案我們在之前討論緩存的時候簡要提到了內容分發網絡。換句話說,元素的串形訪問會削弱負載均衡器以最佳形式 歡迎關注知乎專欄 —— 前端的逆襲歡迎關注我的博客,知乎,GitHub。 譯文地址:【譯】唯快不破:Web 應用的 13 個優化步驟 - 前端的逆襲 - 知乎專欄原文地...
閱讀 1629·2023-04-25 18:27
閱讀 1389·2021-10-19 11:44
閱讀 563·2021-10-14 09:42
閱讀 2138·2021-10-11 10:59
閱讀 2769·2021-09-24 09:47
閱讀 1723·2019-08-30 14:20
閱讀 1150·2019-08-30 14:08
閱讀 731·2019-08-29 15:15