fibjs 對比 nodejs 有哪些優點和缺點?
只說我現在想起來的 fibjs 的缺點吧,以後想起來再補充。
一、說的最多的問題:生態。fibjs 作為新興的開發框架,生態必定會是原始的。並且因為顛覆了 nodejs 的範式,所以也不太能直接借用 npm 的生態。雖然很多 npm 組件其實是可以直接使用的,但是更多人需要的 web/db/io 相關組件一概不可用。沒有英文文檔,在把 fibjs 推向國外社區上乏力,也進一步限制了生態的發展。
二、fiber 相比 callback 而言的唯一缺點是堆棧內存佔用。golang 採取增長堆棧的方式解決了這個問題。因為涉及到 v8 的實現,fibjs 目前沒有好的解決方案。針對這個問題,fibjs 實際上並不是完全的 fiber,等待時間較長的模塊,fibjs 仍然採取的是 callback 的設計。比如 web server 的處理 handler。這樣一來,fiber 的數量便不會因為連接的暴漲而增加太多。一個網站同時 1萬個連接,每秒請求可能只有 500,每個請求 100ms,同時處理的請求也才 50 個而已,而 fibjs 發起萬級 fiber 毫無壓力。這樣的數量級根本沒有到需要考慮內存的程度。
三、fibjs 仍比較年輕,沒有經過更多應用的檢驗,很多組件甚至在孢子社區內部也沒有實用過。以 ssl 為例,最近公司內部在應用的時候便發生了連接一些網站證書驗證問題。即便使用過的組件,也會存在設計不合理的問題。這些都是需要社區的支持,一起驗證、建議和改進的。湊個熱鬧。看了一點點(大概0.00000000001%)的 fib 源碼 (看不懂啊看不懂)優點:大致 @響馬 大叔把非同步的 js 都放到與主 js 不同的線程池裡處理了。* 註:這裡是指長時間等待任務,比如http,短時間的非同步 io 應該是交給協程處理/纖程處理。而 node js 都貌似在同一個js執行進程里,回調(基本沒看過 node 實現)也是搞回主 context 執行。反正趕腳實現上比 node 牛B好多好多啊,起碼人家細節處理的好。
var http = require("http");
server = http.createServer(function (req, res) {
res.end("Hello, World!");
aaa+bb;
})
server.listen(8000);
aaa和bb 都沒定義,運行下,好了,node 直接掛。再刷就 Error Report
fib:var http = require("http");
var svr = new http.Server(8001, function(r){
r.response.write("Hello, World!");
aaa+bb;
});
svr.run();
aaa和bb 都沒定義,運行下,http 模塊線程拋出異常,主進程還在,隨便刷,依然 Hello, World! 堅挺。
總覺得很安心的樣子。var http = require("http");
server = http.createServer(function (req, res) {
res.end("Hello, World!");
})
server.listen(8000);
while(1){}
跟上個重操作(都知道會憋死 = =|||),果然 node 就憋死了,http 請求沒法響應鳥。
因為回調沒有機會插入到主進程的js執行流中,主js一直在操作,不給機會啊。fib:var http = require("http");
var svr = new http.Server(9999, function(r){
r.response.write("Hello, World!");
});
svr.run();
while(1) {}
同樣跟重操作,fib 依然沒事兒,跑的杠杠的。只因為就不上趕著跟主js一起跑。
又小安心了一把呢。--- 以上修改補充 ---
實際上,svr.run 執行後,後面代碼掛起了,不等 server 切出後面不會執行。如果換成 asyncRun 後,就跟node一樣憋死,如:var http = require("http");
var svr = new http.Server(9999, function(r){
r.response.write("Hello, World!");
});
svr.asyncRun();
while(1) {}
說點正經的,貌似沒 npm 之類的東西吧,分享個模塊趕腳很不容易的樣子呢。這就是網路外部性不如 node 嘍。
修改:偶然間看到了這個 http://fpmjs.org/ fpm …… 沒試呢,看來逐步在有。
——————————————補充:fibjs.cpp 初始V8時候給了 --harmony --harmony_proxies
--use_strict
--nologfile_per_isolate
三個參數。
1、其中 --harmony 部分開啟太保守,沒有給出更多參數可選,比如 --harmony_observation、--harmony_collections、--harmony_modules、--harmony_promises(這個興許壓根在fib里用不上 - -+)等,比node 的可配置靈活性差一點。
2、--use_strict 確定了代碼是標準模式的,寫的時候得注意點。
3、--nologfile_per_isolate 不說了,對前端沒啥用。
以上這句修改,因為孢子大叔說有命令行設置項了。——————————————這也可以算是個缺陷,要是跟 node 一樣有配置參數就好了。
晚上又去看了點,更正下,不是線程,貌似是協程(人家文檔里叫纖程)。
有點明白的感覺,由於協程要由自己實現的調度器控制(主動放棄CPU佔用)等wait時候保存當前調用棧和寄存器值後,再切換到其他協程。所以 fib 的非同步寫法是看起來阻塞的,其實當前環境保留,空虛時間被調度器分配運行其他協程了。如此說來,fib與node看起來相似,實際實現完全不同。壓根倆都不是同類的玩意兒。以後看懂多點再補充。——————————————實驗了一些 fib 代碼,使用思路上它和node也不相同。fib 更關注某個孤立的邏輯模塊扔到纖程里就可以不用管了。
而node更關注於某個api是不是非同步要不要用callback來組織代碼。比如,fib:var coroutine = require("coroutine");
var http = require("http");
function foo() {
var t = bar();
console.log(t);
}
function bar() {
var t = http.request("GET", "http://www.baidu.com");
console.log("bar1");
return t.length;
}
foo.start();
console.log("1");
// 就為了拖點時間避免start到纖程後還沒執行完js主線程就退了
coroutine.sleep(1000);
foo.start 到纖程後就可以不用管了,後續代碼能繼續執行。
裡面包什麼api是不是同步的都不用關心,fib自會非同步調度。大概node 得這麼寫(偶node不熟,大致意思吧 = =|||)var http = require("http");
function foo() {
bar(function(l){
console.log(l);
});
}
function bar(fn) {
var opts = {
hostname: "www.baidu.com",
port: 80,
path: "/",
method:"GET"
};
var req = http.request(opts, function(res){
var _d = "";
res.on("data", function(t) {
_d+=t;
});
res.on("end", function() {
console.log("bar1");
fn(_d.length);
});
});
}
foo();
console.log("1");
為了把上面的代碼換成node的回調方式,折騰了半天,基本上等於人工做了 wind.js 乾的事兒。
對比下,fib 基本上不用費心什麼非同步流程式控制制。隨便寫,然後包個不需要返回值的 function start 下完事兒。感覺就跟在線程類里寫代碼似得,run 一把可以不管了。額……突然想到,怪不得 fib 的 coroutine 里有 Lock 呢,跟線程鎖一個路數……先寫道這兒,以後看懂多點再補充。響馬這麼構想是有道理的。但一直糾纏在fibjs與Node之間非我所願,還有各種Web技術可以討論、借鑒、比較。
推薦閱讀:
※ECMAScript 6 會重蹈 ECMAScript 4 的覆轍嗎?
※為何大多數人和新的項目不用 TypeScript 而用 JS + 一堆輔助工具?
※IDE中,選中一個變數,文檔中其它地方的該變數也會高亮,這種功能叫什麼?如何實現的?
※2017你覺得未來五年最具前景的一門編程語言是什麼?
TAG:JavaScript | 後端技術 | Nodejs | fibjs |