摘要:同時也是對無法完整支持的一種補充。不過我們只能通過的返回結果判斷執行成功還是失敗。另外,雖然有垃圾回收機制,但開發者還是應當在使用完數據后手動刪除相應的。最新版版本已經修復上述問題。
原文地址:https://github.com/Microsoft/...
本文介紹 Napa.js 的核心概念,帶領大家探索 Napa.js 是如何運轉起來的。關于它的由來和開發初衷,可以閱讀 這篇文章
簡介 ZoneZone 是 Napa.js 中的核心概念,它是執行 JavaScript 代碼的基本單元,所有涉及多線程相關的內容都離不開 Zone 這個概念。一個進程可以包含多個 zone,而每個 zone 又由多個 JavaScript Worker 組成。
在 zone 內部的所有 worker 都是相似的:他們加載相同的代碼,幾乎以相同的方式處理 broadcast 和 execute 請求,你無法指定執行某一個特定 worker 中的代碼。在不同 zone 之間的 worker 是完全不同的:他們加載不同的代碼,或者雖然加載相同代碼但以不同的策略執行,例如堆棧大小不同、安全策略不同等。應用會利用多個 zone 來加載不同的策略。
有兩種類型的 zone:
Napa zone - 由多個 Napa.js 管理的 JavaScript worker 組成。Napa zone 內的 worker 支持部分 Node.js API
Node zone - 暴露了 Node.js event loop 的虛擬 zone,具有完備的 Node.js 能力
這樣劃分讓你既可以用 Napa zone 處理繁重的計算事務,也可以用 Node zone 處理 IO 事務。同時 Node zone 也是對 Napa zone 無法完整支持 Node API 的一種補充。
以下代碼創建了一個包含 8 個 worker 的 Napa zone:
var napa = require("napajs"); var zone = napa.zone.create("sample-zone", { workers: 8 });
以下代碼演示如何訪問 Node zone:
var zone = napa.zone.node;
在 zone 上可以做兩種類型的操作:
Broadcast - 所有 worker 執行同樣的代碼,改變 worker 狀態,返回 promise 對象。不過我們只能通過 promise 的返回結果判斷執行成功還是失敗。通常用 broadcast 來啟動應用、預加載一些數據或者修改應用設置。
Execute - 在一個隨機 worker 上執行,不改變 worker 狀態,返回一個包含結果數據的 promise。 execute 通常是用來做實際業務的。
Zone 的操作采用“先進先出”的策略,但 broadcast 比 execute 優先級更高。
以下代碼演示了使用 broadcast 和 execute 完成一個簡單的任務:
function foo() { console.log("hi"); } // This setups function definition of foo in all workers in the zone. zone.broadcast(foo.toString()); // This execute function foo on an arbitrary worker. zone.execute(() => { global.foo() });數據傳輸
由于 V8 不適合在多個 isolate 間執行 JavaScript 代碼,每個 isolate 管理自己內部的堆棧。在 isolate 之間傳遞值需要封送/拆收(marshalled/unmarshalled),載荷的大小和對象復雜度決定著通信效率。所有 JavaScript isolate 都屬于同一個進程,且原生對象可以被包裝成 JavaScript 對象,我們嘗試在此基礎上為 Napa 設計一種高效傳輸數據的模式。
為了實現上述模式,引入了以下概念:
可傳輸類型可傳輸類型是指可以在 worker 中自由傳輸的 JavaScript 類型。包括
JavaScript 基礎類型:null, boolean, number, string
實現了 Transportable 接口的對象(TypeScript class)
由以上類型構成的數組或對象
還有 undefined
跨 worker 存儲Store API 用于在 JavaScript worker 中共享數據。當執行 store.set 時,數據被封送到 JSON 并存儲在進程的堆棧中,所有線程都可以訪問;當執行 store.get 時,數據被拆收出來。
以下代碼演示如何利用 store 共享數據:
var napa = require("napajs"); var zone = napa.zone.create("zone1"); var store = napa.store.create("store1"); // Set "key1" in node. store.set("key1", { a: 1, b: "2", c: napa.memory.crtAllocator // transportable complex type. }; // Get "key1" in another thread. zone.execute(() => { var store = global.napa.store.get("store1"); console.log(store.get("key1")); });
盡管很方便,但不建議在同一個事務里用 store 傳值,因為這樣做不僅僅只傳輸了數據(還附帶了別的事情,比如加鎖)。另外,雖然有垃圾回收機制,但開發者還是應當在使用完數據后手動刪除相應的 key。
安裝執行 npm install napajs 安裝。
在 OSX 系統安裝后執行會報錯,在 github issue 中里也有同樣的提問,解決方法是按照官方的構建文檔,自己手動構建。 最新版 v0.1.4 版本已經修復上述問題。
步驟如下:
安裝先決依賴
Install C++ compilers that support C++14:
xcode-select --install
Install CMake:
brew install cmake
Install cmake-js:
npm install -g cmake-js
通過 npm 構建
npm install --no-fetch
快速上手示例 計算圓周率 π 值下面是一個計算 π 值的例子,演示了如何利用多線程執行子任務。
var napa = require("napajs"); // Change this value to control number of napa workers initialized. const NUMBER_OF_WORKERS = 4; // Create a napa zone with number_of_workers napa workers. var zone = napa.zone.create("zone", { workers: NUMBER_OF_WORKERS }); // Estimate the value of π by using a Monte Carlo method function estimatePI(points) { var i = points; var inside = 0; while (i-- > 0) { var x = Math.random(); var y = Math.random(); if ((x * x) + (y * y) <= 1) { inside++; } } return inside / points * 4; } function run(points, batches) { var start = Date.now(); var promises = []; for (var i = 0; i < batches; i++) { promises[i] = zone.execute(estimatePI, [points / batches]); } return Promise.all(promises).then(values => { var aggregate = 0; values.forEach(result => aggregate += result.value); printResult(points, batches, aggregate / batches, Date.now() - start); }); } function printResult(points, batches, pi, ms) { console.log(" " + points + " " + batches + " " + NUMBER_OF_WORKERS + " " + ms + " " + pi.toPrecision(7) + " " + Math.abs(pi - Math.PI).toPrecision(7)); } console.log(); console.log(" # of points # of batches # of workers latency in MS estimated π deviation"); console.log(" ---------------------------------------------------------------------------------------"); // Run with different # of points and batches in sequence. run(4000000, 1) .then(result => run(4000000, 2)) .then(result => run(4000000, 4)) .then(result => run(4000000, 8))
運行結果如下,當設置為 1 組、2 組、4 組子任務并行計算時,可以看出執行時間有明顯提升,當設置為 8 組子任務并行計算時,由于沒有更多的空閑 worker 資源,也就沒有明顯的執行時間的提升。
# of points # of batches # of workers latency in MS estimated π deviation --------------------------------------------------------------------------------------- 40000000 1 4 1015 3.141619 0.00002664641 40000000 2 4 532 3.141348 0.0002450536 40000000 4 4 331 3.141185 0.0004080536 40000000 8 4 326 3.141620 0.00002724641計算斐波那契數列
var napa = require("napajs"); // Change this value to control number of napa workers initialized. const NUMBER_OF_WORKERS = 4; // Create a napa zone with number_of_workers napa workers. var zone = napa.zone.create("zone", { workers: NUMBER_OF_WORKERS }); /* Fibonacci sequence n: | 0 1 2 3 4 5 6 7 8 9 10 11 ... ------------------------------------------------------------------------- NTH Fibonacci: | 0 1 1 2 3 5 8 13 21 34 55 89 ... */ function fibonacci(n) { if (n <= 1) { return n; } var p1 = zone.execute("", "fibonacci", [n - 1]); var p2 = zone.execute("", "fibonacci", [n - 2]); // Returning promise to avoid blocking each worker. return Promise.all([p1, p2]).then(([result1, result2]) => { return result1.value + result2.value; }); } function run(n) { var start = Date.now(); return zone.execute("", "fibonacci", [n]) .then(result => { printResult(n, result.value, Date.now() - start); return result.value; }); } function printResult(nth, fibonacci, ms) { console.log(" " + nth + " " + fibonacci + " " + NUMBER_OF_WORKERS + " " + ms); } console.log(); console.log(" Nth Fibonacci # of workers latency in MS"); console.log(" -----------------------------------------------------------"); // Broadcast declaration of "napa" and "zone" to napa workers. zone.broadcast(" var napa = require("napajs"); var zone = napa.zone.get("zone"); "); // Broadcast function declaration of "fibonacci" to napa workers. zone.broadcast(fibonacci.toString()); // Run fibonacci evaluation in sequence. run(10) .then(result => { run(11) .then(result => { run(12) .then(result => { run(13) .then(result => { run(14) .then(result => { run(15) .then(result => { run(16) }) }) }) }) }) })
運算結果
Nth Fibonacci # of workers latency in MS ----------------------------------------------------------- 10 55 4 10 11 89 4 13 12 144 4 15 13 233 4 22 14 377 4 31 15 610 4 50 16 987 4 81
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/89203.html
摘要:前端日報精選源碼解析一組件的實現與掛載寫在的前端數據層不完全指北非時圓角邊框剪裁問題專題之解讀排序源碼中的閉包再也不用擔心面試被問什么是閉包了中文路由路由基礎入門實戰操作詳細指南前端學習教程用實現一門編程語言語言簡介眾成翻譯第 2017-10-19 前端日報 精選 React源碼解析(一):組件的實現與掛載寫在2017的前端數據層不完全指北Chrome opacity非1時border...
摘要:前端日報精選使用玩轉也許這樣理解更容易簡介的學習筆記的過濾器中文介紹前端課堂之入門詳解前端課堂模塊整理掘金服務端渲染框架基于實戰前端隨筆掘金奇舞周刊第期發布啦我的插件配置二楞徐程序猿小白應該注意什么掘金英文 2017-10-21 前端日報 精選 使用Puppeteer玩轉Headless Chrome也許這樣理解 HTTPS 更容易Napa.js 簡介Vue 2.0的學習筆記:Vue的...
摘要:取自我的的,歡迎,歡迎。原不定期更新,此文可能斷更。最新更新時間。前端資源中文平時開發和學習過程中自己收集的一些前端資源。自行取用,不斷更新。你也可以關注我從而在我的點贊中了解到更多有意思的項目。前端之路,且行且珍惜。 取自 我的GITHUB 的 fe-store-house repo,歡迎 PR,歡迎 STAR。原 repo 不定期更新,此文可能斷更。斷更了一年多,重新更新一下,似乎...
摘要:取自我的的,歡迎,歡迎。原不定期更新,此文可能斷更。最新更新時間。前端資源中文平時開發和學習過程中自己收集的一些前端資源。自行取用,不斷更新。你也可以關注我從而在我的點贊中了解到更多有意思的項目。前端之路,且行且珍惜。 取自 我的GITHUB 的 fe-store-house repo,歡迎 PR,歡迎 STAR。原 repo 不定期更新,此文可能斷更。斷更了一年多,重新更新一下,似乎...
摘要:取自我的的,歡迎,歡迎。原不定期更新,此文可能斷更。最新更新時間。前端資源中文平時開發和學習過程中自己收集的一些前端資源。自行取用,不斷更新。你也可以關注我從而在我的點贊中了解到更多有意思的項目。前端之路,且行且珍惜。 取自 我的GITHUB 的 fe-store-house repo,歡迎 PR,歡迎 STAR。原 repo 不定期更新,此文可能斷更。斷更了一年多,重新更新一下,似乎...
閱讀 3285·2021-11-24 09:39
閱讀 3866·2021-11-22 09:34
閱讀 4799·2021-08-11 11:17
閱讀 1060·2019-08-29 13:58
閱讀 2570·2019-08-28 18:18
閱讀 537·2019-08-26 12:24
閱讀 825·2019-08-26 12:14
閱讀 727·2019-08-26 11:58