This article will give you a preliminary understanding of asynchronous I/O in Nodejs. It has certain reference value. Friends in need can refer to it. I hope it will be helpful to everyone.
# The term "asynchronous" was actually born before Node. But in most high-level programming languages, asynchrony is rare. Among many high-level languages or operating platforms, Node is the first to use asynchronous as the main programming method and design concept. [Related recommendations: "nodejs Tutorial"]
Asynchronous I/O, event-driven and single-threaded constitute the keynote of Node, and the event-driven and asynchronous I/O design of Nginx and Node The concepts are relatively similar. Nginx is written in pure C, has excellent performance, and has the powerful ability to manage connections for clients, but it is still limited by various synchronization programming languages. But Node is all-round. It can be used as a server to handle a large number of concurrent requests brought by clients, and it can also be used as a client to make concurrent requests to various applications in the network.
Why asynchronous I/O
Why asynchronous I/O is so important in Node? This is because Node is designed for the network. Under the structure, concurrency has become a standard feature in modern programming.
User Experience
It is mentioned in "High Performance JavaScript" that if the execution time of the script exceeds 100 milliseconds, the user will feel that the page is stuck. Think the page has stopped responding. In the B/S model, network speed limitations cause great trouble for the real-time experience of web pages.
If the web page temporarily needs to obtain a resource and obtain it synchronously, then JavaScript needs to wait for the resource to be completely obtained from the server before it can continue execution. During this period, the UI pauses and does not respond to the user's interaction. This user experience will be extremely poor. With asynchronous requests, during the downloading of resources, the execution of JavaScript and UI will not be in a waiting state and can continue to respond to user interactions.
Similarly, the front-end can eliminate UI blocking through asynchronous use, but the speed at which the front-end obtains resources also depends on the response speed of the back-end. If a resource comes from the return of data from two different locations, the first resource consumes M milliseconds and the second resource consumes N milliseconds. If the synchronization method is used, the time consumed to obtain the two resources is M N milliseconds. In the asynchronous method, the acquisition of the first resource does not block the acquisition of the second resource, and the time consumed is max(M,N).
As the website or application continues to expand, the values of M and N will grow linearly, and asynchronous performance will be more superior than synchronous.
Resource Allocation
Assuming that there is a set of unrelated tasks that need to be completed in the business scenario, there are the following two mainstream methods:
- Single-threaded serial execution at one time
- Multi-threaded parallel completion
If the cost of creating multi-threads is less than parallel execution, then multi-threading is preferred, but multi-threading requires more effort in creating threads and The overhead of thread context switching during execution is relatively large, and multi-thread programming often faces problems such as locks and state synchronization.
The disadvantage of single-threaded sequential execution of tasks is performance. Any slightly slower task will cause subsequent execution of the code to be blocked. In computer resources, I/O and CPU calculations can usually be executed in parallel, but the synchronous programming model causes I/O to wait for subsequent tasks, resulting in resources not being better utilized.
Node uses a single thread to stay away from multi-thread deadlock, state synchronization and other problems; it uses asynchronous I/O to keep a single thread away from blocking and better utilizes the CPU.
Asynchronous I/O implementation
Asynchronous I/O is the most widely used in Node, but it is not original to Node.
Asynchronous I/O and non-blocking I/O
For computer kernel I/O, asynchronous/synchronous and blocking/non-blocking are two different things. .
The operating system has only two methods for I/O: blocking and non-blocking. When calling blocking I/O, the application needs to wait for the I/O to complete before returning the result.
One of the characteristics of blocking I/O is that after the call, the call must wait until the system kernel level completes all operations before the call ends. Blocking I/O causes the CPU to wait for I/O, wasting waiting time, and the CPU's processing power cannot be fully utilized.
In order to improve performance, the kernel provides non-blocking I/O. The difference between non-blocking I/O and blocking I/O is that it will return immediately after the call. After non-blocking I/O returns, the CPU time slice can be used to process other things. At this time, the performance improvement is obvious, but due to the completion of The I/O is not completed, and what is returned immediately is not the data expected by the business layer, but only the current calling status.
In order to obtain complete data, the application needs to repeatedly call the I/O operation to confirm whether it is completed. This technique of repeatedly calling to determine whether the operation is completed is called Polling.
The existing polling technologies mainly include read, select, poll, epoll and kqueue. Here I will only talk about the polling principle of epoll.
epoll is the most efficient I/O event notification mechanism under Linux. When entering polling, if no I/O event is detected, it will sleep until an event occurs to wake it up. It truly uses event notification and execution callback methods instead of traversing queries, so it does not waste CPU and has higher execution efficiency.
Polling technology meets the need for non-blocking I/O to ensure that complete data is obtained, but for the program, it is still considered a kind of synchronization, because the application still needs Waiting for the I/O to return completely, it still takes a lot of time to wait. While waiting, the CPU is either used to iterate through file descriptors or sleep while waiting for time to occur.
Realistic asynchronous I/O
Completes data acquisition by letting some threads perform blocking I/O or non-blocking I/O plus polling technology, allowing a Threads perform calculations and transfer the data obtained from I/O through communication between threads, which easily implements asynchronous I/O (although this is simulated)
But initially, Node was in *nix The platform uses libeio and libev to implement the I/O part and implement asynchronous I/O. In Node v0.9.3, a thread pool is implemented to complete asynchronous I/O.
The IOCP under Windows provides Li Xiang's asynchronous I/O to a certain extent: calling asynchronous methods, waiting for notification after I/O is completed, and executing callbacks. Users do not need to consider polling. But its internals are still based on the thread pool principle. The difference is that these thread pools are managed by the system kernel.
Due to the difference between Windows platform and *nix platform, Node provides libuv as an abstract encapsulation layer, so that all platform compatibility judgments are completed by this layer, and ensures the customization of the upper Node and the lower layer. The thread pool and IOCP are completely independent.
We often mention that Node is single-threaded. The single-thread here is just JavaScript executing in a single thread. In Node, whether it is *nix or Windows platform, there is a thread pool that completes I/O tasks internally.
Node’s asynchronous I/O
The event loop, observer, and request object complete the entire asynchronous I/O link.
Event Loop
The event loop is Node's own execution model, which makes callback functions very common.
When the process starts, Node will create a loop similar to while(true). Each time the loop body is executed, we call it Tick. The process of each Tick is to check whether there is an event to be processed, and if so, retrieve the event and its related callback function. If associated callback functions exist, execute them. Then enter the next loop, and if there are no more events to handle, exit the process.
Observer
There are one or more observers in each event loop, and it is used to determine whether there are events to be processed The process is to ask these observers if there are events to process.
In Node, events mainly come from network requests, file I/O, etc. The observers corresponding to these times include file I/O observers, network I/O observers, etc. Observers categorized events.
The event loop is a typical producer/consumer model. Asynchronous I/O, network requests, etc. are the producers of events, constantly providing different types of events to Node. These events are delivered to the corresponding observers, and the event loop takes the events from the observers and processes them.
Request object
For Node’s asynchronous I/O calls, the callback function is not called by the developer. In the transition process from JavaScript initiating a call to the kernel executing an I/O operation, there is a product called Request object
The fs.open() method is used below as a small example.
fs.open = function(path,flags,mode,callback){ //... binding.open(pathModule._makeLong(path), stringToFlags(flags), mode, callback); }
The function of fs.open() is to open a file based on the specified path and parameters to obtain a file descriptor. This is the initial trial operation for all subsequent I/O operations. JavaScript-level code performs lower-level operations by calling the C core module.
is engaged in JavaScript calling the core module of Node. The core module calls the C module, and the built-in module makes system calls through libuv. This is the classic calling method in Node. Here libuv serves as the encapsulation layer and has two platform implementations, which essentially calls the uv_fs_open() method. During the calling process of uv_fs_open(), the parameters passed in from the JavaScript layer and the current method are encapsulated in a request object, and the callback function is set on the properties of this object. After the object is packaged, the object is pushed into the thread pool to wait for execution.
At this point, the JavaScript call returns immediately, and the first phase of the asynchronous call initiated by the JavaScript level ends. JavaScript threads can continue to perform subsequent operations on the current task.
The request object is an important intermediate product in the asynchronous I/O process. All states are saved in this object, including being sent to the thread pool to wait for execution and callback processing after the I/O operation is completed.
Execution callback
Assemble the request object and send it to the I/O thread pool to wait for execution. It only completes the first part of an I/O. The callback notification is the first part. Part Two.
After the I/O operation in the thread pool is called, the obtained result will be stored in the req->result attribute, and then PostQueueCompletionStatus() will be called to notify IOCP that the current object operation has been completed.
At this point, the entire asynchronous I/O process is completely over.
Event loop, observer, request object, and I/O thread pool together constitute the basic elements of the Node asynchronous I/O model.
Summary
After sorting it out, we can extract several keywords of asynchronous I/O: single thread, event loop, observer and I/O thread pool. Single thread and thread pool seem to be a bit of a paradox. Because JavaScript is single-threaded, it is easy to understand that it cannot take full advantage of multi-core CPUs. In fact, in Node, except that JavaScript is single-threaded, Node itself is actually multi-threaded, but the I/O thread uses less CPU. Also, except that user code cannot be executed in parallel, all I/O (disk I/O, network I/O, etc.) can be executed in parallel.
For more programming related knowledge, please visit: Programming Video! !
The above is the detailed content of A preliminary understanding of asynchronous I/O in Nodejs. For more information, please follow other related articles on the PHP Chinese website!

Vercel是什么?本篇文章带大家了解一下Vercel,并介绍一下在Vercel中部署 Node 服务的方法,希望对大家有所帮助!

gm是基于node.js的图片处理插件,它封装了图片处理工具GraphicsMagick(GM)和ImageMagick(IM),可使用spawn的方式调用。gm插件不是node默认安装的,需执行“npm install gm -S”进行安装才可使用。

今天跟大家介绍一个最新开源的 javaScript 运行时:Bun.js。比 Node.js 快三倍,新 JavaScript 运行时 Bun 火了!

在nodejs中,lts是长期支持的意思,是“Long Time Support”的缩写;Node有奇数版本和偶数版本两条发布流程线,当一个奇数版本发布后,最近的一个偶数版本会立即进入LTS维护计划,一直持续18个月,在之后会有12个月的延长维护期,lts期间可以支持“bug fix”变更。

大家都知道 Node.js 是单线程的,却不知它也提供了多进(线)程模块来加速处理一些特殊任务,本文便带领大家了解下 Node.js 的多进(线)程,希望对大家有所帮助!

node怎么爬取数据?下面本篇文章给大家分享一个node爬虫实例,聊聊利用node抓取小说章节的方法,希望对大家有所帮助!


Hot AI Tools

Undresser.AI Undress
AI-powered app for creating realistic nude photos

AI Clothes Remover
Online AI tool for removing clothes from photos.

Undress AI Tool
Undress images for free

Clothoff.io
AI clothes remover

AI Hentai Generator
Generate AI Hentai for free.

Hot Article

Hot Tools

WebStorm Mac version
Useful JavaScript development tools

SAP NetWeaver Server Adapter for Eclipse
Integrate Eclipse with SAP NetWeaver application server.

MantisBT
Mantis is an easy-to-deploy web-based defect tracking tool designed to aid in product defect tracking. It requires PHP, MySQL and a web server. Check out our demo and hosting services.

SublimeText3 Chinese version
Chinese version, very easy to use

Dreamweaver Mac version
Visual web development tools