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 ART dan Anda dapat menyesuaikannya melalui properti sistem dan API.
Properti sistem
Layanan ART mendukung semua opsi dex2oat.
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 penghapusan.
Untuk informasi selengkapnya, lihat Filter compiler.
Nilai default standar 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 yang dipandu 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>
atau dimuat
secara dinamis menggunakan Context#createPackageContext
dengan
CONTEXT_INCLUDE_CODE
). Aplikasi tersebut tidak dapat menggunakan
karena alasan privasi.
Untuk aplikasi semacam itu, jika kompilasi yang dipandu profil diminta, Layanan ART terlebih dahulu
mencoba menggunakan profil cloud. Jika profil cloud tidak ada, Layanan ART
akan kembali untuk 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 panggilan dex2oat untuk kompilasi yang telah ditentukan sebelumnya
alasan (first-boot
, boot-after-ota
, boot-after-mainline-update
, dan
bg-dexopt
).
Perhatikan bahwa efek dari 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 dex2oat pemanggilan, sedangkanpm.dexopt.<reason>.concurrency
mengontrol jumlah pemanggilan dex2oat. Artinya, jumlah maksimum thread serentak adalah hasil dari perkalian dua properti sistem.dalvik.vm.*dex2oat-cpu-set
dan profil tugas selalu mengikat core CPU penggunaan, terlepas dari jumlah maksimum thread serentak (dibahas di atas).
Satu pemanggilan dex2oat mungkin tidak sepenuhnya menggunakan semua core CPU, terlepas dari
dari dalvik.vm.*dex2oat-threads
. Oleh karena itu, meningkatkan jumlah
pemanggilan (pm.dexopt.<reason>.concurrency
) dapat memanfaatkan inti CPU dengan lebih baik, untuk
mempercepat progres
dexopt secara keseluruhan. Hal ini sangat berguna selama
booting.
Namun, terlalu banyak pemanggilan dex2oat dapat
menyebabkan perangkat kehabisan
memori, meskipun hal ini dapat dimitigasi dengan menyetel dalvik.vm.dex2oat-swap
ke
true
untuk mengizinkan penggunaan file swap. Terlalu banyak {i>pemanggilan<i}
juga dapat menyebabkan
pengalihan konteks yang tidak perlu. Oleh karena itu, angka ini harus disesuaikan dengan saksama
per produk.
pm.dexopt.downgrade_after_inactive_days (default: tidak ditetapkan)
Jika opsi ini disetel, Layanan ART hanya akan melakukan dexopts aplikasi yang digunakan dalam jumlah hari.
Selain itu, jika penyimpanan hampir habis, selama dexopt latar belakang, Layanan ART
menurunkan versi filter compiler aplikasi yang tidak digunakan dalam periode
jumlah hari, untuk mengosongkan ruang penyimpanan. Alasan compiler untuk ini adalah inactive
,
dan filter compiler ditentukan oleh pm.dexopt.inactive
. Ruang
nilai minimum untuk memicu fitur ini adalah nilai minimum ruang penyimpanan Pengelola Penyimpanan
(dapat dikonfigurasi melalui setelan global sys_storage_threshold_percentage
dan
sys_storage_threshold_max_bytes
, default: 500MB) plus 500MB.
Jika Anda menyesuaikan daftar paket melalui
ArtManagerLocal#setBatchDexoptStartCallback
, paket dalam daftar yang disediakan
oleh BatchDexoptStartCallback
untuk bg-dexopt
tidak pernah didowngrade.
pm.dexopt.disable_bg_dexopt (default: false)
Ini hanya untuk pengujian. Hal ini mencegah Layanan ART menjadwalkan latar belakang dexopt.
Jika tugas dexopt latar belakang sudah dijadwalkan tetapi belum berjalan, opsi tersebut tidak berpengaruh. Artinya, tugas akan tetap berjalan.
Urutan perintah yang disarankan untuk mencegah tugas dexopt latar belakang dari 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 jadwal tugas dexopt latar belakang, jika sudah dijadwalkan, dan akan langsung membatalkan tugas dexopt latar belakang, jika komputernya berjalan.
API Layanan ART
ART Service mengekspos Java API untuk penyesuaian. API didefinisikan dalam
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 dipegang oleh LocalManagerRegistry
. Pembantu
fungsi 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
dari semua aplikasi. Anda bisa mendapatkannya dengan memanggil
PackageManagerLocal#withFilteredSnapshot
, dengan PackageManagerLocal
juga
singleton yang dimiliki oleh LocalManagerRegistry
dan dapat diperoleh dari
com.android.server.pm.PackageManagerServiceUtils#getPackageManagerLocal
.
import static com.android.server.pm.PackageManagerServiceUtils.getPackageManagerLocal;
Berikut ini 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 bisa meneruskan alasan dexopt Anda sendiri. Jika Anda melakukannya, kelas prioritas dan filter compiler harus diatur 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());
}
Batalkan 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 sendiri dalam banyak skenario, seperti
dexopt latar belakang. Untuk memproses semua hasil dexopt, baik operasi tersebut
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 pembaruan dalam hasil. Jika Anda hanya ingin mendengarkan paket yang diperbarui oleh {i>dexopt<i}, setel ke true.
Argumen kedua adalah eksekutor callback. Untuk menjalankan callback pada
thread yang sama yang menjalankan dexopt, gunakan Runnable::run
. Jika Anda tidak ingin
untuk memblokir dexopt, menggunakan 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 Anda menghapusnya.
Jika Anda ingin menghapus callback, pertahankan referensi callback tersebut saat Anda
menambahkannya, lalu 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 booting dan latar belakang
{i>dexopt<i}. Untuk menyesuaikan daftar paket atau
parameter {i>dexopt<i} 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 darinya, mengurutkannya, atau bahkan menggunakan daftar yang benar-benar berbeda.
Callback Anda harus mengabaikan alasan yang tidak diketahui karena alasan lain mungkin ditambahkan di masa depan.
Anda dapat menetapkan maksimal satu BatchDexoptStartCallback
. Callback akan tetap
aktif untuk semua panggilan mendatang kecuali 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 pengisian daya. 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 Anda menghapusnya.
Jika Anda ingin menghapus callback, gunakan
ArtManagerLocal#clearScheduleBackgroundDexoptJobCallback
.
getArtManagerLocal().clearScheduleBackgroundDexoptJobCallback();
Nonaktifkan 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 metode kebijakan percobaan ulang (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 tersebut menjadi satu callback.
// Bad example.
// Disable dexopt.
getArtManagerLocal().unscheduleBackgroundDexoptJob();
// Re-enable dexopt.
getArtManagerLocal().scheduleBackgroundDexoptJob();
Operasi dexopt yang dilakukan pada penginstalan aplikasi tidak dimulai oleh ART
Layanan. Sebagai gantinya, ini dimulai oleh
pengelola paket melalui sebuah
Panggilan dexoptPackage
. Oleh karena itu, tindakan ini tidak memicu
BatchDexoptStartCallback
. Untuk menonaktifkan dexopt saat penginstalan aplikasi, cegah
pengelola paket agar tidak memanggil dexoptPackage
.
Mengganti filter compiler untuk paket tertentu (Android 15+)
Anda dapat mengganti filter compiler untuk paket tertentu dengan mendaftarkan
melalui setAdjustCompilerFilterCallback
. Callback dipanggil
setiap kali sebuah paket akan di-dexopt, tidak peduli dexopt yang dimulai oleh
Layanan ART selama dexopt booting dan latar belakang atau dengan panggilan API dexoptPackage
.
Jika sebuah 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 Anda ingin menggunakan
AdjustCompilerFilterCallback
untuk mengganti filter compiler untuk beberapa
paket, Anda harus menggabungkan kode menjadi satu callback. Callback tetap
aktif untuk semua panggilan mendatang kecuali Anda menghapusnya.
Jika Anda ingin menghapus callback, gunakan
ArtManagerLocal#clearAdjustCompilerFilterCallback
.
getArtManagerLocal().clearAdjustCompilerFilterCallback();
Penyesuaian lainnya
Layanan ART juga mendukung beberapa penyesuaian lainnya.
Menetapkan batas termal untuk dexopt latar belakang
Kontrol termal tugas dexopt latar belakang dilakukan oleh Job Scheduler.
Tugas segera dibatalkan saat suhu mencapai
THERMAL_STATUS_MODERATE
Ambang batas
THERMAL_STATUS_MODERATE
dapat disetel.
Menentukan apakah dexopt latar belakang sedang 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.
...
}
Menyediakan profil untuk dexopt
Untuk menggunakan profil yang akan memandu dexopt, tempatkan file .prof
atau .dm
di samping
APK lainnya.
File .prof
harus berupa file profil format biner, dan nama file harus berupa
nama file APK + .prof
. Misalnya,
base.apk.prof
Nama file .dm
harus berupa nama file APK dengan
ekstensi diganti dengan .dm
. Misalnya,
base.dm
Untuk memverifikasi bahwa profil sedang 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 menghapus semua profil yang dihasilkan oleh runtime (yaitu, profil di
/data/misc/profiles
), jika ada, untuk memastikan bahwa profil di samping APK telah
satu-satunya profil yang mungkin
dapat digunakan oleh Layanan ART. Baris kedua menjalankan dexopt
dengan speed-profile
, dan akan meneruskan -v
untuk mencetak hasil panjang.
Jika profil sedang digunakan, Anda akan melihat actualCompilerFilter=speed-profile
di
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 Layanan ART tidak menggunakan profil meliputi:
- Profil memiliki nama file yang salah atau tidak berada di samping APK.
- Format profil salah.
- Profil tidak cocok dengan APK. (Checksum di profil tidak
cocokkan checksum file
.dex
di APK.)