Peningkatan ART Android 8.0

Runtime Android (ART) telah ditingkatkan secara signifikan dalam rilis Android 8.0. Daftar di bawah merangkum peningkatan yang dapat diharapkan produsen perangkat di ART.

Pembersihan sampah memori pemadat serentak

Seperti yang diumumkan di Google I/O, ART menampilkan pengumpulan sampah (GC) pemadatan serentak baru di Android 8.0. Pengumpul ini memadatkan heap setiap kali GC berjalan dan saat aplikasi berjalan, dengan hanya satu jeda singkat untuk memproses root thread. Berikut manfaatnya:

  • GC selalu memadatkan heap: ukuran heap rata-rata 32% lebih kecil dibandingkan dengan Android 7.0.
  • Kompresi memungkinkan alokasi objek pointer bump lokal thread: Alokasi lebih cepat 70% daripada di Android 7.0.
  • Menawarkan waktu jeda 85% lebih kecil untuk benchmark H2 dibandingkan dengan GC Android 7.0.
  • Waktu jeda tidak lagi diskalakan dengan ukuran heap; aplikasi harus dapat menggunakan heap besar tanpa khawatir akan jank.
  • Detail penerapan GC - Batasan baca:
    • Batasan baca adalah sejumlah kecil pekerjaan yang dilakukan untuk setiap pembacaan kolom objek.
    • Hal ini dioptimalkan di compiler, tetapi dapat memperlambat beberapa kasus penggunaan.

Pengoptimalan loop

Berbagai pengoptimalan loop digunakan oleh ART dalam rilis Android 8.0:

  • Penghapusan pemeriksaan batas
    • Statis: rentang terbukti berada dalam batas pada waktu kompilasi
    • Dinamis: pengujian waktu proses memastikan loop tetap dalam batas (jika tidak, deopt)
  • Penghapusan variabel induksi
    • Menghapus induksi mati
    • Mengganti induksi yang hanya digunakan setelah loop dengan ekspresi bentuk tertutup
  • Penghapusan kode mati di dalam isi loop, penghapusan seluruh loop yang menjadi mati
  • Pengurangan kekuatan
  • Transformasi loop: pembalikan, pertukaran, pemisahan, penguraian, unimodular, dll.
  • SIMDisasi (juga disebut vektorisasi)

Pengoptimal loop berada di bagian pengoptimalan sendiri di compiler ART. Sebagian besar pengoptimalan loop mirip dengan pengoptimalan dan penyederhanaan di tempat lain. Tantangan muncul dengan beberapa pengoptimalan yang menulis ulang CFG dengan cara yang lebih rumit dari biasanya, karena sebagian besar utilitas CFG (lihat nodes.h) berfokus pada pembuatan CFG, bukan menulis ulang CFG.

Analisis hierarki class

ART di Android 8.0 menggunakan Class Hierarchy Analysis (CHA), pengoptimalan compiler yang mendevirtualisasi panggilan virtual menjadi panggilan langsung berdasarkan informasi yang dihasilkan dengan menganalisis hierarki class. Panggilan virtual mahal karena diterapkan di sekitar pencarian vtable, dan memerlukan beberapa pemuatan dependen. Selain itu, panggilan virtual tidak dapat disisipkan.

Berikut adalah ringkasan peningkatan terkait:

  • Pembaruan status metode implementasi tunggal dinamis - Di akhir waktu penautan class, saat vtable telah diisi, ART melakukan perbandingan entry-by-entry dengan vtable dari class super.
  • Pengoptimalan compiler - Compiler akan memanfaatkan informasi implementasi tunggal dari suatu metode. Jika metode A.foo telah menetapkan flag implementasi tunggal, compiler akan mendevirtualisasi panggilan virtual menjadi panggilan langsung, dan selanjutnya mencoba menyisipkan panggilan langsung sebagai hasilnya.
  • Pembatalan validasi kode yang dikompilasi - Juga di akhir waktu penautan class saat informasi implementasi tunggal diperbarui, jika metode A.foo yang sebelumnya memiliki implementasi tunggal, tetapi statusnya sekarang dibatalkan validasinya, semua kode yang dikompilasi yang bergantung pada asumsi bahwa metode A.foo memiliki implementasi tunggal harus membatalkan validasi kode yang dikompilasi.
  • De-pengoptimalan - Untuk kode yang dikompilasi secara live yang ada di stack, de-pengoptimalan akan dimulai untuk memaksa kode yang dikompilasi dan tidak valid ke dalam mode penafsir untuk menjamin ketepatan. Mekanisme de-pengoptimalan baru yang merupakan gabungan dari de-pengoptimalan sinkron dan asinkron akan digunakan.

Cache inline dalam file .oat

ART kini menggunakan cache inline dan mengoptimalkan situs panggilan yang memiliki data yang cukup. Fitur cache inline mencatat informasi runtime tambahan ke dalam profil dan menggunakannya untuk menambahkan pengoptimalan dinamis ke kompilasi lebih awal.

Dexlayout

