node. js Asynchronous IO

Source: Internet
Author: User

Why asynchronous I/O?
  • FromUser Experience Perspective, asynchronous IO can eliminate UI blocking and quickly respond to resources
    • JavaScript is single-threaded, and it is a thread that is shared with UI rendering. So when JavaScript executes, the UI rendering will be at a standstill and the user experience is poor. While asynchronous requests can download resources, JavaScript and UI rendering are executed simultaneously, eliminating UI blocking and reducing the time overhead required to respond to resources.
    • If a resource is returned from two different locations, the first resource takes a M millisecond, and the second resource takes n milliseconds to take time. When synchronizing, the total time taken is (m+n) milliseconds, and the code is roughly as follows:
      // time-consuming M-millisecond getData (' from_db '); // time-consuming n milliseconds getData (' From_remote_api ');

      When used asynchronously, the total time is Max (M,n), and the code is roughly the following:

      GetData (' from_db ',function(result) {  // consumption time is M    }); GetData (' From_remote_api ',function(result) {  // consumption time is n  });

      With the complexity of the application, the situation becomes m+n+ ... and Max (M,n, ... ), the pros and cons of synchronization and Asynchrony will be more prominent at this time. On the other hand, as sites and applications expand, data tends to spread across multiple servers, and distribution means that the values of M and n grow linearly, which also amplifies the performance differences between asynchronous and synchronous. In short, IO is expensive and distributed IO is more expensive!

    • From a resource allocation Perspective , asynchronous IO can allow single-line Chengyuan blocking to better utilize the CPU
      • Assuming that there is a set of unrelated tasks on the line of business that need to be done, there are two main ways to do this:
        • Single-threaded synchronous execution: Blocking IO results in less optimal use of hardware resources and CPUs
        • Multithreading concurrent execution: Deadlock, state synchronization, and other issues
      • Node's solution
        • The use of single thread , away from multi-threaded deadlock, state synchronization and other issues;
        • Use asynchronous I/O, let the single-line Chengyuan off-block, better CPU

Figure 1.1-Asynchronous I/O calls asynchronous IO implementation status?

I/O blocking and non-blocking : IO for the operating system kernel, only blocking and non-blocking two ways. 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. The technique of repeating calls to determine whether an operation is complete is called polling.

Synchronous and asynchronous I/O : Synchronous and asynchronous 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.

    • Calling blocking IO: Causes the CPU to wait for IO, waste wait time, and the CPU's processing power is not fully utilized:

    • Call non-blocking IO: Although IO is not blocked, but because IO is not completed, the immediate return is not the data expected by the business layer, just the state of the current call

In order to obtain the complete data, the application needs to invoke the IO operation repeatedly to confirm completion, called polling. The following are the main polling technologies:

    • READ: It is the most primitive, the lowest performance one.
    • Select: An improved scheme based on read that judges the status of events on file descriptors.
    • Poll: Better than Select, using a linked list to avoid data length limitations, and second it to avoid unnecessary checks. However, performance is very low when there are too many file descriptors.
    • Epoll: This scheme is the most efficient IO event notification mechanism under Linux, see figure.

 

Although Epoll has used events to reduce CPU consumption, the CPU is idle during hibernation and is not sufficiently utilized for the current thread. So, is there an ideal asynchronous I/O?

The answer is of course there is! the ideal asynchronous I/O implementation looks like this:

Smart you think: we can pass the data to the application by signal or callback !

Indeed, Linux provides a way of asynchronous IO (AIO), which is to pass data through a signal or callback.

Unfortunately, only Linux is available , and there are some flaws, such as the inability of the system cache to exploit it.

So, in reality, asynchronous IO is implemented like this:

We take advantage of multi-threading, the main thread is responsible for the computation, theIO thread is responsible for IO operations, and the threads communicate through signals .

Smart you may ask: node is not single-threaded, how to implement multithreading it?

In fact, thebottom of node can be multi-threaded , but the upper layer to provide users with the JavaScript is single-threaded. And here, what we're discussing is how node bottom is implementing asynchronous IO?

In fact, Linux is implemented using multithreaded creation thread pools like the one above, while Windows is created using IOCP .

After the realization of the asynchronous IO in the bottom of node is clear, we can further understand how a node process implements asynchronous IO.

    • Node's asynchronous I/O model:
      • Event Loop : When the process starts, node creates a loop like while (true) to determine if an event needs to be handled
      • Observer : The Observer is used to determine whether there are events to be dealt with. There is one or more observers in the event loop, and the judging process asks the observer if there are any events that need to be handled. This process is similar to the relationship between the restaurant chef and the front desk attendant. Cooks every round of dishes, will be the front desk waiter asked if there is a dish to do, if there is to continue to do, no words on the work. In this process, the front desk attendant is the equivalent of the observer, and the customer order she receives is the callback function.

Note: The event loop is a typical producer/consumer model . asynchronous I/O, network requests are producers, and event loops take events out of the observer and process them.

      • Request Object : Take the Fs.open () method as an example,
        Fs.open = function (path, flags, mode, callback) {//...binding.open (Pathmodule._makelong (path), stringtoflags (Flags), Mode,callback);};

          

        The purpose of this function 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.


Figure 1.2-Calling

The entire calling process:JavaScript, node core module, C + + built-in module, LIBUV system call

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.

At this point, the first phase of the asynchronous invocation initiated by the JavaScript plane ends.

      • Execute callback : Assemble the Request object, feed the I/O thread pool to wait for execution, actually complete the first part of asynchronous I/O, callback notification is the second part. 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 completed and return the thread to the thread pool.
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.

In this process, each event loop calls the GetQueuedCompletionStatus () method to check the thread pool for any completed requests and, if so, joins the request object to the I/O Observer's queue as an event handler.

The behavior of the I/O Observer callback function is to fetch the result property of the request object as a parameter, remove the Oncomplete_sym property as a method, and invoke execution to achieve the purpose of executing the callback function.

Note: IOCP is an asynchronous I/O solution under Windows

Summarize

JavaScript is single-threaded, but node itself is multithreaded , and all I/O requests can be executed in parallel, except that user code cannot be executed in parallel. The event Loop is the core of the node asynchronous I/O implementation, and node handles the request in an event-driven manner so that it does not have to create additional threads for each request, eliminating the overhead of creating and destroying threads. It also maintains node's high performance because of the small number of threads, which is not affected by thread context switching.

 

node. js Asynchronous IO

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.