nodejs非同步IO的實現

來源:互聯網
上載者:User
本文為原創文章,出自http://cnodejs.org,轉載請註明出處和作者
作者:changlin
原文:http://cnodejs.org/blog/?p=244

nodejs的核心之一就是非阻塞的非同步IO,於是想知道它是怎麼實現的,挖了下nodejs源碼,找到些答案,在此跟大家分享下。首先,我用了一段js代碼test-fs-read.js做測試,代碼如下:

var path = require('path'), fs = require('fs'), filepath = path.join(__dirname, 'experiment.log'), fd = fs.openSync(filepath, 'r');  fs.read(fd, 12*1024*1024, 0, 'utf-8', function(err, str, bytesRead) {     console.log('[main thread] execute read callback'); }); console.log('[main thread] execute operation after read');

這段代碼的非同步IO操作就在fs.read的調用上,讀取的experiment.log是一個12M的文字檔,所謂的非同步,大家大概能想得到運行時會先列印
[main thread] execute operation after read
然後列印回呼函數中的
[main thread] execute read callback

但 大家也許還聽說過,nodejs是單線程的,那又是怎麼實現非同步IO的呢?讀檔案操作是在哪裡執行的呢?讀完又是怎麼調用回呼函數的呢?猜想讀文 件可能是在另一個線程中完成的,讀完後通過事件通知nodejs執行回調。為了一探究竟,debug了一把nodejs和libeio源碼,重新編譯後, 運行測試代碼node test-fs-read.js,輸出如下:

可以看到,nodejs的IO操作是通過調用libeio庫完成的,debug從fs.read開始,js代碼經過v8編譯後,fs.read會調用node_file.cc中的Read方法,測試代碼的運行經曆了以下步驟:

1 node_file.cc中的Read方法調用libeio(eio.c)的eio_read, read請求被放入請求隊列req_queue中。

2 主線程建立了1個eio線程,此時主線程的read調用返回。

3 eio線程從req_queue中取出1個請求,開始執行read IO

4 主線程繼續執行read調用後的其它操作。

5 主線程poll eio,從響應隊列res_queue取已經完成的請求,此時res_queue為空白,主線程stop poll

6 eio線程完成了read IO,read請求被放入響應隊列res_queue中,並且向主線程發送libev事件want_poll(通過主線程初始化eio時提供的回呼函數)。

7 eio線程從req_queue中取下一個請求,此時已經沒有請求。

8 主線程響應want_poll事件,從res_queue中取出1個請求,取出請求後res_queue變為空白,主線程發送done_poll事件。

9 主線程執行請求的callback函數。

還需要說明的是,當同時有多個IO請求時,主線程會建立多個eio線程,以提高IO請求的處理速度。
為了更清晰的看到nodejs的IO執行過程,圖示如下,序號僅用來標示流程,與上述步驟序號並無對應關係。

最後總結幾條,不當之處還請大家指正。

1 nodejs通過libev事件得到IO執行狀態,而不是輪詢,提高了CPU利用率。

2 雖然nodejs是單線程的,但它的IO操作是多線程的,多個IO請求會建立多個libeio線程(最多4個),使通常情況的IO操作效能得到提高。

3 但是當IO操作情況比較複雜的時候,有可能造成線程競爭狀態,導致IO效能降低;而且libeio最多建立4個線程,當同時有大量IO請求時,實際效能有 待測量。另外,由於每個IO請求對應一個libeio的資料結構,當同時有大量IO操作駐留在系統中時候,會增加記憶體開銷。

4 Libeio為了實現非同步IO功能,帶來了額外的管理,當IO資料量比較小的時候,整體效能不一定比同步IO好。

 

1、node使用libeio實現非阻塞非同步檔案操作,但實際上libeio是通過多線程的方式,在標準的阻塞式IO上類比非阻塞非同步。

2、為什麼node沒有使用原生態的非同步IO API(AIO)?原因可能是為了實現跨平台的相容性(主要針對Windows,具體參見:http://groups.google.com /group/nodejs/browse_thread/thread/aff97d25c59f6f2d)

3、libeio的4個線程限制是預設配置,可以對此配置進行修改

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.