Cấu hình cơ sở là danh sách các lớp và phương thức có trong một APK mà Android Runtime (ART) sử dụng trong quá trình cài đặt để tổng hợp trước các đường dẫn quan trọng đến mã máy. Đây là một phương thức tối ưu hoá theo cấu hình (PGO) cho phép ứng dụng tối ưu hoá quá trình khởi động, giảm hiện tượng giật và cải thiện hiệu suất cho người dùng cuối.
Cách hoạt động của Cấu hình cơ sở
Các quy tắc cấu hình được biến dịch thành dạng nhị phân trong APK, trong assets/dexopt/baseline.prof
.
Trong quá trình cài đặt, ART thực hiện việc tổng hợp các phương thức trước thời gian (AOT) trong cấu hình, nhờ đó các phương thức đó được thực thi nhanh hơn. Nếu cấu hình chứa các phương thức dùng khi chạy ứng dụng hoặc trong quá trình kết xuất khung hình, thì người dùng sẽ có thời gian khởi chạy nhanh hơn và/hoặc giảm hiện tượng giật.
Trong khi phát triển ứng dụng hoặc thư viện, hãy cân nhắc xác định Cấu hình cơ sở để bao gồm các đường dẫn nóng cụ thể trong các hành trình trọng yếu của người dùng, nơi mà thời gian kết xuất hoặc độ trễ là thành phần quan trọng, chẳng hạn như khởi động, chuyển đổi hoặc cuộn.
Sau đó, Cấu hình cơ sở sẽ được gửi trực tiếp cho người dùng (thông qua Google Play) cùng với APK, như trong hình 1:
Lý do sử dụng Cấu hình cơ sở
Thời gian khởi động là một thành phần quan trọng để cải thiện mức độ tương tác của người dùng với ứng dụng của bạn. Việc tăng tốc độ và khả năng phản hồi của ứng dụng sẽ mang lại nhiều người dùng hoạt động hằng ngày hơn và tỷ lệ truy cập trung bình của người dùng cũ cao hơn.
Cấu hình đám mây cũng tối ưu hoá các lượt tương tác này, nhưng chỉ dành cho người dùng một ngày trở lên sau khi bản cập nhật được phát hành và không hỗ trợ Android 7 (API 24) cho đến Android 8 (API 26).
Hành vi tổng hợp trên các phiên bản Android
Các phiên bản Android Platform đã sử dụng các phương pháp tổng hợp ứng dụng khác nhau, mỗi phương pháp đều có sự đánh đổi hiệu suất tương ứng. Cấu hình cơ sở cải thiện theo các phương thức tổng hợp trước đó bằng cách cung cấp một cấu hình cho tất cả các lượt cài đặt.
Phiên bản Android | Phương pháp tổng hợp | Phương pháp tối ưu hoá |
---|---|---|
Android 5 (API cấp 21) tới Android 6 (API cấp 23) | AOT đầy đủ | Toàn bộ ứng dụng được tối ưu hoá trong quá trình cài đặt, dẫn đến thời gian chờ sử dụng ứng dụng lâu, tăng mức sử dụng RAM và dung lượng ổ đĩa cùng với thời gian tải mã lâu hơn từ ổ đĩa, có thể làm tăng thời gian khởi động nguội. |
Android 7 (API cấp 24) tới Android 8.1 (API cấp 27) | AOT một phần (Cấu hình cơ sở) | Cấu hình cơ sở được androidx.profileinstaller cài đặt trong lần chạy đầu tiên, khi mô-đun ứng dụng xác định phần phụ thuộc này. ART có thể cải thiện điều này hơn nữa bằng cách thêm các quy tắc cấu hình khác trong quá trình ứng dụng sử dụng và tổng hợp những quy tắc này khi thiết bị ở trạng thái rảnh. Cách này sẽ tối ưu hoá dung lượng ổ đĩa và thời gian tải mã từ ổ đĩa, từ đó giảm thời gian chờ xử lý ứng dụng. |
Android 9 (API cấp 28) trở lên | AOT một phần (Cấu hình cơ sở + Cấu hình đám mây) | Play sử dụng Cấu hình cơ sở trong quá trình cài đặt ứng dụng để tối ưu hoá APK và cấu hình đám mây (nếu có). Sau khi cài đặt, cấu hình ART được tải lên Play và tổng hợp, sau đó được cung cấp dưới dạng Cấu hình đám mây cho những người dùng khác khi họ cài đặt/cập nhật ứng dụng. |
Tạo cấu hình cơ sở
Tự động tạo quy tắc cấu hình bằng BaselineProfileRule
Là một nhà phát triển ứng dụng, bạn có thể tự động tạo cấu hình cho mọi bản phát hành ứng dụng bằng cách sử dụng thư viện Jetpack Macrobenchmark.
Cách tạo cấu hình cơ sở bằng thư viện Macrobenchmark:
Hãy thêm phần phụ thuộc vào thư viện ProfileInstaller trong
build.gradle
của ứng dụng để bật tính năng tổng hợp Cấu hình cơ sở cục bộ và trên Cửa hàng Play. Đây là cách duy nhất để tải không qua cửa hàng một Cấu hình cơ sở ở phạm vi cục bộ.dependencies { implementation("androidx.profileinstaller:profileinstaller:1.2.0-beta01") }
Thiết lập mô-đun Macrobenchmark trong dự án Gradle của bạn.
Xác định thử nghiệm mới có tên là
BaselineProfileGenerator
giống như:@ExperimentalBaselineProfilesApi @RunWith(AndroidJUnit4::class) class BaselineProfileGenerator { @get:Rule val baselineProfileRule = BaselineProfileRule() @Test fun startup() = baselineProfileRule.collectBaselineProfile(packageName = "com.example.app") { pressHome() // This block defines the app's critical user journey. Here we are interested in // optimizing for app startup. But you can also navigate and scroll // through your most important UI. startActivityAndWait() } }
Kết nối một trình mô phỏng
userdebug
Dự án nguồn mở Android (AOSP) đã bị can thiệp vào hệ thống chạy Android 9 trở lên.Chạy lệnh
adb root
từ thiết bị đầu cuối để đảm bảo dabonemon đang chạy với các quyền gốc.Chạy thử nghiệm và đợi hoàn thành.
Tìm vị trí hồ sơ đã tạo trong logcat. Tìm thẻ nhật ký
Benchmark
.com.example.app D/Benchmark: Usable output directory: /storage/emulated/0/Android/media/com.example.app
# List the output baseline profile ls /storage/emulated/0/Android/media/com.example.app SampleStartupBenchmark_startup-baseline-prof.txt
Kéo tệp đã tạo từ thiết bị của bạn.
adb pull storage/emulated/0/Android/media/com.example.app/SampleStartupBenchmark_startup-baseline-prof.txt .
Đổi tên tệp đã tạo thành
baseline-prof.txt
rồi sao chép tệp đó vào thư mụcsrc/main
của mô-đun ứng dụng.
Xác định quy tắc cấu hình theo cách thủ công
Bạn có thể xác định quy tắc cấu hình theo cách thủ công trong ứng dụng hoặc mô-đun thư viện bằng cách tạo
tệp có tên baseline-prof.txt
nằm trong thư mục src/main
. Đây chính là thư mục chứa tệp AndroidManifest.xml
.
Tệp chỉ định một quy tắc trên mỗi dòng. Mỗi quy tắc thể hiện một mẫu cho các phương thức hoặc lớp trùng khớp trong ứng dụng hoặc thư viện mà bạn cần tối ưu hoá.
Cú pháp cho các quy tắc này là tập mẹ của định dạng cấu hình ART (HRF) mà người dùng có thể đọc được khi sử dụng adb shell profman --dump-classes-and-methods
. Cú pháp rất giống với
cú pháp cho phần mô tả và chữ ký, nhưng cũng cho phép ký tự đại diện đơn giản hoá quá trình viết quy tắc.
Các ví dụ sau đây hiển thị một số quy tắc của Cấu hình cơ sở có trong thư viện Jetpack Compose:
HSPLandroidx/compose/runtime/ComposerImpl;->updateValue(Ljava/lang/Object;)V
HSPLandroidx/compose/runtime/ComposerImpl;->updatedNodeCount(I)I
HLandroidx/compose/runtime/ComposerImpl;->validateNodeExpected()V
PLandroidx/compose/runtime/CompositionImpl;->applyChanges()V
HLandroidx/compose/runtime/ComposerKt;->findLocation(Ljava/util/List;I)I
Landroidx/compose/runtime/ComposerImpl;
Cú pháp quy tắc
Các quy tắc này dùng một trong 2 biểu mẫu để nhắm mục tiêu hoặc phương thức hoặc lớp:
[FLAGS][CLASS_DESCRIPTOR]->[METHOD_SIGNATURE]
Quy tắc lớp sử dụng mẫu sau:
[CLASS_DESCRIPTOR]
Cú pháp | Mô tả |
---|---|
FLAGS |
Cho biết một hoặc nhiều ký tự H , S và P để cho biết phương thức này có bị gắn cờ là Hot , Startup hay Post Startup liên quan đến loại khởi động. Phương thức có cờ H cho biết đây là phương pháp "nóng", tức là phương thức này được gọi nhiều lần trong suốt vòng đời ứng dụng. Phương thức có cờ S cho biết đây là phương thức gọi khi khởi động. Phương thức có cờ P cho biết đây là phương thức nóng không liên quan đến việc khởi động. Một lớp có trong tệp này cho biết rằng lớp này được dùng trong khi khởi động và cần được phân bổ trước trong vùng nhớ khối xếp để tránh chi phí tải lớp. Trình tổng hợp ART sử dụng nhiều chiến lược tối ưu hoá, chẳng hạn như tổng hợp AOT của các phương pháp này và thực hiện tối ưu hoá bố cục trong tệp AOT đã tạo. |
CLASS_DESCRIPTOR |
Phần mô tả cho lớp của phương pháp nhắm mục tiêu. Ví dụ: androidx.compose.runtime.SlotTable sẽ có phần mô tả là Landroidx/compose/runtime/SlotTable; . Lưu ý: L được thêm vào đây ở định dạng có thể thực thi Dalvik (DEX). |
METHOD_SIGNATURE |
Chữ ký của phương thức, bao gồm tên, loại thông số và các loại dữ liệu trả về của phương thức. Ví dụ: phương thức // LayoutNode.kt fun isPlaced():Boolean { // ... } trên LayoutNode có chữ ký isPlaced()Z . |
Những mẫu này có thể có ký tự đại diện để có một quy tắc bao gồm nhiều phương thức hoặc lớp. Để được hỗ trợ hướng dẫn khi viết bằng cú pháp quy tắc trong Android Studio, hãy xem trình bổ trợ Cấu hình cơ sở của Android.
Ví dụ về quy tắc ký tự đại diện có thể có dạng như sau:
HSPLandroidx/compose/ui/layout/**->**(**)**
Các loại được hỗ trợ trong quy tắc cấu hình cơ sở
Quy tắc cấu hình cơ sở hỗ trợ các loại sau. Để biết chi tiết về các loại này, hãy xem định dạng có thể thực thi Dalvik (DEX).
Nhân vật | Loại | Mô tả |
---|---|---|
B |
byte | Byte đã ký |
C |
ký tự | Điểm mã ký tự Unicode được mã hoá bằng UTF-16 |
D |
gấp đôi | Giá trị dấu phẩy động có độ chính xác gấp đôi |
F |
số thực dấu phẩy động | Giá trị dấu phẩy động có độ chính xác đơn |
I |
int | Số nguyên |
J |
dài | Số nguyên dài |
S |
ngắn | Ký tên ngắn |
V |
void | Void |
Z |
boolean | Đúng hay sai |
L (tên lớp) |
tham chiếu | Một bản sao tên lớp |
Ngoài ra, các thư viện có thể xác định các quy tắc sẽ được đóng gói trong cấu phần phần mềm AAR. Khi bạn tạo APK để bao gồm các cấu phần phần mềm này, các quy tắc sẽ được hợp nhất với nhau (tương tự như cách thực hiện hợp nhất tệp kê khai) và được tổng hợp thành một cấu hình ART nhị phân nhỏ gọn dành riêng cho APK.
ART tận dụng cấu hình này khi APK được sử dụng trên các thiết bị để AOT tổng hợp một nhóm nhỏ cụ thể của ứng dụng tại thời điểm cài đặt trên Android 9 (API cấp 28) hoặc Android 7 (API cấp 24) khi sử dụng ProfileInstaller.
Ghi chú khác
Khi tạo cấu hình cơ sở, bạn cần lưu ý một số điều sau đây:
AOT có sẵn Android 5 tới Android 6 (API cấp 21 và 23) tổng hợp APK tại thời điểm cài đặt.
Các ứng dụng có thể gỡ lỗi không bao giờ được tổng hợp bằng AOT để giúp khắc phục sự cố.
Các tệp quy tắc phải được đặt tên là
baseline-prof.txt
và đặt trong thư mục gốc của nhóm tài nguyên chính (phải là tệp đồng cấp với tệpAndroidManifest.xml
)Bạn chỉ sử dụng được các tệp này nếu bạn đang dùng trình bổ trợ Android cho Gradle
7.1.0-alpha05
trở lên (Android Studio Bumblebee Canary 5).Bazel hiện không hỗ trợ việc đọc và hợp nhất các Cấu hình cơ sở thành một APK.
Cấu hình cơ sở đã nén không được lớn hơn 1,5 MB. Do đó, các thư viện và ứng dụng nên cố gắng xác định một bộ quy tắc nhỏ để tăng tối đa mức độ ảnh hưởng.
Các quy tắc rộng tổng hợp quá nhiều ứng dụng có thể làm chậm quá trình khởi động do quyền truy cập ổ đĩa tăng lên. Bạn nên kiểm tra hiệu suất của cấu hình cơ sở.
Đo lường các điểm cải thiện
Tự động đo lường với thư viện Macrobenchmark
Macrobenchmark cho phép bạn kiểm soát việc tổng hợp đo lường trước thông qua CompilationMode API, bao gồm cả mức sử dụng BaselineProfile
.
Nếu đã thiết lập bài kiểm thử BaselineProfileRule
trong mô-đun Macrobenchmark, thì bạn có thể xác định bài kiểm thử mới trong mô-đun đó để đánh giá hiệu suất của bài kiểm thử:
@RunWith(AndroidJUnit4::class)
class BaselineProfileBenchmark {
@get:Rule
val benchmarkRule = MacrobenchmarkRule()
@Test
fun startupNoCompilation() {
startup(CompilationMode.None())
}
@Test
fun startupBaselineProfile() {
startup(CompilationMode.Partial(
baselineProfileMode = BaselineProfileMode.Require
))
}
private fun startup(compilationMode: CompilationMode) {
benchmarkRule.measureRepeated(
packageName = "com.example.app",
metrics = listOf(StartupTimingMetric()),
iterations = 10,
startupMode = StartupMode.COLD,
compilationMode = compilationMode
) { // this = MacrobenchmarkScope
pressHome()
startActivityAndWait()
}
}
}
Hình 2 minh hoạ ví dụ về kết quả kiểm thử đạt:
Lưu ý rằng mặc dù trong ví dụ ở trên xem xét StartupTimingMetric
, có những chỉ số quan trọng khác mà bạn nên cân nhắc (như Độ giật (chỉ số về khung)) có thể được đo bằng Jetpack Macrobenchmark.
Đo lường các điểm cải thiện với ứng dụng theo cách thủ công
Trước tiên, hãy đo lường quá trình khởi động ứng dụng chưa được tối ưu hoá để tham khảo.
PACKAGE_NAME=com.example.app
# Force Stop App adb shell am force-stop $PACKAGE_NAME # Reset compiled state adb shell cmd package compile --reset $PACKAGE_NAME
# Measure App startup # This corresponds to `Time to initial display` metric # For additional info https://developer.android.com/topic/performance/vitals/launch-time#time-initial adb shell am start-activity -W -n $PACKAGE_NAME/.ExampleActivity \ | grep "TotalTime"
Tiếp theo, hãy tải không qua cửa hàng Cấu hình cơ sở.
# Unzip the Release APK first unzip release.apk
# Create a ZIP archive # Note: The name should match the name of the APK # Note: Copy baseline.prof{m} and rename it to primary.prof{m} cp assets/dexopt/baseline.prof primary.prof cp assets/dexopt/baseline.profm primary.profm
# Create an archive zip -r release.dm primary.prof primary.profm
# Confirm that release.dm only contains the two profile files: unzip -l release.dm # Archive: release.dm # Length Date Time Name # --------- ---------- ----- ---- # 3885 1980-12-31 17:01 primary.prof # 1024 1980-12-31 17:01 primary.profm # --------- ------- # 2 files
# Install APK + Profile together adb install-multiple release.apk release.dm
Để xác minh rằng gói đã được tối ưu hoá khi cài đặt, hãy chạy lệnh sau:
# Check dexopt state
adb shell dumpsys package dexopt | grep -A 1 $PACKAGE_NAME
Kết quả sẽ nêu rõ gói đó đã được tổng hợp.
[com.example.app]
path: /data/app/~~YvNxUxuP2e5xA6EGtM5i9A==/com.example.app-zQ0tkJN8tDrEZXTlrDUSBg==/base.apk
arm64: [status=speed-profile] [reason=install-dm]
Bây giờ, chúng ta có thể đo lường hiệu suất khi khởi động ứng dụng như trước đây, nhưng không đặt lại trạng thái tổng hợp.
# Force Stop App adb shell am force-stop $PACKAGE_NAME
# Measure App startup adb shell am start-activity -W -n $PACKAGE_NAME/.ExampleActivity \ | grep "TotalTime"
Vấn đề đã biết
Việc sử dụng Hồ sơ cơ sở hiện tồn tại một số vấn đề đã biết:
Các hồ sơ cơ sở không được đóng gói chính xác khi tạo APK từ một gói ứng dụng. Để giải quyết vấn đề này, hãy áp dụng từ
com.android.tools.build:gradle:7.3.0-beta02
trở lên (vấn đề).Các hồ sơ cơ sở chỉ được đóng gói chính xác cho tệp
classes.dex
chính. Điều này ảnh hưởng đến các ứng dụng có nhiều tệp.dex
. Để giải quyết vấn đề này, hãy áp dụng từcom.android.tools.build:gradle:7.3.0-beta02
trở lên (vấn đề).Macrobenchmark không tương thích với Hồ sơ cơ sở trên thiết bị Android 12L (API cấp 32) (vấn đề ) và Android 13 (API cấp 33) (vấn đề ).
Không cho phép đặt lại bộ nhớ đệm của hồ sơ ART trên các bản dựng
user
(không bị can thiệp). Để giải quyết vấn đề này,androidx.benchmark:benchmark-macro-junit4:1.1.0-rc02
bao gồm bản sửa lỗi sẽ cài đặt lại ứng dụng trong quá trình đo điểm chuẩn (vấn đề).Trình phân tích tài nguyên Android Studio không cài đặt Cấu hình cơ sở khi phân tích tài nguyên ứng dụng (vấn đề).
Các hệ thống xây dựng không phải Gradle (chẳng hạn như Bazel, Buck, v.v.) không hỗ trợ biên dịch Cấu hình cơ sở thành APK đầu ra.
Cửa hàng Play hiện sẽ cần 10 – 14 giờ sau khi tải AAB lên để cung cấp Cấu hình cơ sở tại thời điểm cài đặt. Người dùng tải ứng dụng xuống trong khoảng thời gian này sẽ không thấy lợi ích cho đến khi công cụ dexopt ở chế độ nền chạy (có thể qua đêm). Tính năng này đang được tích cực cải thiện.
Các kênh phân phối ứng dụng không phải Cửa hàng Play có thể sẽ không hỗ trợ việc sử dụng Cấu hình cơ sở tại thời điểm cài đặt. Người dùng ứng dụng thông qua những kênh này sẽ không thấy lợi ích cho đến khi công cụ dexopt ở chế độ nền chạy (có thể qua đêm).