試玩一下 Nodejs 10.5.0 Worker Threads
最近 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 的事情。這點要謹記。