Author: Doodle – Changsheng

Come doodle work: job.tuya.com/


A lot of people just contact small program, often “dislike” it compared with the Web castration weakened ability, compared with Vue simple to excessive syntax, and even some people will think small program is to rely on their own strong ecology and users in the technology monopoly! But in fact, the root of this problem is that compared with Web sites, wechat small programs need to consider security, performance and other factors, because it needs to take into account the small programs written by developers will not have security risks to the host wechat, but also have as close to the original user experience as possible. The two-thread model of small programs is also considered for these reasons. So what is the applets two-threaded model? We can understand this from the familiar browser thread model.

Browser process

JavaScript is single-threaded, but the browser is not single-threaded. In fact, the internal architecture of the browser is complex, but the GUI rendering thread and the JavaScript logical script thread use mutual, blocking management mode. Take Chrome, our most common browser, for example. Click the Settings button and go to “More Tools” -> “Task Manager” to see the browser’s multiple threads:

As you can see from the figure, Chrome has multiple processes, including the browser process, GPU process, web service process and other common processes, as well as two TAB page processes. Chrome opens a separate rendering process for each TAB page, and each process does not share resources and behaviors. Even if one TAB crashes, the other tabs will not be affected. In each TAB process, the browser hands off different tasks to the corresponding thread. For example, the GUI rendering thread is responsible for rendering HTML into a visual UI. JavaScript engine threads are responsible for parsing and running JavaScript code logic; The timer trigger thread is responsible for handling setTimeout/setInterval timers. The GUI rendering process and JavaScript engine threads are mutually exclusive, JavaScript will block UI rendering during execution, and even the script execution may take too long and crash due to the page being unresponsive for a long time. It is also because of the mutually exclusive, blocking thread management between GUI renderers and JavaScript engine threads that some people think browsers are single-threaded.

Why JavaScript is single threaded

From the perspective of running mechanism, JavaScript is designed as a single thread mainly to avoid UI conflicts caused by multi-thread DOM manipulation. If multiple threads operate the same DOM, it is difficult for the browser to determine which thread is used for the final UI effect. Although locking mechanism similar to Java can be used to deal with it, But this greatly increases the complexity of JavaScript. This also explains why the GUI rendering thread and the JavaScript engine are mutually exclusive. JavaScript has the DOM modification rights, so it’s easy to get into a fight and cause the page to freeze.

From the point of view of design, JavaScript language was designed to be a “simple” language, without rich language features, nor the ambition of a unified, let alone “all-conquering” virtual machine engine, is really “small and simple”. From this point of view, JavaScript also can’t design multithreading, after all, multithreading programming alone can be taught as a course.

When JavaScript code is executed, the GUI rendering thread is suspended until the JavaScript engine thread is idle, so as not to have the DOM repeatedly modified by JavaScript during rendering cause unnecessary rendering stress. Using a mutually exclusive mode to wait for the JavaScript code to finish executing ensures that the page is rendered as a result of the final execution. Therefore, browser space time (LDLE) has also become one of the indicators to measure website performance. More idle time means that JavaScript logic is not dense and DOM change frequency is low, so the browser can respond to user interaction more quickly and smoothly. Below is the free time on doodle’s official website:

But, again, HTML5 introduces Web workers, provides the ability of multithreading to execute JavaScript codes, allows the main thread to create Worker threads, assign some tasks to Worker threads to execute, and wait for Worker threads to complete computing tasks. The result is then returned to the main thread. Different from Java and other back-end programming languages, Worker threads are not in the same position as the main thread, but a master-slave multithreading model. In addition, once Worker threads are successfully created, they will always run and will not be interrupted by actions on the main thread. Although this helps to respond to the communication of the main thread at any time, However, it also causes Worker to consume resources.

Why applets don’t use the browser’s threading model

From the above, in fact, applets can also use similar Worker threads to run business logic and use webView to render pages. Theoretically, this is no problem, but it is problematic to analyze the following points of applets.

From the perspective of a platform, the core consideration of a platform is to ensure sufficient security of its own platform on the premise of providing external capabilities. The Doodle IoT platform, for example, provides the developer with the ability to control the device externally, but must ensure that their own platform and data are secure. The same is true for wechat, where applets run on the host, but cannot have full Web capabilities, or else dangerous code (such as eval) that is out of wechat’s control is executed.

From the perspective of performance, the communication content between the main thread of the browser and the Worker can be text or object. But this communication is passing values, not addresses, regardless of whether you are passing the base data type or the reference data type. The advantage of this is that the Worker’s modification of communication content will not affect the main thread, while the disadvantage is that the efficiency will be affected. If I want to send a 100MB message, the main thread needs to make a copy of the original file and send the value to the Worker thread through postMessage, thus the overall transmission efficiency will be greatly reduced. However, if a two-thread model is designed, the two threads are parallel and both are independent main threads, and the value transmission is done by Native. Besides, because the rendering process has a single role, that is, only responsible for rendering, there will be no logical code, and the overall architecture and performance will be clearer.

From the perspective of development, dom nodes cannot be obtained from Worker threads, but in some development situations, DOM nodes still need to be obtained and some operations need to be performed, so workers are not competent. In the logical process of small programs, although Tencent tries to prevent us from obtaining nodes, However, there are still interfaces to asynchronously obtain node information and perform some special operations.

From these points of view, the two-threaded model of applets is pretty clear. The dual threading of the applet refers to the rendering thread and the logic thread, which take care of UI rendering and JavaScript code execution, respectively. As shown in the figure below

The render thread uses the Webview to render the UI. The logic layer is an independent thread parallel to WebView, using JavaScript engine provided by the client to run the code, ios platform is used by JavaScriptCore, Android is Tencent X5 kernel JsCore environment and IDE tool Nw.js. Do render threads and logic threads communicate via Native, in an event-driven way?

Two – threaded model communication

The two-thread communication of the applet is not to directly transfer data or events between the rendering thread and the logical thread, but to use Native as a medium for forwarding. The whole process is a typical event-driven mode:

  • The render layer triggers specific events by interacting with the user;
  • Events are passed to the logical layer through Native
  • The logical layer receives and triggers an event, and passes the processed data to the rendering layer through a series of logical processing, data request, interface call and other work
  • The render layer renders data as a visual UI

conclusion

Compared with the dual-thread model of the browser, the dual-thread model of the applet solves the performance problem of Web Worker and also realizes the same thread safety as Web Worker, which has been improved from the perspectives of performance and safety. Is limited by the browser’s existing process and thread management mode, in the small program scenario an improved architecture solution. From the understanding of the two-thread model of small programs, there is also a certain enlightenment for our development work, such as if we want to improve the performance of small programs, we need to ensure the function of the premise of using simple UI, as far as possible to reduce the complexity of JavaScript logic, reduce the execution time, Minimize the frequency of setData calls and the volume of data carried.


Come doodle work: job.tuya.com/