preface

This article is the eighth part of the V8 engine detailed series, focusing on the V8 engine message queuing, will start with the characteristics of the single thread, gradually its message queuing operation mechanism. There will be links to the finished series at the end of this article, which is still being updated.

Single thread

Why single thread

As javascript is originally a browser scripting language, it is mainly used to interact with users and manipulate DOM, etc. If multiple threads operate a DOM at the same time, it will be very difficult to handle, so javascript can only be designed as a single thread.

However, modern computers are basically multi-core CPUS, so pure single thread will lead to some performance cannot be released, so the concept of Web worker is put forward in the new HTML5 standard, allowing users to open additional threads, but worker threads are completely controlled by the main thread (processing some computing logic in most cases). And without DOM permissions, javascript is essentially single-threaded.

Asynchronous tasks

Javascript only a main thread to perform the task, but at the same time can only perform a task or function, general function can form a task queue execution, but some tasks can be very time consuming and uncontrolled (network) requests, event listeners, etc., if these tasks are and queue to perform common tasks, Then the execution efficiency is not to mention will cause the page to freeze. Then there are asynchronous tasks, and the V8 engine uses message queues and event loops to let them execute without queuing up for completion.

The message queue

The message queue is an additional queue maintained by the V8 engine in addition to the main thread tasks. It mainly stores the tasks (functions) to be executed. In full compliance with the first in first out (FIFO) feature of the queue, tasks are fetched from the head of the queue and added from the tail of the queue.

The browser itself requires many asynchronous scenarios, and each asynchronous operation has a different mechanism. Message queues can interact with many asynchronous scenarios.

  • Asynchronous interactions related to input events, such as onClick, are handled by the engine’s DOM Binding module, and the corresponding callback function is added to the message queue when the corresponding event is triggered.
  • Asynchronous interactions related to Ajax requests are handled by the engine’s Network module, and the corresponding callback function is added to the message queue after the network request is completed and returned.
  • Timer related asynchronous interactions are handled by the engine’s Timer module and the callback function is added to the task queue when the time is up. (Timer scheduling policies are complex, and special scheduling policies are used to add corresponding callback tasks at appropriate times.)

And some other modules will place asynchronous operations on message queues and wait until the main thread of the engine has finished executing the tasks pushed in the message queue. The details are as follows:

Help, I’m Stuck in an Event-Loop

So when will the message queue be executed? Each execution of the code in the stack is a macro task, and the tasks in the message queue are placed in the next macro task in sequence. As each macro task is executed, V8 recreates the stack and changes the stack as the function in the macro task is called. Finally, When the macro task finishes, the stack is emptied again, and the main thread continues to execute the next macro task.

The browser rerenders the page after a macro task has finished and before the next task has started:

Since the time granularity of the macro task in the message queue is too coarse for the main thread (there is a rendering process in the middle of the main thread), it is not capable of some scenes requiring high accuracy and real-time performance, so the Promise mechanism is introduced, namely the micro-task as shown in the figure:

(the key to this is not a macro and micro tasks so simple, but I want to say is that now the front interview big probability will be asked about macro and micro tasks, a lot of people will only answer the executing order of tasks was to the macro and micro, but if you answer the middle one page rendering process, in order to be truly understand)

Event loop

If you can understand the message queue mechanism above, then the event loop is easy to understand, essentially

  • The main thread run generates the stack of execution, and some asynchronous functions are called in the process of calling the stack.
  • When the trigger condition of an asynchronous function is met, the corresponding callback function is pushed to the message queue.
  • When the code in the main stack completes, a page rendering is triggered and a new main stack is created.
  • Push the callback function in the message queue to the main stack. The main stack tasks are then executed sequentially.
  • Repeating the above process over and over is a time loop.

conclusion

This paper mainly to understand the message queue on V8 engine running mechanism, also easy to understand why use a single thread mechanism, js and simply the macro and micro tasks (online related good article very much, so this paper does not repeat, simply point the overlooked point). If there are any mistakes, please discuss them with the author in the comments. If you found this article helpful, please give it a thumbs up.

Refer to the article

Vimeo.com/96425312 time.geekbang.org/column/arti…

series

V8 Engine Details (1) — Overview V8 engine details (2) — AST V8 engine details (3) — Bytecode evolution V8 engine details (4) — Bytecode execution V8 engine details (5) — Inline caching V8 engine details (6) — Memory structure V8 engine details (7) – Garbage collection mechanism V8 engine details (8) – message queue V8 engine details (9) – coroutines & generator functions