Triển khai trình biên dịch đúng thời điểm ART

Android Runtime (ART) bao gồm một trình biên dịch vừa kịp thời (JIT) với tính năng phân tích mã giúp liên tục cải thiện hiệu suất của các ứng dụng Android khi chạy. Trình biên dịch JIT bổ sung cho trình biên dịch chạy trước (AOT) hiện tại của ART, đồng thời cải thiện hiệu suất trong thời gian chạy, tiết kiệm không gian lưu trữ và tăng tốc độ cập nhật ứng dụng cũng như hệ thống. Công cụ này cũng cải thiện trình biên dịch AOT bằng cách tránh làm chậm hệ thống trong quá trình cập nhật ứng dụng tự động hoặc biên dịch lại ứng dụng trong quá trình cập nhật qua mạng không dây (OTA).

Mặc dù JIT và AOT sử dụng cùng một trình biên dịch với một bộ tối ưu hoá tương tự, nhưng mã được tạo có thể không giống nhau. JIT tận dụng thông tin về loại thời gian chạy, có thể thực hiện cùng dòng tốt hơn và có thể thực hiện việc biên dịch thay thế ngăn xếp (OSR), tất cả đều tạo ra mã hơi khác nhau.

Cấu trúc JIT

Cấu trúc JIT
Hình 1. Cấu trúc JIT.

Biên dịch JIT

Quá trình biên dịch JIT bao gồm các hoạt động sau:

Bản tóm tắt theo hướng dẫn của hồ sơ
Hình 2. Biên dịch theo hướng dẫn của hồ sơ.
  1. Người dùng chạy ứng dụng, sau đó ứng dụng sẽ kích hoạt ART để tải tệp .dex.
    • Nếu có tệp .oat (tệp nhị phân AOT cho tệp .dex), ART sẽ sử dụng trực tiếp tệp đó. Mặc dù các tệp .oat được tạo thường xuyên, nhưng không phải lúc nào các tệp này cũng chứa mã đã biên dịch (tệp nhị phân AOT).
    • Nếu tệp .oat không chứa mã đã biên dịch, thì ART sẽ chạy thông qua JIT và trình thông dịch để thực thi tệp .dex.
  2. JIT được bật cho mọi ứng dụng không được biên dịch theo bộ lọc biên dịch speed (có nội dung là "biên dịch nhiều nhất có thể từ ứng dụng").
  3. Dữ liệu hồ sơ JIT được kết xuất vào một tệp trong thư mục hệ thống mà chỉ ứng dụng mới có thể truy cập.
  4. Trình biên dịch AOT (dex2oat) sẽ phân tích cú pháp tệp đó để điều khiển quá trình biên dịch.

    Trình nền JIT
    Hình 3. Hoạt động trình nền JIT (JIT).

Dịch vụ Google Play là một ví dụ mà các ứng dụng khác sử dụng và hoạt động tương tự như thư viện dùng chung.

Quy trình làm việc JIT

Cấu trúc JIT
Hình 4. Luồng dữ liệu JIT.
  • Thông tin phân tích tài nguyên được lưu trữ trong bộ nhớ đệm mã và phải được thu gom rác khi có áp lực bộ nhớ.
    • Không có gì đảm bảo rằng một bản tổng quan nhanh được chụp khi ứng dụng chạy ở chế độ nền sẽ chứa dữ liệu đầy đủ (tức là mọi thứ đã được cập nhật thực tế).
    • Không có nỗ lực nào để đảm bảo mọi thứ đều được ghi lại (vì điều này có thể ảnh hưởng đến hiệu suất thời gian chạy).
  • Phương thức có thể ở 3 trạng thái:
    • được thông dịch (mã dex)
    • Biên dịch JIT
    • Đã biên dịch AOT
    Nếu tồn tại cả mã JIT và AOT (ví dụ: do phải loại bỏ tối ưu hoá nhiều lần), thì mã JITed sẽ được ưu tiên.
  • Yêu cầu về bộ nhớ để chạy JIT mà không ảnh hưởng đến hiệu suất của ứng dụng trên nền trước phụ thuộc vào ứng dụng có liên quan. Ứng dụng lớn cần nhiều bộ nhớ hơn ứng dụng nhỏ. Nhìn chung, các ứng dụng lớn thường ổn định trong khoảng 4 MB.

Bật tính năng ghi nhật ký JIT

Để bật tính năng ghi nhật ký JIT, hãy chạy các lệnh sau:

adb root
adb shell stop
adb shell setprop dalvik.vm.extra-opts -verbose:jit
adb shell start

Tắt JIT

Để tắt JIT, hãy chạy các lệnh sau:

adb root
adb shell stop
adb shell setprop dalvik.vm.usejit false
adb shell start

Buộc biên dịch

Để buộc biên dịch, hãy chạy lệnh sau:

adb shell cmd package compile

Các trường hợp sử dụng phổ biến để buộc biên dịch một gói cụ thể:

  • Dựa trên hồ sơ:
    adb shell cmd package compile -m speed-profile -f my-package
    
  • Đầy đủ:
    adb shell cmd package compile -m speed -f my-package
    

Các trường hợp sử dụng phổ biến đối với việc buộc biên dịch tất cả các gói:

  • Dựa trên hồ sơ:
    adb shell cmd package compile -m speed-profile -f -a
    
  • Đầy:
    adb shell cmd package compile -m speed -f -a
    

Xoá dữ liệu hồ sơ

Trên Android 13 trở xuống

Để xoá dữ liệu hồ sơ cục bộ và xoá mã đã biên dịch, hãy chạy mã sau:

adb shell pm compile --reset 

Trên Android 14 trở lên

Cách chỉ xoá dữ liệu hồ sơ cục bộ:

adb shell pm art clear-app-profiles 

Lưu ý: Không giống như lệnh dành cho Android 13 trở xuống, lệnh này không xoá dữ liệu hồ sơ bên ngoài (".dm") được cài đặt cùng với ứng dụng.

Để xoá dữ liệu hồ sơ cục bộ và xoá mã đã biên dịch được tạo từ dữ liệu hồ sơ cục bộ (tức là để đặt lại về trạng thái cài đặt), hãy chạy các lệnh sau:

adb shell pm compile --reset 

Lưu ý: Lệnh này không xoá mã được biên dịch được tạo từ dữ liệu hồ sơ bên ngoài (".dm") được cài đặt cùng với ứng dụng.

Để xoá tất cả mã đã biên dịch, hãy chạy lệnh sau:

adb shell cmd package compile -m verify -f 

Lưu ý: Lệnh này giữ lại dữ liệu hồ sơ cục bộ.