如何評價Microsoft的開源項目napajs?

Napa.js: a multi-threaded JavaScript runtime

github:Microsoft/napajs


前段時間我也正好擼了一個 Node.js 的多線程庫來著,簡單粗暴地看了下 NapaJS 的介面,分別提供了 transport/store/memory 來在線程間共享數據,相對地,提供了同步(Sync)介面,這些其實都是多線程比較通用的一些特性,就不多說了,要用 Node.js Addon 做這個也是很容易的。

不過,對於$M引入了 Zone 這個概念,個人覺得算是一個新東西,按照文檔中定義的一個 Zone 可以容納多個工作線程(Thread),每個工作線程都是冪等的,然後分別提供了2個方法對每個工作線程做操作,分別是:

  1. broadcast,可能跟我們理解的廣播有一些不同,這裡並不是我們理解的發送消息那麼簡單,而是說讓每一個工作線程執行同樣的代碼,一般被用來初始化用的;
  2. execute,在其中一個工作線程中執行你定義的代碼,值得注意的是這裡的執行不會改變工作線程的狀態,從而保證下一次的 execute 仍然是冪等的;

這裡一個有趣的事情便是,除了基本的多線程介面外,$M特意提供了 Zone 就是來簡化多線程的業務邏輯,這裡保證每個 Worker 冪等性的原因也是在於用戶不必自己去維護數據的同步性,將鎖作為一種高級 API 來提供,從而降低了一些多線程的使用門檻,這個看得出來是經過時間和實戰沉澱出來的結果。

另外要說的就是 NapaJS 所支持的 Node.js 介面:Microsoft/napajs 基本上都是一些同步方法,具體實現方式還沒有來得及讀完,但我想不支持非同步方法的原因還不支持類似 postMessage 這種通訊方式吧,因為整體看下來,每個線程雖然是獨立的,不過$M還是傾向於將每個工作線程的代碼當作是代碼片段去執行,因此所有的代碼組織還是會放在主線程去完成。

這裡不得不說下我之前擼的 Rokid/node-webworker,首先為了簡化 API,我選擇了直接去掉所有多線程介面,然後使用 WebWorker 標準提供給用戶,也算是跟 NapaJS 的方式異曲同工吧!另外一個不同點是,由於 postMessage 和 onmessage 的存在,因此在我的實現中,可以輕鬆在工作線程中調用主線程的非同步回調方法,不過這也意味著,工作線程中的代碼量相較於 NapaJS 會更多,並且其實兩份不同運行時的代碼也會經常讓內部的使用者混淆。

最後,個人還是比較看好 NapaJS 的,源代碼一如既往地好看,還有介面也可以看出設計者的良苦用心,但它並不會是所有多線程方案的最佳實踐,別忘記了它的約束條件!


Napa.js

Napa.js is a multi-threaded JavaScript runtime built on V8, which was originally designed to develop highly iterative services with non-compromised performance in Bing. As it evolves, we find it useful to complement Node.js in CPU-bound tasks, with the capability of executing JavaScript in multiple V8 isolates and communicating between them. Napa.js is exposed as a Node.js module, while it can also be embedded in a host process without Node.js dependency.

以前的javascript都是運行在單線程上的,這個線程用一個棧來處理函數過程,用一個隊列來處理事件和setTimeout。簡單的說,先在棧里處理函數,棧空了以後就從隊列里拿事件出來處理。

現在我軟要搞多線程的javascript runtime了,這樣以前js靠隊列實現的promise-then,現在真的能靠多線程實現了。這兩種模式的區別是,以前一次只能做一件事,比如先燒水,這時把「水開沖水」這個事件放進隊列,燒水的時候去切菜,切完菜後檢查水有沒有開,開了的話就沖水。沒有開的話就把「水開沖水」這個事件再放進隊列里,然後繼續切肉,切完肉再檢查水。。。。

現在直接有3個人,一個燒水,一個切菜,一個切肉。

run)


Napa.js的中心思想跟PHP的Swoole引擎異曲同工.

PHP的Swoole中將請求的事件輪詢放在master進程的reactor線程里,將PHP執行邏輯放在worker進程里.worker進程也有事件輪詢,比如非同步HTTP/Redis/MySQL客戶端,所以Swoole還提供了task進程.可以把worker進程里的PHP邏輯中CPU計算耗時的操作(比如推送系統消息到所有客戶端)放到task進程執行,避免worker進程的EventLoop被密集計算阻塞.


瀉藥。

基本來說,這庫……

很一般。

之前 node 下已經有一些基於 thread 的 C++ 擴展庫,或者基於進程的 api 包裝。napajs 除了提供了稍微不同的 api 包裝,本質上並沒有超出這些庫。最重要的是,(到目前為止)沒有提供不經過序列化直接傳遞大塊數據的方式。

所以在現在這個時間點,沒有什麼好說的,就是等 node 內核實現 WebWorkers 介面(包括對 ArrayBuffer、SharedArrayBuffer、Atomics 等的完全支持)才是唯一正道。在此介面上,你愛包個什麼 API 都可以,比方說 zone/broadcast/execute 這樣的,3天擼一個沒有問題。

最後說一下,我並不喜歡 napa 傳遞函數的方式,因為其不遵循(也不可能遵循)標準的閉包語義。這種看上去有點兒方便的東西其實並沒有提供真正的價值。當然,從好的方面說,這也算一個目前情況下還不錯的 workaround,畢竟可以避開很麻煩的模塊問題。

以上。


唯一好奇的地方是為什麼是基於v8而不是ChakraCore……

所以其實MS內部用了很多基於v8的node么……


全世界都開始抄vert.x了

多核的node.js-&>node.x,which就是vert.x最早叫的名字

eventloop,支持同步方法(worker verticle)

vert.x不僅把這些都給做了,連同多腳本支持(不僅僅是js)也都給搞定了

生態的話,vert.x支持npm和maven repo,想不出來比這個更大的eco了

理論上vert.x連gem都能支持

還跨平台

現在連spring也開始搞什麼eventloop

不過怎麼看這些東西的功能都只是做到vert.x的一個子集

比如vert.x支持讓ruby像用node一樣寫代碼,這個抄襲者就都沒做到

還有groovy之類的,你自己都可以定義一個語言然後讓vert.x支持

比如latte

Latte lang - A JVM Language


嗯,剛出來,各種資料都比較缺,官方文檔也不健全。看看這篇中文翻譯入門先ヾ?≧?≦)o

https://zhuanlan.zhihu.com/p/30305523


這是正經玩意

rest+多線程密集計算

js server嘛都能幹了


我們理解或者說通過宣傳中知道的Node是非同步的,其實Node中js代碼執行和事件通知是運行在一個線程中的,js代碼中的耗時操作會擠占事件輪詢的CPU時間。

Napa.js的出現,對於 Node 的這個缺陷進行了很好的補充,將js執行和事件輪詢拆分到不同的線程中。不過在引入多線程概念的同時,線程之間數據的同步也同樣會注意。


( ???)!可以不用開多個實例了?話說為什麼不一鼓作氣起名為 napa.ts……(霧


js 的多線程的庫不止M$一家,哪個好用還不知道了


推薦閱讀:

HSimulate這條Hydrogen里的instruction到底是什麼意思?

TAG:前端開發 | JavaScript | Nodejs | V8 |