node. JS Getting Started: Asynchronous IO

Source: Internet
Author: User

Asynchronous IO

In the operating system, the space that the program runs is divided into kernel space and user space. We often mention asynchronous I/O, which is essentially a program in user space that does not rely on I/O operations in the kernel space to actually complete the next task.

Parallel mode for synchronous IO

    • Multithreaded single Process
The design of multithreading is to realize the parallel processing task in the shared program space, so as to make full use of the CPU effect. The disadvantage of multithreading is the large overhead of context switching during execution, and the problem of state synchronization (lock). It also complicates program authoring and invocation.
    • Single thread multi-process
In order to avoid the inconvenience caused by multithreading, some languages choose single-threaded to keep the call simple, adopt the way of initiating multi-process to make full use of CPU and improve the overall parallel processing ability. Its disadvantage lies in the complexity of the business logic (involving multiple I/O calls), because the business logic cannot be distributed across multiple processes and the transaction length is much larger than multithreaded mode.

The necessity of asynchronous IO

The total time spent on these two tasks by a program that synchronizes is M + N. However, if you are using an asynchronous program, the time overhead will be reduced to Max (M, n) in situations where two I/O can be parallel (such as network I/O and file I/O). And when parallel tasks are more, M + N + ... With Max (M, N, ...) The best of both is a glance. node. JS naturally supports this asynchronous I/O, which is the root cause for many cloud computing vendors to favor.

Operating system support for asynchronous I/O

Asynchronous and non-blocking sounds like the same thing. From an actual effect point of view, both asynchronous and non-blocking have achieved our parallel I/o purposes. But from the computer kernel I/O, asynchronous/synchronous and blocking/non-blocking are actually two different things.
    • Blocking and non-blocking of I/O
Blocking mode I/O causes the application to wait until I/O is complete. While the operating system also supports the setting of I/O operations to non-blocking mode, the application's call may return immediately without getting the real data, which requires multiple calls to confirm the I/O operation is complete.
    • Synchronization and asynchronous for I/O
Synchronization and asynchronous presence of I/O occurs in the application. If you do block I/O calls, the process of the application waiting for the call to complete is a synchronous state. Instead, the application is asynchronous when I/O is non-blocking mode.

asynchronous I/O and polling technology

When a non-blocking I/O call is made, to read the full data, the application needs to poll multiple times to ensure that the read data is complete for the next steps. The disadvantage of polling technology is that applications are actively invoked, resulting in more CPU time slices and lower performance. The existing polling technology has the following:
    • READ: Full data reads are performed by repeated calls to check the status of I/O and the lowest performance.
    • Select: Determines the state of the event on the file descriptor.
    • Poll
    • Epoll
    • Pselect
    • Kqueue
Polling technology satisfies the assurance that asynchronous I/O ensures full data acquisition. But for applications, it can still count as a synchronization, because applications still need to proactively determine the state of I/O, and still spend a lot of CPU time waiting.

An ideal asynchronous I/O model

The ideal asynchronous I/O should be for an application to initiate an asynchronous call without polling to handle the next task, simply passing the data to the application via a signal or callback after I/O is complete.

Asynchronous IO schemes for different operating systems

    • Linux
There is a way to do this in Linux, which provides an asynchronous, non-blocking I/O mode (AIO) that passes data through a signal or callback.    Unfortunately, only Linux has such a support, and there are flaws (AIO only supports O_direct-mode reads in kernel I/O, which prevents the system cache from being exploited.)    Another ideal asynchronous I/O is to use blocking I/O, but to join multiple threads, divide I/O operations across multiple threads, and use communication between threads to simulate asynchrony. There is no perfect asynchronous I/O support under the Linux platform. Fortunately, Marc Alexander Lehmann, author of Libev, has re-implemented a library of asynchronous I/O: Libeio. The Libeio essence is still the asynchronous I/O that is simulated with the thread pool and blocking I/O.
    • Windows