Dexlayout adalah library yang diperkenalkan di Android 8.0 untuk menganalisis file dex dan mengurutkannya ulang sesuai dengan profil. Dexlayout bertujuan untuk menggunakan informasi pembuatan profil runtime untuk mengurutkan ulang bagian file dex selama kompilasi pemeliharaan tidak ada aktivitas di perangkat. Dengan mengelompokkan bagian file dex yang sering diakses bersama, program dapat memiliki pola akses memori yang lebih baik dari lokalitas yang ditingkatkan, menghemat RAM, dan mempersingkat waktu mulai.

Karena informasi profil saat ini hanya tersedia setelah aplikasi dijalankan, dexlayout terintegrasi dalam kompilasi di perangkat dex2oat selama pemeliharaan tidak ada aktivitas.

Penghapusan cache Dex

Hingga Android 7.0, objek DexCache memiliki empat array besar, yang sebanding dengan jumlah elemen tertentu dalam DexFile, yaitu:

  • string (satu referensi per DexFile::StringId),
  • jenis (satu referensi per DexFile::TypeId),
  • metode (satu pointer native per DexFile::MethodId),
  • (satu pointer native per DexFile::FieldId).

Array ini digunakan untuk pengambilan objek yang cepat yang sebelumnya kita selesaikan. Di Android 8.0, semua array telah dihapus kecuali array metode.

Performa penafsir

Performa penafsir meningkat secara signifikan dalam rilis Android 7.0 dengan diperkenalkannya "mterp" - penafsir yang menampilkan mekanisme pengambilan/decoding/penafsiran inti yang ditulis dalam bahasa assembly. Mterp dimodelkan setelah penafsir Dalvik yang cepat, dan mendukung arm, arm64, x86, x86_64, mips, dan mips64. Untuk kode komputasi, mterp Art kurang lebih sebanding dengan penafsir cepat Dalvik. Namun, dalam beberapa situasi, proses ini dapat menjadi jauh lebih lambat:

  1. Performa pemanggilan.
  2. Manipulasi string, dan pengguna berat metode lainnya yang dikenali sebagai intrinsik di Dalvik.
  3. Penggunaan memori stack yang lebih tinggi.

Android 8.0 mengatasi masalah ini.

Penyisipan lainnya

Sejak Android 6.0, ART dapat menyisipkan panggilan apa pun dalam file dex yang sama, tetapi hanya dapat menyisipkan metode leaf dari file dex yang berbeda. Ada dua alasan untuk batasan ini:

  1. Penginlinean dari file dex lain memerlukan penggunaan cache dex dari file dex lain tersebut, tidak seperti penginlinean file dex yang sama, yang hanya dapat menggunakan kembali cache dex pemanggil. Cache dex diperlukan dalam kode yang dikompilasi untuk beberapa petunjuk seperti panggilan statis, pemuatan string, atau pemuatan class.
  2. Peta stack hanya mengenkode indeks metode dalam file dex saat ini.

Untuk mengatasi keterbatasan ini, Android 8.0:

  1. Menghapus akses cache dex dari kode yang dikompilasi (lihat juga bagian "Penghapusan cache dex")
  2. Memperluas encoding peta stack.

Peningkatan sinkronisasi

Tim ART menyesuaikan jalur kode MonitorEnter/MonitorExit, dan mengurangi ketergantungan kami pada penghalang memori tradisional di ARMv8, menggantinya dengan petunjuk (akuisisi/rilis) yang lebih baru jika memungkinkan.

Metode native yang lebih cepat

Panggilan native yang lebih cepat ke Java Native Interface (JNI) tersedia menggunakan anotasi @FastNative dan @CriticalNative. Pengoptimalan runtime ART bawaan ini mempercepat transisi JNI dan menggantikan notasi !bang JNI yang kini tidak digunakan lagi. Anotasi tidak memengaruhi metode non-native dan hanya tersedia untuk kode Bahasa Java platform di bootclasspath (tidak ada update Play Store).

Anotasi @FastNative mendukung metode non-statis. Gunakan ini jika metode mengakses jobject sebagai parameter atau nilai return.

Anotasi @CriticalNative memberikan cara yang lebih cepat untuk menjalankan metode native, dengan batasan berikut:

  • Metode harus bersifat statis—tidak ada objek untuk parameter, nilai yang ditampilkan, atau this implisit.
  • Hanya jenis primitif yang diteruskan ke metode native.
  • Metode native tidak menggunakan parameter JNIEnv dan jclass dalam definisi fungsinya.
  • Metode harus didaftarkan dengan RegisterNatives, bukan mengandalkan penautan JNI dinamis.

@FastNative dapat meningkatkan performa metode native hingga 3x lipat, dan @CriticalNative hingga 5x lipat. Misalnya, transisi JNI yang diukur pada perangkat Nexus 6P:

Pemanggilan Java Native Interface (JNI) Waktu eksekusi (dalam nanodetik)
JNI Reguler 115
!bang JNI 60
@FastNative 35
@CriticalNative 25