Tối ưu App Launch trong iOS
Qua bài này các bạn sẽ nắm được:
- App Launch và các kiểu launch.
- Các phase trong launch app và cách optimize.
- Môi trường đo thời gian app launch.
- Sử dụng Instrument để phân tích ứng dụng.
- Thu thập thời gian app launch hằng ngày.
App Launch và các kiểu launch
Theo apple, app launch được định nghĩa như sau:
App launch is a user experience interruption.
Hiểu đơn giản, App launch là trải nghiệm đầu tiên người dùng tiếp xúc với ứng dụng, là khoảng thời gian app block tương tác người dùng từ khi mở app đến khi hiển thị những content đầu tiên và người dùng có thể tương tác.
Tại sao phải quan tâm đến Launch?
- Ấn tượng đầu tiên rất quan trọng và Apple luôn chú tâm tới trải nghiệm người dùng, đây là điều tạo ra sự hài lòng trong hệ sinh thái Apple mà ai đã trải nghiệm thì không thể tách ra được.
- Đối với developer, thời gian launch đại diện cho performance tổng thể của ứng dụng, launch càng nhanh chứng tỏ tổ chức source code base của bạn càng tốt. Apple cho ra các thiết bị và version iOS mới hàng năm, vì vậy bạn cần đảm bảo trải nghiệm launch tuyệt vời trên tất cả các thiết bị, với tất cả version iOS mà app có thể support.
- Trong quá trình launch, thiết bị tốn rất nhiều tài nguyên, từ CPU, RAM để khởi tạo đưa chương trình vào bộ nhớ, nhiệt độ máy sẽ cao lên đột ngột và ảnh hưởng tiêu cực tới pin. Giảm thời gian launch là kéo dài vòng đời của pin. Đây 1 trong các yếu tố mà người dùng quyết định tiếp tục trải nghiệm app của bạn hay gỡ nó.
Các kiểu launch app
Apple minh hoạ 3 kiểu phản ánh thời gian launch rất hay như hình dưới, .
- Cold launch: sau khi ứng dụng được khởi động lại, ứng dụng chưa được tải vào bộ nhớ, hoặc ứng dụng chưa được launch trong 1 thời gian dài. Cold launch chạy chậm nhất, may mắn rằng nó chỉ chạy 1 lần, Apple tối ưu bộ nhớ trên RAM và từ lần khởi động tiếp theo sẽ nhanh hơn rất nhiều, và khi đó có thể sẽ vào trạng thái warm launch.
- Warm launch: ngay sau khi ứng dụng vừa được terminate, ứng dụng còn 1 phần chương trình được load trong bộ nhớ. Khi này tốc độ launch được cải thiện hơn 1 chút.
- Resume launch: sau khi người dùng quay trở lại sử dụng ứng dụng của bạn đang trong nền (background), ứng dụng đã được khởi chạy từ trước đó, vì thế tốc độ launch là rất nhanh.
Hệ điều hành tự tối ưu tốc độ launch ở trạng thái warm và resume, vì thế chúng ta chỉ tập trung vào cold launch, là kiểu mất nhiều thời gian nhất.
Apple công bố thời gian launch được coi là "delightful" ở sự kiện WWDC 2019: 400 milliseconds. Con số khắt khe này sẽ khiến anh em developer phải đau đầu 😵. Mình đã đọc các blog của các tác giả khác, con số này không phải là stardard chung cho tất cả các ứng dụng, còn tuỳ thuộc lĩnh vực của ứng dụng là gì. Nên tốt nhất bạn có thể so sánh với đối thủ cạnh tranh trong cùng lĩnh vực nhé.
Quay trở lại con số 400ms đối với cold launch, sẽ có 3 phần chính:
- 100ms đầu tiên, hệ thống sẽ thực hiện các công việc cần thiết để khởi chạy ứng dụng của bạn.
- 300ms tiếp theo dành cho việc tạo UI, content và vẽ các frame đầu tiên để hiển thị. Lúc này không cần hiển thị đầy đủ content, nên hiển thị placeholder và load dữ liệu bất đồng bộ, để các task nặng về phía sau.
- 400ms trở đi, ứng dụng kết thúc launch và có thể tương tác với người dùng. Lúc này sẽ tiếp tục tải content, thực hiện các task background để thay thế content vào các chỗ placeholder trong khi người dùng vẫn có thể tương tác với ứng dụng. VD: nhập textField vào ô search, chọn category hay chuyển tabbar, ...
Dưới đây là ví dụ tiêu biểu launch app Map của Apple: Trải nghiệm launch app tuyệt vời phải không.
Các phase trong launch app và cách optimize
Quá trình launch app có 3 phase chính:
1. Phase 1
Là khối màu tím, system thực hiện việc các việc khởi tạo cần thiết trước khi hàm main() run.
-
1.1. System Interface: hệ thống dydl (Dynamic link editor) chịu trách nhiệm tải các shared library và framework vào ứng dụng ở thời điểm run time, cached lại các dependencies để tăng tốc độ launch ở trạng thái "warm".
Từ iOS 13, apple giới thiệu dynamic linker mới được tối ưu hoá để tăng tốc độ trong phase này, tất nhiên developer có thể optimize phase này với các recommendation sau
- Xoá các thư viện không sử dụng. Mỗi framework sẽ tốn "cost" để liên kết và tăng thời gian launch.
- Hạn chế dùng thư viện nhất có thể, bạn có thể copy code của library bạn cần dùng.
- Không tải các dynamic library như DLOpen hoặc NSBundleLoad.
- Tải thư viện vào ứng dụng tại thời điểm build time thay vì run time. Sử dụng linh hoạt static library thay thế cho dynamic library.
Sau khi liên kết động tới các thư viện, libSystemInit sẽ thiết lập môi trường runtime, khởi tạo các thread, đầu vào ra I/O và vùng bộ nhớ, ... đảm bảo rằng tất cả system service và configuration được khởi tạo đúng cách. Hãy để system lo, developer không cần để ý tới phần này.
-
1.2.Runtime Init: Hệ thống khởi tạo mã nguồn Objective-C và Swift để bắt đầu động tới mã nguồn của bạn, hệ thống sẽ init các khai báo static trong source code và library. Để giảm thiểu thiểu tác động tới phần này, dưới đây là các recommendation:
- Tránh khởi tạo static nhất có thể.
- Nếu bắt buộc phải dùng khởi tạo static thì nên:
- Không code logic ở hàm init().
- Không sử dụng khởi tạo instance, thay thế bằng khởi tạo method(). Vì các instant sẽ được load và init ngay khi class được khởi tạo, sẽ chạy trong quá trình launch, còn static method sẽ thực sự được gọi khi nó được gọi từ nơi khác.
2. Phase 2
Là khối màu xanh lá cây, ứng dụng sẽ bắt đầu thực hiện hàm main(), kết thúc việc launch và vẽ những frame UI đầu tiên.
-
2.1. UIKit Init: Hệ thống sẽ khởi tạo UIApplication và UIApplicationDelegate. Hầu như phase này phụ thuộc vào iOS system, và sẽ bị ảnh hưởng nếu Developer override hoặc custom UIApplication hoặc UIApplicationDelegate.
-
2.2. Application Init: Ứng dụng sẽ gọi tới class AppDelegate, đây là nơi Developer có ảnh hưởng nhiều nhất.
Đối với ứng dụng không dùng UIScreen, các hàm trong AppDelegate sẽ được gọi tới: willFinishLaunchingwithOptions, didFinishLaunchingwithOptions, applicationDidBecomeActive. Dưới đây là recommendation để tối ưu chạy phase này:
- Chỉ nên thực hiện khởi tạo viewController, các tác vụ khác nên được thực hiện async hoặc thực hiện sau, tránh block main thread tại phase này.
-
2.3. Initial Frame Render: Đây là phase tạo các view, layout, content và vẽ lên hiển thị cho người dùng, để tạo trải nghiệm tốt, dưới đây là recommendation:
- Khởi tạo lazy đối với các layout không hiển thị ngay lập tức hoặc xuất hiện có điều kiện để giảm thời gian launch.
- Hiển thị placeholder và để các tác vụ load content async hoặc delay để không chặn tương tác người dùng.
- Thực hiện các task nặng ở background thread, set QoS hợp lý để không block main thread.
- Nếu quá trình chuẩn bị data hiển thị cho màn hình đầu tiên lâu, có thể thêm màn hình Splash với animation để người dùng không thấy nhàm chán.
3. Phase 3
Là khối khối màu xanh dương, ứng dụng ở trạng thái foreground và nhận tương tác với người dùng. Khi này ứng dụng đã hiển thị, không nhất thiết là phải đầy đủ content mà hãy hiển thị placeholder nếu tác vụ load content mất thời gian, điều quan trọng nhất là ứng dụng của bạn đã có thể tương tác với người dùng. Bạn có thể tiếp tục áp dụng các recommendation ở phase 2.3 để optimize performance nhé.
Môi trường đo thời gian app launch
Tại bất kỳ thời điểm, thiết bị iOS có thể ở trạng thái và điều kiện khác nhau, và điều này tạo ra sự khác biệt lớn trong mỗi quá trình launch app. Vì vậy, khi chúng ta phân tích và so sánh kết quả launch, điều quan trọng là phải đảm bảo rằng chúng ta đang so sánh trong cùng 1 điều kiện môi trường.
- Kill tất cả các app khác đang chạy, kiểm tra đường truyền initernet là ổn định giống tiêu chuẩn bạn đặt ra, tắt các chức năng bạn không cần dùng tới như Bluetooth, Wi-Fi, Cellular, Personal Hotpot, VPN, Air drop.
- Reset thiết bị, và để yên trong vòng từ 2-3 phút.
- Enable Airplane mode, hoặc sử dụng môi trường Internet mock để tạo sự ổn định.
- Không thay đổi tài khoản ICloud trong tất cả bài test, tốt nhất là không đăng nhập ICloud.
- Build bản release của ứng dụng.
- Có thể đo launch app/cold để thấy sự khác biệt, tuỳ mục đích bạn hướng tới.
Tổng kết phần 1
Bài viết đến đây là dài rồi, nội dung còn lại (Sử dụng Instrument để profile App launch) sẽ ở phần 2 nhé. Cùng tổng kết lại những gì bạn đã nắm được nhé.
- App launch là trải nghiệm đầu tiên của người dùng với app, vì vậy hãy làm nó thật đáng nhớ.
- Các phase trong app launch, những phần nào developer can thiệp được để tăng tốc độ launch.
- Recommendations để tối ưu launch.
- Thiết lập môi trường để đo launch app.
Tham khảo
WWDC 2019: https://developer.apple.com/videos/play/wwdc2019/423
All rights reserved