Windows has a unique kernel asynchronous IO scenario: IOCP. The idea of IOCP is a true asynchronous I/O scenario, invoking an async method, and then waiting for I/O completion notification. IOCP internal threads are still implemented by threading, except that these threads are managed by the system kernel. The asynchronous model of IOCP is very similar to the asynchronous invocation model of node. js.

Asynchronous IO Scenarios for node. js

Due to the differences between the Windows platform and the *nix platform, node. JS provides libuv as an abstraction wrapper layer, making all platform compatibility judgments done at this level, ensuring that the upper node. JS is separate from the lower Libeio/libev and IOCP. node. JS will determine the platform conditions during compilation, selectively compiling UNIX directories or source files in the win directory into the target program.

The asynchronous IO Model of node. js

How exactly is node. JS's callback function called?    The file I/O is different from the normal business logic callback function because it is not triggered by our own code, but is triggered by the system after the end of the system call. Here we take the simplest fs.open approach as an example of how node. js and the underlying are performing asynchronous I/O calls and how the callback functions are invoked.
1Fs.open =function(path, flags, mode, callback) {2callback = Arguments[arguments.length-1]; 3     if(typeof(callback)!== ' function ') { 4callback =NoOp;5     }6mode = Modenum (mode, 438/*=0666*/); 7Binding.open (Pathmodule._makelong (path), stringtoflags (Flags), mode, callback); };

The function of Fs.open is to open a file according to the specified path and parameters, thereby obtaining a file descriptor, which is the initial operation of all subsequent I/O operations.

The Fs.open method called at the JavaScript level eventually calls through the node_file.cc to the Uv_fs_open method in Libuv, where LIBUV as the package layer, respectively, wrote two platform code implementation, after compiling, There will only be one implementation being called.
    • Request Object
In the Uv_fs_open Invocation, node. JS creates a Fsreqwrap request object. The parameters passed in from JavaScript and the current method are encapsulated in the request object, where the callback function is set on the object's Oncomplete_sym property.
Req_wrap->object_->set (Oncomplete_sym, callback);
After wrapping the object, call the QueueUserWorkItem method to push the Fsreqwrap object into the thread pool for execution.
QueueUserWorkItem (&uv_fs_thread_proc, req, wt_executelongfunction)
QueueUserWorkItem accepts three parameters, the first is the method to execute, the second is the context of the method, and the third is the flag to execute. Call the Uv_fs_thread_proc method to execute when there are threads available in the thread pool. The method calls the appropriate underlying function based on the type passed in, and in Uv_fs_open, for example, it is actually called to the Fs__open method. After the call is complete, the obtained results are set on Req->result. Then call PostQueuedCompletionStatus to notify us that the IOCP object operation has been completed.
PostQueuedCompletionStatus (Loop)->IOCP, 0, 0, & ((req)->overlapped))
The purpose of the PostQueuedCompletionStatus method is to communicate to the associated thread on the created IOCP, and the thread exits based on the execution state and the parameters passed in. At this point, the first phase of the asynchronous invocation initiated by the JavaScript plane ends.
    • Event Loops
In the process of calling the Uv_fs_open method, it is actually applied to the event loop. In implementation under the Windows platform, when you start node. js, a IOCP-based event Loop loop is created and is always in the execution state.
Uv_run (Uv_default_loop ());
In each loop, it calls the IOCP-related GetQueuedCompletionStatus method to check if there are any completed requests in the thread pool, and if so, the poll operation joins the request object to the Pending_reqs_tail property of the loop. On the other side, the loop also checks the Pending_reqs_tail reference on the Loop object and, if there is a request object available, takes the result property of the request object and passes it to oncomplete_sym for execution. This achieves the purpose of invoking the callback function passed in JavaScript.    At this point, the complete process of asynchronous I/O finishes. The process is as follows: The event loop and the Request object form the two basic elements of the asynchronous I/O model of node. JS, which is a typical consumer producer scenario. GetQueuedCompletionStatus, PostQueuedCompletionStatus, QueueUserWorkItem methods and events loop through IOCP under Windows. For the *nix platform, the difference between this process and the way to implement these features is provided by Libeio and Libev.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

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.