Tối ưu hoá bố cục DEX và hồ sơ khởi động

Tài liệu này mô tả các bước bật tính năng tối ưu hoá bố cục DEX bằng hồ sơ khởi động khi tạo một ứng dụng Android.

Yêu cầu

Để sử dụng tính năng tối ưu hoá bố cục DEX và các chức năng liên quan, bạn cần có Jetpack Macrobenchmark phiên bản 1.2.0-alpha14 trở lên và phiên bản trình bổ trợ Android cho Gradle được mô tả trong bảng sau:

Công nghệ Phiên bản trình bổ trợ Android cho Gradle tối thiểu
Hồ sơ cơ sở 7.4.1
Tối ưu hoá bố cục DEX 8.2.0-alpha09
Cải thiện tính năng biên dịch hồ sơ 8.2.0-alpha09

Hiện tại, các hệ thống xây dựng của bên thứ ba như Bazel chưa được hỗ trợ.

Hồ sơ khởi động

Hồ sơ khởi động tương tự như Hồ sơ cơ sở. Loại hồ sơ này mô tả các lớp và phương thức quan trọng đối với quá trình khởi động ứng dụng, phải sẵn sàng tải trước tiên. Hồ sơ khởi động cũng dùng định dạng con người có thể đọc được (HRF) như Hồ sơ cơ sở.

Một điểm khác biệt chính giữa hồ sơ khởi động và Hồ sơ cơ sở là Hồ sơ cơ sở có các lớp và phương thức quan trọng để tối ưu hoá bên ngoài quá trình khởi động ứng dụng, ví dụ: giảm hiện tượng giật trong hoạt ảnh hoặc CUJ chính bên ngoài quá trình khởi động ứng dụng.

Một điểm khác biệt chính khác giữa hồ sơ khởi động và Hồ sơ cơ sở là thư viện không thể cung cấp hồ sơ khởi động và hồ sơ khởi động không tham gia quá trình hợp nhất bằng trình bổ trợ Android cho Gradle. Lý do là thư viện không nhất thiết phải nắm rõ các lớp và phương thức quan trọng cho quá trình khởi động ứng dụng. Tốt nhất là nên thu thập các lớp và phương thức này từ Jetpack Macrobenchmark, bằng cách sử dụng BaselineProfileRule với CUJ nhắm mục tiêu cụ thể đến quá trình khởi động ứng dụng, chẳng hạn như collect.

Hãy xem bảng sau đây để nắm được nội dung tóm tắt nhanh về những điểm khác biệt chính giữa Hồ sơ cơ sở và hồ sơ khởi động.

Loại hồ sơ Trên mỗi bản dựng Có thể hợp nhất
Hồ sơ cơ sở Không
Hồ sơ khởi động Không

Hồ sơ khởi động được lưu trữ trong src/<variantName>/main/baselineProfiles/startup-prof.txt.

Tối ưu hoá bố cục DEX

Tính năng tối ưu hoá này giúp giảm số lượng lỗi nghiêm trọng của trang trong quá trình khởi động ứng dụng, bằng cách cải thiện vị trí của mã được sử dụng, nhờ đó rút ngắn thời gian khởi động.

Bạn có thể thực hiện việc này bằng cách thêm tất cả các mã được thực thi trong quá trình khởi động vào tệp classes.dex chính, đồng thời xoá tất cả các mã không dùng trong quá trình khởi động khỏi tệp classes.dex chính.

Hình 1. Cải thiện vị trí của mã để tối ưu hoá bố cục DEX.

Sử dụng tính năng tối ưu hoá bố cục DEX

Phần này cho biết cách sử dụng tính năng tối ưu hoá bố cục DEX.

Xây dựng hồ sơ khởi động

Trước tiên, bạn cần xây dựng hồ sơ khởi động.

Thiết lập dự án

Trong ví dụ trước, phép kiểm thử đo lường điều khiển một mô-đun app có tên gói là com.example.app.

Khi dùng Jetpack Macrobenchmark để tạo quy tắc hồ sơ khởi động, bạn sẽ xác định một biến thể điểm chuẩn mới trong bản dựng. Biến thể điểm chuẩn giống với biến thể bản phát hành, ngoại trừ việc bạn tắt tính năng giảm thiểu.

Sau đây là một phần trích dẫn từ tệp build.gradle của mô-đun ứng dụng.

Kotlin

buildTypes {
        ...
        create("benchmark") {
            initWith(buildTypes.getByName("release")
            isMinifyEnabled = false
            signingConfig = signingConfigs.getByName("debug")
            matchingFallbacks += "release"
        }
}

Groovy

buildTypes {
        ...
        benchmark {
            initWith buildTypes.release
            minifyEnabled false
            signingConfig signingConfigs.debug
            matchingFallbacks = ['release']
        }
}

Tạo quy tắc khởi động

Kotlin

@RunWith(AndroidJUnit4::class)
class StartupProfileGenerator {
    @get:Rule
    val baselineProfileRule = BaselineProfileRule()

    @Test
    fun startup() =
        baselineProfileRule.collect(
            packageName = "com.example.app",
            includeInStartupProfile = true
    ) {
            // This scenario just starts the activity and waits for it to draw
            // the first frame. If you have animations or async content in your
            // startup, wait for them with UiAutomator.
            startActivityAndWait()
        }
}

Java

@RunWith(AndroidJUnit4.class)
public class StartupProfileGenerator {
    @Rule
    BaselineProfileRule baselineProfileRule = new BaselineProfileRule();

    @Test
    public void startup() {
        baselineProfileRule.collect(
            "com.example.app",
            /* includeInStartupProfile = */ true,
            (scope -> {
                // This scenario just starts the activity and waits for it to
                // draw the first frame. If you have animations or async content
                // in your startup, wait for them with UiAutomator.
                scope.startActivityAndWait();
                return null;
            }
        ));
    }
}

Đầu ra

Chạy kết quả kiểm thử trong một tệp có dạng như sau:

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;

Sao chép nội dung của tệp đầu ra vào src/main/baselineProfiles/startup-prof.txt.

Bật tính năng tối ưu hoá bố cục DEX

Thuộc tính thử nghiệm android.experimental.r8.dex-startup-optimization cho phép tối ưu hoá bố cục DEX.

Kotlin

android {
    // ...
    experimentalProperties["android.experimental.r8.dex-startup-optimization"] = true
}

Groovy

android {
    // ...
    experimentalProperties["android.experimental.r8.dex-startup-optimization"] = true
}

Để xây dựng APK bằng tính năng tối ưu hoá bố cục DEX, bạn có thể dùng cách sau:

./gradlew :app:assembleRelease