Mobile Development 19 min read

Quantifying and Improving Mobile App Performance: Metrics, Monitoring, and Optimization Practices at Ctrip

This article details Ctrip's mobile app performance improvement framework, introducing quantitative smoothness metrics, interactive load time measurement, Flutter and React Native monitoring techniques, and practical optimizations that reduced slow‑load rates from 42.9% to 8% while boosting overall smoothness to 80%.

Ctrip Technology
Ctrip Technology
Ctrip Technology
Quantifying and Improving Mobile App Performance: Metrics, Monitoring, and Optimization Practices at Ctrip

APP performance has always been a perpetual focus for the Ctrip hotel front‑end team. Two major challenges were identified: the lack of sustained performance after iterative releases and the absence of scientific, quantitative measurement methods. Quoting Peter Drucker, "If you can’t measure it, you can’t improve it," the team set out to define metrics, governance, and monitoring to continuously improve user experience.

The concept of smoothness (流畅度) was introduced as a composite user‑experience indicator covering stability, speed, and quality. The smoothness rate is calculated as (sample - unsmooth factors) / sample , where the sample size equals page PV + secondary loads . Unsmooth factors include white screens, crashes, slow loads, freezes, and other error events.

Interactive load time (TTI) is defined as the sum of local rendering time and network service response time: TTI = local render time + network load time . The team described collection principles for both Flutter and Ctrip React Native pages.

Flutter TTI collection traverses the Element tree from the root until a non‑empty Text component is found within a predefined scanning window. The framework provides the interface voidvisitChildElements(ElementVisitor visitor) for element traversal.

Ctrip React Native TTI collection scans the native view hierarchy for Text controls, excluding static header/footer regions; if more than one Text node is detected, the page is considered TTI‑detected.

Rendering lag and frame‑rate were discussed using Google’s definition: a frame must render within 16 ms to achieve 60 fps. Two lag categories were highlighted—slow rendering (over 50% of frames > 16 ms) and frame freeze (single frame > 700 ms). FPS alone does not guarantee smoothness.

Lag quantification leverages Flutter’s FrameTiming data (vsyncStart, buildStart, buildFinish, rasterStart, rasterFinish). The total span is computed as totalSpan = rasterFinish - vsyncStart . Thresholds: totalSpan > 700 ms indicates severe freeze; > 30 frames with totalSpan > 16 ms within one second indicates slow rendering.

The smoothness monitoring system consists of three stages: current‑state analysis and optimization direction discovery, data‑completion for monitoring metrics, and multi‑dimensional monitoring with alerting. Dashboards provide macro‑level views of smoothness progress, while detailed tables expose factor‑level impacts, version trends, and device distributions.

In practice, page‑load speed optimizations reduced the hotel‑booking flow’s slow‑load rate from 42.90% to 8.05% through data pre‑fetching, caching strategies, and careful timing to avoid stale price information.

Flutter service‑channel optimization eliminated unnecessary serialization steps. Previously the data flow involved four steps: PB deserialization, Response → JsonString encoding, JsonString transmission via the Flutter channel, and JsonString → Response decoding. After refactoring, raw PB streams are sent directly to Flutter, where they are deserialized, dramatically shortening the pipeline and improving load performance.

Lag analysis uses Flutter’s Performance Overlay to differentiate CPU‑side (Dart code) and GPU‑side (rendering) bottlenecks. Red vertical bars indicate frames exceeding the 16 ms budget. GPU issues often stem from complex off‑screen layers, while CPU issues arise from heavy build logic or synchronous I/O.

GPU‑related problems are mitigated by enabling checkerboardOffscreenLayers to detect costly layer compositing and checkerboardRasterCacheImages to spot uncached images. Wrapping expensive widgets in RepaintBoundary allows Flutter to cache them, reducing redundant rasterization.

Ctrip React Native (CRN) page optimizations focused on action consolidation: static data avoids actions, actions with identical triggers are merged, non‑essential data is lazy‑loaded, and multi‑layer actions are combined. This reduced the number of dispatched actions to only initialization, main service response, and subsequent sub‑service actions.

Component re‑render governance involved splitting large components, using PureComponent for low‑impact parts, and implementing shouldComponentUpdate with manual prop comparison for critical components. The open‑source tool why‑did‑you‑render was employed to pinpoint unnecessary re‑renders.

Overall, the smoothness rate rose from an initial 47% to about 80%, slow‑load rate dropped from ~45% to 8%, and white‑screen rate fell from 1.9% to 0.3%. The team emphasized a data‑driven mindset, continuous monitoring, and iterative engineering upgrades across Flutter architecture, data transmission, and pre‑loading mechanisms.

fluttermobilemonitoringperformanceoptimizationReactNative
Ctrip Technology
Written by

Ctrip Technology

Official Ctrip Technology account, sharing and discussing growth.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.