This document aims to help developers master how to accurately locate each execution stage in a Trace, thereby enabling effective analysis of specific performance issues.
Frontend pages can flag Pipeline for key components. When the component finishes rendering on screen, the Timing Track in Trace generates a bubble at the corresponding timestamp to mark the key stage.
A Lynx page generally has two render types: first-frame rendering and update rendering. Internally, the Lynx SDK produces LoadBundleEntry and PipelineEntry to describe stage durations in each process.
Click a bubble to open a details panel showing the sub-stage timeline and the duration of each sub-stage in the render process.
The following sections detail both render types and their constituent stages, including the corresponding Trace event names, so you can locate and troubleshoot issues via Trace events.
First-frame rendering primarily consists of LoadBundle and Paint:
This stage corresponds to Timing::Mark.loadBundleStart and Timing::Mark.loadBundleEnd in Trace. It mainly parses the bundle and performs the initial screen render. It can be broken down into six sub-stages:
This stage corresponds to Timing::Mark.parseStart and Timing::Mark.parseEnd in Trace. It parses the binary bundle into in-memory data structures. The bundle contains a header and multiple sections; the JS source section runs on the background thread, mapped to Timing::Mark.loadBackgroundStart and Timing::Mark.loadBackgroundEnd in Trace.
This stage corresponds to Timing::Mark.mtsRenderStart and Timing::Mark.mtsRenderEnd in Trace. It executes Main Thread Script (MTS) to build the Element Tree.
This stage corresponds to Timing::Mark.resolveStart and Timing::Mark.resolveEnd in Trace. It traverses the element tree, computes a layout node tree from node attributes and styles, and generates UI Paint OP.
This stage corresponds to Timing::Mark.layoutStart and Timing::Mark.layoutEnd in Trace. It traverses the layout node tree produced during Resolve, computes node positions and sizes, and generates UI Layout OP.
This stage corresponds to Timing::Mark.paintingUiOperationExecuteStart and Timing::Mark.paintingUiOperationExecuteEnd in Trace. It executes the UI Paint OP generated during Resolve.
This stage corresponds to Timing::Mark.layoutUiOperationExecuteStart and Timing::Mark.layoutUiOperationExecuteEnd in Trace. It executes the UI Layout OP generated during Layout.
The system drawing stage measures, lays out, and paints the platform UI tree. The end of painting maps to Timing::Mark.paintEnd in Trace.
Update renders are primarily driven by the background thread to update and draw the UI tree. The main difference from first-frame rendering lies in Framework Rendering. Using ReactLynx 3 as an example, we highlight the differing parts:
This stage corresponds to Timing::MarkFrameWorkTiming.diffVdomStart and Timing::MarkFrameWorkTiming.diffVdomEnd in Trace. It performs component diff on the background thread.
This stage corresponds to Timing::MarkFrameWorkTiming.packChangesStart and Timing::MarkFrameWorkTiming.packChangesEnd in Trace. It serializes diff results and sends them to the main thread.
This stage corresponds to Timing::MarkFrameWorkTiming.parseChangesStart and Timing::MarkFrameWorkTiming.parseChangesEnd in Trace. It parses the serialized data on the main thread.
This stage corresponds to Timing::MarkFrameWorkTiming.patchChangesStart and Timing::MarkFrameWorkTiming.patchChangesEnd in Trace. It applies the diff results on the main thread and updates the Element Tree.
Subsequent render stages are similar to the first-frame process: Resolve, Layout, Paint UI OP Execute, Layout UI OP Execute, and Paint.