Sebelum memulai, lihat ringkasan umum Layanan ART.
Mulai Android 14, kompilasi AOT di perangkat untuk aplikasi (alias dexopt) ditangani oleh Layanan ART. Layanan ART adalah bagian dari modul ART, dan Anda dapat menyesuaikannya melalui properti sistem dan API.
Properti sistem
Layanan ART mendukung semua opsi dex2oat yang relevan.
Selain itu, Layanan ART mendukung properti sistem berikut:
pm.dexopt.<reason>
Ini adalah kumpulan properti sistem yang menentukan filter compiler default untuk semua alasan kompilasi standar yang dijelaskan dalam skenario Dexopt.
Untuk informasi selengkapnya, lihat Filter compiler.
Nilai default standarnya adalah:
pm.dexopt.first-boot=verify
pm.dexopt.boot-after-ota=verify
pm.dexopt.boot-after-mainline-update=verify
pm.dexopt.bg-dexopt=speed-profile
pm.dexopt.inactive=verify
pm.dexopt.cmdline=verify
pm.dexopt.shared (default: kecepatan)
Ini adalah filter compiler penggantian untuk aplikasi yang digunakan oleh aplikasi lain.
Pada prinsipnya, Layanan ART melakukan kompilasi terpandu profil (speed-profile
) untuk
semua aplikasi jika memungkinkan, biasanya selama dexopt latar belakang. Namun, ada
beberapa aplikasi yang digunakan oleh aplikasi lain (baik melalui <uses-library>
maupun dimuat
secara dinamis menggunakan Context#createPackageContext
dengan
CONTEXT_INCLUDE_CODE
). Aplikasi tersebut tidak dapat menggunakan
profil lokal karena alasan privasi.
Untuk aplikasi tersebut, jika kompilasi terpandu profil diminta, Layanan ART akan mencoba
menggunakan profil cloud terlebih dahulu. Jika profil cloud tidak ada, Layanan ART
akan kembali menggunakan filter compiler yang ditentukan oleh pm.dexopt.shared
.
Jika kompilasi yang diminta tidak dipandu oleh profil, properti ini tidak akan berpengaruh.
pm.dexopt.<reason>.concurrency (default: 1)
Ini adalah jumlah pemanggilan dex2oat untuk alasan kompilasi
yang telah ditentukan sebelumnya (first-boot
, boot-after-ota
, boot-after-mainline-update
, dan
bg-dexopt
).
Perhatikan bahwa efek opsi ini digabungkan dengan
opsi penggunaan resource dex2oat (dalvik.vm.*dex2oat-threads
,
dalvik.vm.*dex2oat-cpu-set
, dan profil tugas):
dalvik.vm.*dex2oat-threads
mengontrol jumlah thread untuk setiap pemanggilan dex2oat, sedangkanpm.dexopt.<reason>.concurrency
mengontrol jumlah pemanggilan dex2oat. Artinya, jumlah maksimum thread serentak adalah hasil dari dua properti sistem.dalvik.vm.*dex2oat-cpu-set
dan profil tugas selalu mengikat penggunaan core CPU, terlepas dari jumlah maksimum thread serentak (dibahas di atas).
Pemanggilan dex2oat tunggal mungkin tidak sepenuhnya menggunakan semua core CPU, terlepas dari
dalvik.vm.*dex2oat-threads
. Oleh karena itu, meningkatkan jumlah pemanggilan dex2oat (pm.dexopt.<reason>.concurrency
) dapat memanfaatkan core CPU dengan lebih baik, untuk
mempercepat progres dexopt secara keseluruhan. Hal ini sangat berguna selama
proses booting.
Namun, terlalu banyak pemanggilan dex2oat dapat menyebabkan perangkat kehabisan
memori, meskipun hal ini dapat dimitigasi dengan menetapkan dalvik.vm.dex2oat-swap
ke
true
untuk memungkinkan penggunaan file swap. Terlalu banyak pemanggilan juga dapat menyebabkan
peralihan konteks yang tidak perlu. Oleh karena itu, angka ini harus disesuaikan dengan cermat
berdasarkan produk.
pm.dexopt.downgrade_after_inactive_days (default: tidak ditetapkan)
Jika opsi ini ditetapkan, Layanan ART hanya akan melakukan dexopt pada aplikasi yang digunakan dalam jumlah hari terakhir yang ditentukan.
Selain itu, jika penyimpanan hampir habis, selama dexopt latar belakang, Layanan ART
akan mendowngrade filter compiler aplikasi yang tidak digunakan dalam jumlah hari
terakhir yang ditentukan, untuk mengosongkan ruang. Alasan compiler untuk hal ini adalah inactive
,
dan filter compiler ditentukan oleh pm.dexopt.inactive
. Batas ruang
untuk memicu fitur ini adalah batas ruang rendah Pengelola Penyimpanan
(dapat dikonfigurasi melalui setelan global sys_storage_threshold_percentage
dan
sys_storage_threshold_max_bytes
, default: 500 MB) ditambah 500 MB.
Jika Anda menyesuaikan daftar paket melalui
ArtManagerLocal#setBatchDexoptStartCallback
, paket dalam daftar yang disediakan
oleh BatchDexoptStartCallback
untuk bg-dexopt
tidak akan pernah didowngrade.
pm.dexopt.disable_bg_dexopt (default: false)
Ini hanya untuk pengujian. Hal ini mencegah Layanan ART menjadwalkan tugas dexopt latar belakang.
Jika tugas dexopt latar belakang sudah dijadwalkan, tetapi belum berjalan, opsi ini tidak akan berpengaruh. Artinya, tugas akan tetap berjalan.
Urutan perintah yang direkomendasikan untuk mencegah tugas dexopt latar belakang berjalan adalah:
setprop pm.dexopt.disable_bg_dexopt true
pm bg-dexopt-job --disable
Baris pertama mencegah tugas dexopt latar belakang dijadwalkan jika belum dijadwalkan. Baris kedua membatalkan penjadwalan tugas dexopt latar belakang, jika sudah dijadwalkan, dan segera membatalkan tugas dexopt latar belakang, jika sedang berjalan.
ART Service API
Layanan ART mengekspos Java API untuk penyesuaian. API ditentukan di
ArtManagerLocal
. Lihat Javadoc di
art/libartservice/service/java/com/android/server/art/ArtManagerLocal.java
untuk
penggunaan (sumber Android 14, sumber pengembangan yang belum dirilis).
ArtManagerLocal
adalah singleton yang disimpan oleh LocalManagerRegistry
. Fungsi
helper com.android.server.pm.DexOptHelper#getArtManagerLocal
membantu Anda
mendapatkannya.
import static com.android.server.pm.DexOptHelper.getArtManagerLocal;
Sebagian besar API memerlukan instance PackageManagerLocal.FilteredSnapshot
,
yang menyimpan informasi semua aplikasi. Anda bisa mendapatkannya dengan memanggil
PackageManagerLocal#withFilteredSnapshot
, dengan PackageManagerLocal
juga
merupakan singleton yang disimpan oleh LocalManagerRegistry
dan dapat diperoleh dari
com.android.server.pm.PackageManagerServiceUtils#getPackageManagerLocal
.
import static com.android.server.pm.PackageManagerServiceUtils.getPackageManagerLocal;
Berikut adalah beberapa kasus penggunaan umum API.
Memicu dexopt untuk aplikasi
Anda dapat memicu dexopt untuk aplikasi apa pun kapan saja dengan memanggil
ArtManagerLocal#dexoptPackage
.
try (var snapshot = getPackageManagerLocal().withFilteredSnapshot()) {
getArtManagerLocal().dexoptPackage(
snapshot,
"com.google.android.calculator",
new DexoptParams.Builder(ReasonMapping.REASON_INSTALL).build());
}
Anda juga dapat meneruskan alasan dexopt Anda sendiri. Jika Anda melakukannya, class prioritas dan filter compiler harus ditetapkan secara eksplisit.
try (var snapshot = getPackageManagerLocal().withFilteredSnapshot()) {
getArtManagerLocal().dexoptPackage(
snapshot,
"com.google.android.calculator",
new DexoptParams.Builder("my-reason")
.setCompilerFilter("speed-profile")
.setPriorityClass(ArtFlags.PRIORITY_BACKGROUND)
.build());
}
Membatalkan dexopt
Jika operasi dimulai oleh panggilan dexoptPackage
, Anda dapat meneruskan
sinyal pembatalan, yang memungkinkan Anda membatalkan operasi pada waktu tertentu. Hal ini dapat
berguna saat Anda menjalankan dexopt secara asinkron.
Executor executor = ...; // Your asynchronous executor here.
var cancellationSignal = new CancellationSignal();
executor.execute(() -> {
try (var snapshot = getPackageManagerLocal().withFilteredSnapshot()) {
getArtManagerLocal().dexoptPackage(
snapshot,
"com.google.android.calculator",
new DexoptParams.Builder(ReasonMapping.REASON_INSTALL).build(),
cancellationSignal);
}
});
// When you want to cancel the operation.
cancellationSignal.cancel();
Anda juga dapat membatalkan dexopt latar belakang, yang dimulai oleh Layanan ART.
getArtManagerLocal().cancelBackgroundDexoptJob();
Mendapatkan hasil dexopt
Jika operasi dimulai oleh panggilan dexoptPackage
, Anda bisa mendapatkan hasilnya
dari nilai yang ditampilkan.
DexoptResult result;
try (var snapshot = getPackageManagerLocal().withFilteredSnapshot()) {
result = getArtManagerLocal().dexoptPackage(...);
}
// Process the result here.
...
Layanan ART juga memulai operasi dexopt itu sendiri dalam banyak skenario, seperti
dexopt latar belakang. Untuk memproses semua hasil dexopt, baik operasi dimulai oleh panggilan dexoptPackage
atau oleh Layanan ART, gunakan ArtManagerLocal#addDexoptDoneCallback
.
getArtManagerLocal().addDexoptDoneCallback(
false /* onlyIncludeUpdates */,
Runnable::run,
(result) -> {
// Process the result here.
...
});
Argumen pertama menentukan apakah hanya akan menyertakan update dalam hasil. Jika Anda hanya ingin memproses paket yang diupdate oleh dexopt, tetapkan nilai ini ke true.
Argumen kedua adalah eksekutor callback. Untuk menjalankan callback pada
thread yang sama dengan yang melakukan dexopt, gunakan Runnable::run
. Jika Anda tidak ingin callback memblokir dexopt, gunakan eksekutor asinkron.
Anda dapat menambahkan beberapa callback, dan Layanan ART akan menjalankan semuanya secara berurutan. Semua callback akan tetap aktif untuk semua panggilan mendatang, kecuali jika Anda menghapusnya.
Jika Anda ingin menghapus callback, simpan referensi callback saat Anda
menambahkannya, dan gunakan ArtManagerLocal#removeDexoptDoneCallback
.
DexoptDoneCallback callback = (result) -> {
// Process the result here.
...
};
getArtManagerLocal().addDexoptDoneCallback(
false /* onlyIncludeUpdates */, Runnable::run, callback);
// When you want to remove it.
getArtManagerLocal().removeDexoptDoneCallback(callback);
Menyesuaikan daftar paket dan parameter dexopt
Layanan ART memulai operasi dexopt sendiri selama dexopt booting dan
latar belakang. Untuk menyesuaikan daftar paket atau parameter dexopt untuk operasi tersebut,
gunakan ArtManagerLocal#setBatchDexoptStartCallback
.
getArtManagerLocal().setBatchDexoptStartCallback(
Runnable::run,
(snapshot, reason, defaultPackages, builder, cancellationSignal) -> {
switch (reason) {
case ReasonMapping.REASON_BG_DEXOPT:
var myPackages = new ArrayList<String>(defaultPackages);
myPackages.add(...);
myPackages.remove(...);
myPackages.sort(...);
builder.setPackages(myPackages);
break;
default:
// Ignore unknown reasons.
}
});
Anda dapat menambahkan item ke daftar paket, menghapus item dari daftar, mengurutkannya, atau bahkan menggunakan daftar yang sama sekali berbeda.
Callback Anda harus mengabaikan alasan yang tidak diketahui karena lebih banyak alasan dapat ditambahkan di masa mendatang.
Anda dapat menetapkan maksimal satu BatchDexoptStartCallback
. Callback akan tetap
aktif untuk semua panggilan mendatang kecuali jika Anda menghapusnya.
Jika Anda ingin menghapus callback, gunakan
ArtManagerLocal#clearBatchDexoptStartCallback
.
getArtManagerLocal().clearBatchDexoptStartCallback();
Menyesuaikan parameter tugas dexopt latar belakang
Secara default, tugas dexopt latar belakang berjalan sekali sehari saat perangkat tidak ada aktivitas
dan sedang diisi dayanya. Hal ini dapat diubah menggunakan
ArtManagerLocal#setScheduleBackgroundDexoptJobCallback
.
getArtManagerLocal().setScheduleBackgroundDexoptJobCallback(
Runnable::run,
builder -> {
builder.setPeriodic(TimeUnit.DAYS.toMillis(2));
});
Anda dapat menetapkan maksimal satu ScheduleBackgroundDexoptJobCallback
. Callback akan
tetap aktif untuk semua panggilan mendatang kecuali jika Anda menghapusnya.
Jika Anda ingin menghapus callback, gunakan
ArtManagerLocal#clearScheduleBackgroundDexoptJobCallback
.
getArtManagerLocal().clearScheduleBackgroundDexoptJobCallback();
Menonaktifkan dexopt untuk sementara
Setiap operasi dexopt yang dimulai oleh Layanan ART akan memicu
BatchDexoptStartCallback
. Anda dapat terus membatalkan operasi untuk
menonaktifkan dexopt secara efektif.
Jika operasi yang Anda batalkan adalah dexopt latar belakang, operasi tersebut akan mengikuti kebijakan percobaan ulang default (30 detik, eksponensial, dibatasi hingga 5 jam).
// Good example.
var shouldDisableDexopt = new AtomicBoolean(false);
getArtManagerLocal().setBatchDexoptStartCallback(
Runnable::run,
(snapshot, reason, defaultPackages, builder, cancellationSignal) -> {
if (shouldDisableDexopt.get()) {
cancellationSignal.cancel();
}
});
// Disable dexopt.
shouldDisableDexopt.set(true);
getArtManagerLocal().cancelBackgroundDexoptJob();
// Re-enable dexopt.
shouldDisableDexopt.set(false);
Anda dapat memiliki maksimal satu BatchDexoptStartCallback
. Jika Anda juga ingin menggunakan
BatchDexoptStartCallback
untuk menyesuaikan daftar paket atau parameter dexopt,
Anda harus menggabungkan kode menjadi satu callback.
// Bad example.
// Disable dexopt.
getArtManagerLocal().unscheduleBackgroundDexoptJob();
// Re-enable dexopt.
getArtManagerLocal().scheduleBackgroundDexoptJob();
Operasi dexopt yang dilakukan pada penginstalan aplikasi tidak dimulai oleh Layanan
ART. Sebagai gantinya, proses ini dimulai oleh pengelola paket melalui
panggilan dexoptPackage
. Oleh karena itu, tindakan ini tidak memicu
BatchDexoptStartCallback
. Untuk menonaktifkan dexopt saat penginstalan aplikasi, cegah
pengelola paket memanggil dexoptPackage
.
Mengganti filter compiler untuk paket tertentu (Android 15+)
Anda dapat mengganti filter compiler untuk paket tertentu dengan mendaftarkan
callback melalui setAdjustCompilerFilterCallback
. Callback dipanggil
setiap kali paket akan dide-dexopt, terlepas dari apakah dexopt dimulai oleh
Layanan ART selama booting dan dexopt latar belakang atau oleh panggilan API dexoptPackage
.
Jika paket tidak memerlukan penyesuaian, callback harus menampilkan
originalCompilerFilter
.
getArtManagerLocal().setAdjustCompilerFilterCallback(
Runnable::run,
(packageName, originalCompilerFilter, reason) -> {
if (isVeryImportantPackage(packageName)) {
return "speed-profile";
}
return originalCompilerFilter;
});
Anda hanya dapat menetapkan satu AdjustCompilerFilterCallback
. Jika ingin menggunakan
AdjustCompilerFilterCallback
guna mengganti filter compiler untuk beberapa
paket, Anda harus menggabungkan kode menjadi satu callback. Callback tetap
aktif untuk semua panggilan mendatang, kecuali jika Anda menghapusnya.
Jika Anda ingin menghapus callback, gunakan
ArtManagerLocal#clearAdjustCompilerFilterCallback
.
getArtManagerLocal().clearAdjustCompilerFilterCallback();
Penyesuaian lainnya
Layanan ART juga mendukung beberapa penyesuaian lainnya.
Menetapkan nilai minimum termal untuk dexopt latar belakang
Kontrol termal tugas dexopt latar belakang dilakukan oleh Job Scheduler.
Tugas akan segera dibatalkan saat suhu mencapai
THERMAL_STATUS_MODERATE
. Batas minimum
THERMAL_STATUS_MODERATE
dapat disesuaikan.
Menentukan apakah dexopt latar belakang berjalan
Tugas dexopt latar belakang dikelola oleh Job Scheduler, dan ID tugasnya adalah
27873780
. Untuk menentukan apakah tugas sedang berjalan, gunakan Job Scheduler API.
// Good example.
var jobScheduler =
Objects.requireNonNull(mContext.getSystemService(JobScheduler.class));
int reason = jobScheduler.getPendingJobReason(27873780);
if (reason == PENDING_JOB_REASON_EXECUTING) {
// Do something when the job is running.
...
}
// Bad example.
var backgroundDexoptRunning = new AtomicBoolean(false);
getArtManagerLocal().setBatchDexoptStartCallback(
Runnable::run,
(snapshot, reason, defaultPackages, builder, cancellationSignal) -> {
if (reason.equals(ReasonMapping.REASON_BG_DEXOPT)) {
backgroundDexoptRunning.set(true);
}
});
getArtManagerLocal().addDexoptDoneCallback(
false /* onlyIncludeUpdates */,
Runnable::run,
(result) -> {
if (result.getReason().equals(ReasonMapping.REASON_BG_DEXOPT)) {
backgroundDexoptRunning.set(false);
}
});
if (backgroundDexoptRunning.get()) {
// Do something when the job is running.
...
}
Memberikan profil untuk dexopt
Untuk menggunakan profil guna memandu dexopt, tempatkan file .prof
atau file .dm
di samping
APK.
File .prof
harus berupa file profil berformat biner, dan nama file harus
nama file APK + .prof
. Misalnya,
base.apk.prof
Nama file file .dm
harus berupa nama file APK dengan
ekstensi diganti dengan .dm
. Misalnya,
base.dm
Untuk memverifikasi bahwa profil digunakan untuk dexopt, jalankan dexopt dengan
speed-profile
dan periksa hasilnya.
pm art clear-app-profiles <package-name>
pm compile -m speed-profile -f -v <package-name>
Baris pertama akan menghapus semua profil yang dihasilkan oleh runtime (yaitu, profil dalam
/data/misc/profiles
), jika ada, untuk memastikan bahwa profil di samping APK adalah
satu-satunya profil yang mungkin dapat digunakan Layanan ART. Baris kedua menjalankan dexopt
dengan speed-profile
, dan meneruskan -v
untuk mencetak hasil panjang.
Jika profil sedang digunakan, Anda akan melihat actualCompilerFilter=speed-profile
dalam
hasilnya. Jika tidak, Anda akan melihat actualCompilerFilter=verify
. Misalnya,
DexContainerFileDexoptResult{dexContainerFile=/data/app/~~QR0fTV0UbDbIP1Su7XzyPg==/com.google.android.gms-LvusF2uARKOtBbcaPHdUtQ==/base.apk, primaryAbi=true, abi=x86_64, actualCompilerFilter=speed-profile, status=PERFORMED, dex2oatWallTimeMillis=4549, dex2oatCpuTimeMillis=14550, sizeBytes=3715344, sizeBeforeBytes=3715344}
Alasan umum mengapa Layanan ART tidak menggunakan profil meliputi hal-hal berikut:
- Profil memiliki nama file yang salah atau tidak berada di samping APK.
- Format profil salah.
- Profil tidak cocok dengan APK. (Checksum dalam profil tidak
cocok dengan checksum file
.dex
dalam APK.)