Từng bước áp dụng các biện pháp tối ưu hoá

Theo mặc định, R8 thực hiện nhiều hoạt động tối ưu hoá để cải thiện hiệu suất và kích thước, nhưng các hoạt động tối ưu hoá này có thể không hoạt động ngay lập tức cho ứng dụng của bạn. Nếu bạn bật R8 (hoặc bật chế độ đầy đủ) trong một ứng dụng lớn lần đầu tiên, hãy thử áp dụng các tính năng tối ưu hoá một cách tăng dần: tạm thời tắt tính năng làm rối mã nguồn và bật R8 cho từng phần mã thay vì cho tất cả mã trong ứng dụng. Bạn nên sử dụng phương pháp tăng dần này trong quá trình phát triển cục bộ, nhưng bạn cũng có thể sử dụng phương pháp này trong quá trình kiểm thử QA nội bộ hoặc thậm chí trong quá trình phát hành công khai dưới dạng việc triển khai dần dần. Các bước chính xác mà bạn thực hiện phụ thuộc vào tiến trình bạn muốn và mức độ tự tin về phạm vi kiểm thử trước khi phát hành.

Giới hạn các hoạt động tối ưu hoá

R8 thực hiện nhiều loại hoạt động tối ưu hoá, bao gồm xoá mã, viết lại mã và xoá tài nguyên. Sau đây là một số nội dung mô tả tổng quan về các loại tính năng tối ưu hoá:

  • Rút gọn mã (hoặc loại bỏ mã chết): xoá mã không được tham chiếu
  • Làm rối mã nguồn (hoặc rút gọn giá trị nhận dạng): rút ngắn tên lớp và phương thức
  • Tối ưu hoá: viết lại mã, ví dụ: nội tuyến

Để giảm khả năng xảy ra lỗi, bạn có thể bắt đầu bằng cách chỉ bật một số tính năng tối ưu hoá này.

Chỉ bật tính năng loại bỏ mã không dùng đến

Rút gọn mã (còn được gọi là rung cây (tree shaking)) sẽ xoá mã có vẻ như không được tham chiếu. Bạn nên bắt đầu với việc chỉ loại bỏ cây, vì đây là cách đơn giản nhất.

Để chỉ bật tính năng loại bỏ cây, hãy thêm nội dung sau vào tệp proguard-rules.pro để tắt các loại tính năng tối ưu hoá khác. Việc tắt tính năng làm rối mã nguồn là rất quan trọng vì tính năng này giúp các dấu vết ngăn xếp dễ đọc hơn nhiều.

-dontobfuscate // Use temporarily to turn off identifier minification
-dontoptimize // Use temporarily to turn off optimization

Cuối cùng, bạn không nên phân phối cấu hình này vì cấu hình này hạn chế đáng kể khả năng R8 tối ưu hoá mã, nhưng đây là điểm xuất phát tuyệt vời khi sử dụng R8 lần đầu tiên trong một cơ sở mã lớn có vấn đề cần khắc phục.

Sử dụng chế độ tương thích

Theo mặc định, R8 chạy ở chế độ đầy đủ. Chế độ đầy đủ giúp cải thiện đáng kể hiệu suất và tiết kiệm kích thước, nhưng bạn có thể tạm thời tắt chế độ này và sử dụng chế độ tương thích khi bật tính năng rút gọn lần đầu tiên.

Để sử dụng chế độ tương thích, hãy sử dụng chế độ cài đặt sau trong tệp gradle.properties:

android.enableR8.fullMode = false // Use temporarily to disable full mode

Bật các tính năng tối ưu hoá còn lại

Khi xác nhận rằng tính năng loại bỏ mã không dùng đến hoạt động hiệu quả cho ứng dụng, bạn có thể xoá các chế độ cài đặt trước đó để bật lại tính năng làm rối mã, tối ưu hoá và chế độ đầy đủ R8. Xin lưu ý rằng việc làm rối mã nguồn có thể khiến việc gỡ lỗi trở nên khó khăn hơn. Đó là lý do bạn nên giải quyết các vấn đề về việc loại bỏ mã thừa trước.

Để biết thêm thông tin về cách gỡ rối mã nguồn cho dấu vết ngăn xếp, hãy xem phần Khôi phục dấu vết ngăn xếp ban đầu.

Giới hạn phạm vi tối ưu hoá

Bản dựng được tối ưu hoá đầy đủ sẽ tối ưu hoá tất cả mã trên mọi thư viện và gói, vì vậy, bạn thường gặp phải các vấn đề với R8 khi bật công cụ này lần đầu tiên. Nếu bạn phát hiện vấn đề về việc tối ưu hoá trong một phần của ứng dụng, đừng tắt hoàn toàn R8, nếu không bạn sẽ mất đi các lợi ích ở mọi nơi khác. Thay vào đó, hãy tạm thời tắt R8 chỉ trong các phần của ứng dụng đang gây ra sự cố.

Sử dụng quy tắc giữ trên toàn gói

Bạn nên sử dụng các quy tắc giữ trên toàn gói để tạm thời tắt R8 trong một số phần của ứng dụng. Bạn phải luôn quay lại để khắc phục các vấn đề tối ưu hoá này sau; đây thường là giải pháp tạm thời để giải quyết các vấn đề.

Ví dụ: nếu một phần ứng dụng của bạn sử dụng nhiều Gson và gây ra vấn đề về việc tối ưu hoá, thì giải pháp lý tưởng là thêm nhiều quy tắc giữ mục tiêu hoặc chuyển sang giải pháp codegen. Tuy nhiên, để bỏ chặn việc tối ưu hoá phần còn lại của ứng dụng, bạn có thể đặt mã xác định các loại Gson trong một gói con chuyên dụng và thêm quy tắc như sau vào tệp proguard-rules.pro:

-keep class com.myapp.json.** { *; }

Nếu một số thư viện mà bạn đang sử dụng có tính năng phản chiếu vào các thành phần nội bộ, thì bạn cũng có thể thêm quy tắc giữ lại cho toàn bộ thư viện. Bạn sẽ cần kiểm tra mã hoặc JAR/AAR của thư viện để tìm gói thích hợp cần giữ lại. Xin nhắc lại rằng bạn không nên duy trì cách này lâu dài, nhưng có thể bỏ chặn tính năng tối ưu hoá phần còn lại của ứng dụng:

-keep class com.somelibrary.** { *; }

Xoá quy tắc giữ lại trên toàn gói

Sau khi ứng dụng hoạt động chính xác với các quy tắc giữ trên toàn gói, bạn nên quay lại và thêm các quy tắc giữ được nhắm mục tiêu hoặc xoá việc sử dụng phản chiếu hoặc thư viện cần có quy tắc giữ ngay từ đầu.

Ví dụ: việc giữ lại tất cả các quy tắc mở rộng một lớp nhất định là cực kỳ phổ biến trong AndroidX để chỉ giữ lại các lớp có liên quan. Nhìn chung, tính năng phản chiếu chỉ nên nhắm đến các lớp hoặc phương thức mở rộng một số lớp trừu tượng nhất định, triển khai một số giao diện nhất định hoặc vào các lớp có chú thích thời gian chạy cụ thể. Mỗi cách trong số này đều là cách được hỗ trợ để xác định quy tắc giữ lại, nhờ đó bạn không cần quy tắc giữ lại trên toàn gói trong ứng dụng hoàn thiện, được tối ưu hoá đầy đủ.