This article is original Article , From the http://cnodejs.org, reprinted please indicate the source and author
Author: Changlin
Http://cnodejs.org/blog? P = 244
One of the core of nodejs is non-blocking asynchronous Io, so I want to know how it is implemented. I have dug the node. js source code and found some answers. I would like to share with you here. First, I used a piece of JSCodeTest-fs-read.js to do the test, the Code is as follows:
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 ');
The asynchronous Io operation of this Code is on the call of FS. Read. The read experiment. log is a 12 m text file. The so-called Asynchronization, you may want to print it first when you want to run it.
[Main thread] execute Operation after read
Then print
[Main thread] execute read callback
But you may have heard that nodejs is single-threaded. How does it Implement Asynchronous io? Where is the file read operation performed? How did I call the callback function after reading it? It is assumed that the read file may be completed in another thread. After reading the file, the node. JS is notified to execute the callback through the event. To find out exactly, debug a nodejs and libeio source code, re-compile, run the test code node test-fs-read.js, the output is as follows:
We can see that node. js Io operations are completed by calling the libeio library, and debug is performed from FS. after the JS Code is compiled by V8, the FS. read calls the read method in node_file.cc. The following steps are taken to test the Code:
The read method in 1 node_file.cc calls the eio_read of libeio (EIO. C), and the read request is put into the request queue req_queue.
2. The main thread creates an EIO thread. At this time, the read call of the main thread returns.
3. the EIO thread extracts one request from req_queue and starts executing read Io.
4. The main thread continues to execute other operations after the read call.
5. The main thread poll EIO is used to retrieve completed requests from the response queue res_queue. At this time, the res_queue is empty and the main thread stops poll.
6. the EIO thread completes the read Io, the read request is put into the response queue res_queue, And the libev event want_poll is sent to the main thread (the callback function provided when the main thread initializes EIO ).
7. the EIO thread takes the next request from req_queue, and no request has been made.
8. The main thread responds to the want_poll event and extracts one request from res_queue. After the request is retrieved, res_queue becomes null. The main thread sends the done_poll event.
9 The main thread executes the callback function of the request.
It should also be noted that when there are multiple IO requests at the same time, the main thread will create multiple EIO threads to increase the processing speed of IO requests.
The following figure shows the node. js I/O Execution Process in a clearer way. The serial number is only used to indicate the process. It does not correspond to the serial number of the above steps.
The last few articles are summarized. Please correct the mistakes.
1 nodejs gets the IO execution status through the libev event, instead of polling, which improves CPU utilization.
2. Although nodejs is single-threaded, its Io operations are multi-threaded. Multiple IO requests will create multiple libeio threads (up to four ), improves the performance of Io operations in general cases.
3. However, when I/O operations are complex, thread competition may occur, resulting in lower I/O performance. In addition, libeio can create up to four threads. When there are a large number of I/O requests at the same time, the actual performance is to be measured. In addition, because each Io request corresponds to a libeio data structure, when a large number of Io operations reside in the system at the same time, the memory overhead will be increased.
4 libeio provides additional management to Implement Asynchronous Io functions. When the IO data volume is small, the overall performance is not necessarily better than synchronous Io.
1. node uses libeio to implement non-blocking asynchronous file operations. In fact, libeio simulates non-blocking asynchronous operations on standard blocking Io through multi-thread methods.
2. Why didn't node use the original asynchronous Io API (AIO )? The reason may be to achieve cross-platform compatibility (mainly for Windows, see: http://groups.google.com/group/nodejs/browse_thread/thread/aff97d25c59f6f2d)
3. The four libeio thread restrictions are the default configuration, which can be modified.