This article will help you understand the dual-thread model in WeChat mini programs. Let’s talk about what is the dual-thread model of mini programs? Why does the applet not use the browser's threading model, but uses the dual-threading model? I hope it will be helpful to everyone!
Friends who have experience in WeChat applet development should all know the concept of "dual-threaded model". This article briefly summarizes some popular science knowledge of the dual-threaded model. The knowledge is shallow. Please correct me if there are any errors.
I used to work in the "Mini Program·Cloud Development" team. In some external training and technology sharing, I was often asked this question: "The main technical difference between WeChat Mini Program and Web website What is it?" In terms of programming language and paradigm, small program development is very similar to Web front-end development (for example, both use JavaScript language, WXML/WXSS which is very similar to HTML/CSS, etc.), but it does not directly use the native front-end technology. [Related learning recommendations: 小program development tutorial]
Compared with Web websites, small programs hosted on WeChat need to consider security, performance and other factors. Ensure that mini programs do not pose security risks to the WeChat App itself, and at the same time, try to achieve performance and user experience as close to native applications as possible. These are the two main reasons why small programs do not directly use the browser's thread model and have to build a dual-thread model by themselves.
So what is the dual-thread model of a small program?
The best way to understand a new concept or technology is to give it a reference. Therefore, to understand the threading model of a small program, you must first have a certain understanding of the browser's threading model.
Perhaps every front-end engineer was asked more than once by the interviewer when he first entered the industry, "How do you understand the single thread of the front-end?", because the front-end core The JavaScript language, one of the skills, is single-threaded. Fully understanding and mastering the operation of JS single-thread is the most basic requirement for a front-end engineer. But there is a misunderstanding that many beginners easily fall into: mistakenly understanding "JavaScript single-threaded" as "browser single-threaded".
In fact, the internal architecture of the browser is very complex, but it uses a mutually exclusive and blocking management model to handle the GUI rendering thread and JavaScript logic script thread, which makes some developers confused. misunderstood.
Take the Chrome browser as an example, click the settings button in the upper right corner and then enter "More Tools"->"Task Manager" and you will see a pop-up window like this:
You can see that Chrome has opened multiple processes, including browser processes, network processes, GPU processes, etc. These are all common processes. Please note, there are two tab processes in the picture above. Chrome opens an independent rendering process (Renderer Process) for each tab page, and the resources between each process (CPU, memory, etc.) and behaviors (UI, logic, etc.) are not shared with each other, so even if one tab crashes, it will not affect other tabs.
In each tab process, the browser will hand over different tasks to the corresponding threads. For example, the GUI rendering thread is responsible for rendering HTML into a visual UI; the JavaScript engine thread is responsible for parsing and running JavaScript code. Logic; the timing trigger thread is responsible for processing setTimeout/setInterval timers, etc.
One more thing, there is a place where it is easy to get confused. In fact, setTimeout/setInterval is not part of the JavaScript language, but the runtime (originally the browser, and later Node.js also supports it ) provides the capabilities.
The GUI rendering thread and the JavaScript engine thread are mutually exclusive. JavaScript will block the rendering of the UI during execution. Even if the script execution time is too long, the page will be unresponsive for a long time and then crash. This is exactly This mutually exclusive and blocking thread management method between the GUI rendering thread and the JavaScript engine thread makes some front-end developers think that the browser is single-threaded.
So why is JavaScript designed to be single-threaded?
The founder of JavaScript only took 10 days to create this language. His original idea was to provide some simple script logic in the browser to handle user interaction, DOM operations, etc., so Two points must be followed in design:
The syntax is simple;
The operating mechanism is simple.
In terms of syntax, JavaScript borrows from Java, but removes many complex settings, such as type declarations, module systems (added later), etc.
In terms of running mechanism, JavaScript does not provide multi-threading capabilities like Java. The main reason is to avoid UI conflicts caused by multi-threaded DOM operations. For example, if multiple threads operate the same DOM at the same time, how should the browser determine which thread is used to produce the final UI effect? This is a classic thread safety (also known as thread synchronization) problem. There are many solutions in the field of multi-threaded programming, such as adding lock mechanisms, but this brings more complexity, unlike the simple and easy-to-use design of JavaScript. It goes against the original intention.
This also explains why the GUI rendering thread and the JavaScript engine thread are mutually exclusive: JavaScript code has the permission to modify the DOM.
When JavaScript code is executed, the GUI rendering thread will be suspended and waits for the JavaScript engine thread to be idle before being executed to avoid unnecessary rendering pressure caused by repeated modification of the DOM by JavaScript during rendering. Using a mutually exclusive mode to wait for the JavaScript code to complete execution can ensure that rendering is the final execution result. Therefore, the browser's idle time has also become one of the important indicators for measuring website performance. The idle time mostly indicates that JavaScript logic is not intensive and the frequency of DOM changes is low. In this case, the browser can respond to user interactions more quickly and smoothly. The behavior is as shown below:
#React Fiber uses idle time to process sharding tasks.
Later, HTML5 introduced Web Worker, which provides the ability to execute JavaScript code in multiple threads. However, unlike other programming languages, the Worker thread is not parallel to the main thread, but a main thread. Slave (Master-Slave) multi-threading model.
The JavaScript code within the Worker cannot operate the DOM and can be understood as thread-safe. Remember this, this is an important basis for the small program dual-thread model discussed later.
So why doesn’t WeChat applet directly use the browser’s threading model? This requires comparing the differences between mini programs and web websites from both product and technical perspectives.
When I first came into contact with mini program development, I often “disliked” its weakened capabilities compared to the Web, and how simple it was compared to Vue. Excessive grammar, etc. At that time, I almost felt that mini programs were WeChat’s technological monopoly relying on its huge number of users.
However, with the continuous in-depth understanding of technology and products, my attitude towards mini programs has also changed, from "dislike" to admiration, because after fully understanding the product positioning of mini programs, I found that the dual-thread model is the optimal solution in product scenarios such as small programs. So what kind of product is the mini program?
The host of the mini program is WeChat, but the iteration of the mini program version is independent, and upgrades and updates do not depend on the host. This is the same as the Web website. In other words, mini programs inherit some of the advantages of the Web, but they are not the Web. Currently, Web-related technologies are quite comprehensive and can host some very large applications, such as 3D maps, games, etc.
The positioning of mini programs is to be small, beautiful, and go away after use. It does not pursue all the Web capabilities in WeChat, so it is definitely inferior to the Web in terms of capabilities. At the same time, it has some of the native capabilities provided by WeChat. Capabilities, such as native components, system level and WeChat ecosystem APIs, etc.
In addition, the relationship between "mini program-WeChat" is different from the relationship between "website-browser". The former is closer to each program case in online programming platforms such as CodePen and JSFiddler (referred to as platform in class) ( Referred to as the case) and the relationship between the platform.
From a technical perspective, one of the core considerations of the platform is to provide sufficient capabilities for the case, to ensure that the logic of the case will not endanger the security of the platform. Imagine if you could write a program on CodePen to obtain CodePen's private information, maybe CodePen would crash the next day and fire all the employees.
Under such a product tone, when technology selection is made, the next step is the work of architects and programmers.
Still taking CodePen as an example, if you were asked to design such a programming platform, what technology would you use? Maybe your first thought is to use iframe, because you can use all web capabilities within iframe. In fact, CodePen does use iframe to present the program effect, but it does not completely copy the input JavaScript code to the iframe for running. Instead, the code will go through a compilation process before being injected into the iframe. The starting point of this is mainly based on security considerations, eliminating some dangerous codes during the compilation process; secondly, this can also support more languages in the platform, such as typescript. Of course, there is also performance. Performance issues are a common issue with iframes, so I won’t go into details.
So, not only do you need to use iframe, but you also need to introduce an additional JavaScript compiler. CodePen must ensure that the JavaScript code in each case is thread-safe. The most basic thing is to prohibit the program from operating the DOM of the CodePen website. There are two ways to achieve this:
One is Web Worker;
The other is to use Shadow DOM.
Web Worker is thread-safe. The JavaScript code within the Worker cannot obtain the Window and Document objects, and therefore cannot operate the DOM. In addition, due to the thread safety feature of Worker, the code within the Worker will not block the outer GUI rendering thread during running, and the two can run in parallel.
Shadow DOM is part of the Web Components specification. Setting the mode of ShadowRoot to closed
will prevent the ShadowRoot node from being obtained, and thus the internal DOM cannot be manipulated.
Compared with the two, the compatibility of Shadow DOM is worse than that of Web Worker, and it is still far away from the date of large-scale use, so the Web Worker solution is more realistic.
This forms a simple two-thread model: the Worker thread is responsible for calculation, passing the results to the main thread through postMessage, and the main thread is responsible for rendering.
However, this model has serious performance problems. Web Worker is very resource-consuming. In addition to computing consumption, the communication process with the main thread also has a very serious impact on performance.
So is there a way to achieve the same thread safety as Web Worker, while taking into account performance and ensuring a good user experience? This is the main purpose of using the dual-thread model for WeChat applet.
Although programming platforms such as CodePen were used as an analogy earlier, the technical requirements of small programs and CodePen are not exactly the same. The main difference is that small programs do not It needs to support all HTML tags and only provide a limited number of UI components. According to the product positioning of the mini program, we can summarize the main technical requirements of the mini program as follows. (Any new technology or architecture is designed to solve specific problems, so it is necessary to understand the main technical requirements of the applet.)
Restrict UI component types to only allow declarations to be specified Several components of
The applet does not use native HTML tags when declaring components, but can only use several built-in basic components provided by WeChat. Of course, you can also customize components, but It is also achieved through the combination of built-in basic components.
Ensure logical thread safety and do not allow direct manipulation of UI components
The way the mini program updates the UI is similar to MVVM frameworks such as Vue/React. JavaScript code cannot directly operate the DOM (just for analogy, in fact there is no concept of DOM in the applet), but updates the UI asynchronously by updating the state (setState). In this process, VDOM and efficient diff algorithm will be used (this These two points are not what we want to discuss. You can search for relevant information after class).
Can be updated online and does not rely on WeChat
The host of the mini program is WeChat. If it is implemented using pure Native, then the version of the mini program will be updated You have to rely on WeChat and release the version together with WeChat code, which is definitely not possible. If it is a pure web implementation, security and performance will be difficult to guarantee.
Mini programs need to be able to host resources in the cloud like the Web and be updated independently; at the same time, they need to be able to ensure good enough security and performance. So in the end, the applet adopts a mixed architecture model: Use Webview to render the UI, and use independent threads similar to Web Workers to run logic. This is the dual-thread model.
Performance needs to be improved as much as possible to ensure user experience
The performance of the simple dual-thread model based on Web Worker mentioned earlier is very high The big problem is that the dual-thread model of the mini program does not use Web Worker sub-threads, but an independent "main thread", which can ensure relatively good performance.
The dual threads of the applet refer to the rendering thread and the logic thread. These two threads are responsible for rendering the UI and executing JavaScript code respectively. work. As shown in the figure below:
#The rendering thread uses Webview to render the UI. Webview is a complete browser-like operating environment with the ability to run JavaScript. However, the applet does not put the logic script into Webview to run, but separates the logic layer into a thread parallel to Webview, using the client to provide The JavaScript engine runs the code, iOS's JavaScriptCore, Android's JsCore environment and the nwjs IDE tool provided by Tencent's X5 kernel.
The logical thread is a sandbox environment that can only run JavaScript. It does not provide APIs related to DOM operations, so it cannot directly operate the UI. It can only update the UI asynchronously by updating data through setData.
Event-driven communication method
Pay attention to the communication method between the rendering thread and the logic thread in the above figure. Different from Vue/React, the applet The communication between the rendering layer and the logic layer does not directly transfer data or events between the two, but is forwarded by Native as an intermediary.
The whole process is a typical event-driven model:
The rendering layer (also called the view layer) triggers specific events through interaction with the user. event;
The event is then passed to the logic layer;
The logic layer then passes a series of logic processing, data requests, and interfaces Calling and other actions will pass the processed data to the rendering layer;
The final rendering layer renders the data into a visual UI.
This data-driven UI model is now a more respected programming paradigm in the field of front-end programming. If you are a front-end developer with more than 5 years of development experience, then I believe that in the beginning There must be some discomfort when you come into contact with this model, because before this, JavaScript operation of DOM was almost an "industry rule". There are even many books, blogs and textbooks for getting started with the front end that start with DOM operation. , now it seems that these are indeed somewhat out of date.
On the one hand, this thread division mode that separates logic and rendering can ensure that the JavaScript code running in the logical thread sandbox is thread-safe. On the other hand, because the calculation amount of the rendering thread is very small, it ensures that the Quick response to user interaction behavior improves user experience.
In general, compared with the browser's thread model, the dual-thread model of the mini program solves or avoids the worrying performance of the Web Worker while achieving the same thread safety as the Web Worker. Improvements have been achieved from both the performance and security perspectives. It can be summarized that dual-thread mode is an improved architectural solution within the specific scenario of small programs that is limited by the browser's existing process and thread management model.
In my opinion, the core competency and competitiveness of programmers is not to fully understand the API of a certain language or framework, but to know the underlying principles of these languages and frameworks. For a small program developer, the solution when encountering technical problems at work is often based on the underlying principles (even more straightforwardly, when you are looking for a job interview, no one will ask you about the syntax of the small program ).
By understanding the background, design, and communication of the mini program's dual-thread model, I hope that everyone can have a deeper understanding of the underlying architecture of the mini program. It can also be used as a reference if there is a need for similar scenarios in subsequent work. Of course, understanding the dual-thread model of small programs is not the only goal. This knowledge can provide some inspiration for daily development work to a certain extent, mainly in terms of performance:
In ensuring functionality Try to use a UI with a simple structure under the premise;
Try to reduce the complexity of JavaScript logic;
Try to reduce the frequency and portability of setData calls volume of data.
For more programming-related knowledge, please visit: Programming Video! !
The above is the detailed content of In-depth analysis of the dual-thread model in mini programs. For more information, please follow other related articles on the PHP Chinese website!