試玩一下 Nodejs 10.5.0 Worker Threads

Hyman Chen
Hybrid Maker
Published in
4 min readJun 25, 2018
“Spools of white cotton threads on a machine in a factory in Rydal.” by Janko Ferlič on Unsplash

最近 Node 發表了新的版本 10.5.0 支持了 worker threads 的技術,於是我就來玩看看!簡單介紹一下這個功能,node 預設在執行的時候只會跑單一執行緒,所以你有四核心的電腦,開了一個 node 的 server ,只會同時跑一個核心,目前來說都是用 cluster 這個功能把程式依照 cpu 的數量 fork 出來,worker 跟 cluster 比較不太像,他比較像是把要複雜處理的程式單獨抽出來成為一個執行緒,體積比較小,那我們就來看看範例。

worker threads 是還在實驗中的功能,所以我不確定以後會不會被拿掉

簡單的 worker 範例

我先做了一個主程式 index.js,他會透過建立一個 worker 並且聽取 worker 回傳的 message 做顯示

另外做了一隻 worker.js 他會負責處理一些複雜邏輯

首先要確定你的 node js 版本為 10.5.0,執行程式由於是實驗性質的功能,所以我們要在執行的指令上面加入 flag 變成這樣 node --experimental-worker index.js 程式才可以正常被執行,執行之後產生出結果為這樣。

WorkerData 傳入預設數值

worker 有一個功能就是可以給予 workerData 不同的數值在每個 worker 裡面,變成每個 worker 都可以給予預設參數,我們做了兩隻 worker ,第一個 worker 每次遞增 1 , 第二個 worker 每次遞增 10

worker.js 裡面取得 workerData 的方式是透過 require,如下方範例

執行出來的結果如下

postMessage 溝通

我們可以透過 postMessage 從 main thread 傳送訊息到 worker 裡面,這跟瀏覽器的 web worker 使用方式一樣。

而 worker 則是透過 parentPort 來接收跟傳送訊息回去

執行結果就如同以下

並行提升執行效能

我現在來做一個範例,產生兩百萬筆亂數的 sha256 編碼,如果使用單一執行緒的方式來寫會是這樣

所耗費的時間為 10376 ms

而把兩百萬筆資料平均分配給 4 個執行緒去執行呢?

全部完成的時間是 5676 ms,所以適當的時機使用 worker threads 可以提升效能

Threads 共享記憶體

cluster 不能夠共享記憶體,所以我們通常會把資料存在 db 或是 file 來讓每個 cluster 取用,但是 worker-threads 每個 threads 可以跟 main thread 共享 SharedArrayBuffer 的資訊,意思就是當我 postMessage 的時候不用在拷貝一次記憶體了,這樣不僅減少記憶體的用量,也提高了速度,但是缺點就是不是很方便使用,畢竟轉換成 SharedArrayBuffer 比較麻煩。

請看這個範例,當 worker 告訴我成功的時候,我直接拿取 main thread 裡面的數值,而結果顯示了 worker 的確修改了共用的記憶體。

總結

比起 cluster , worker_threads 可以讓我把一些複雜的邏輯抽開獨立,不過我唯一可以想到的使用情境是在資料科學跟機器學習。node 總算可以把全部的 cpu 拿來運並且分享記憶體位置了 😄 ,另外就是官方有講到不要在 worker 裡面做 I/O 的事情。這點要謹記。

--

--