Android çalışma zamanı (ART), Android 8.0 sürümünde önemli ölçüde iyileştirildi. Aşağıdaki listede, cihaz üreticilerinin ART'da yararlanabileceği geliştirmeler özetlenmiştir.
Eş zamanlı sıkıştırıcı çöp toplayıcı
Google I/O'da duyurulduğu gibi, ART Android 8.0'da yeni bir eşzamanlı sıkıştırmalı çöp toplayıcı (GC) içeriyor. Bu toplayıcı, GC her çalıştırıldığında ve uygulama çalışırken yığını sıkıştırır. Bunun için yalnızca bir kez kısa bir duraklatma yapılır ve bu duraklatma sırasında iş parçacığı kökleri işlenir. Bu özelliğin avantajları şunlardır:
- GC her zaman yığını sıkıştırır: Android 7.0'a kıyasla ortalama% 32 daha küçük yığın boyutları.
- Sıkıştırma, yerel iş parçacığı artışı işaretçisi nesne tahsisine olanak tanır: Tahsisler Android 7.0'a kıyasla% 70 daha hızlıdır.
- H2 karşılaştırması için Android 7.0 GC'ye kıyasla% 85 daha kısa duraklatma süreleri sunar.
- Duraklatma süreleri artık yığın boyutuyla ölçeklenmiyor. Uygulamalar, takılma endişesi olmadan büyük yığınlar kullanabilir.
- GC uygulama ayrıntısı - Okuma engelleri:
- Okuma bariyeri, her nesne alanı okuması için yapılan küçük bir çalışmadır.
- Bunlar derleyicide optimize edilir ancak bazı kullanım alanlarını yavaşlatabilir.
Döngü optimizasyonları
Android 8.0 sürümünde ART, çok çeşitli döngü optimizasyonları kullanır:
- Sınır denetimi için eleman çıkarma işlemleri
- Statik: Aralıkların derleme zamanında sınırlar içinde olduğu kanıtlanmıştır
- Dinamik: Çalışma zamanında yapılan testler, döngülerin sınırlar içinde kalmasını sağlar (aksi takdirde optimizasyondan çıkarılır).
- İndüksiyon değişkeni çıkarma işlemleri
- Ölü indüksiyonunu kaldırın
- Yalnızca döngüden sonra kullanılan indüksiyonu kapalı formlu ifadelerle değiştirin
- Döngü gövdesinde ölü kodun kaldırılması, kullanılmayan döngülerin tamamının kaldırılması
- Güç azaltma
- Döngü dönüşümleri: ters çevirme, değiştirme, bölme, açma, tek modüllü vb.
- SIMD'leştirme (vektorlaştırma olarak da bilinir)
Döngü optimize edici, ART derleyicisinde kendi optimizasyon geçişinde bulunur. Döngü optimizasyonlarının çoğu, diğer yerlerdeki optimizasyonlara ve basitleştirmelere benzer. Çoğu CFG yardımcı programı (bkz. nodes.h), CFG'yi yeniden yazmaya değil, oluşturmaya odaklandığından, CFG'yi normalden daha ayrıntılı bir şekilde yeniden yazan bazı optimizasyonlarda zorluklar ortaya çıkar.
Sınıf hiyerarşisi analizi
Android 8.0'daki ART, sınıf hiyerarşileri analiz edilerek oluşturulan bilgilere göre sanal çağrıları doğrudan çağrılara dönüştüren bir derleyici optimizasyonu olan Sınıf Hiyerarşisi Analizi'ni (CHA) kullanır. Sanal çağrılar, vtable araması etrafında uygulandıkları ve birkaç bağımlı yükleme yaptıkları için pahalıdır. Ayrıca sanal çağrılar da satır içine alınamaz.
İlgili iyileştirmelerin özeti aşağıda verilmiştir:
- Dinamik tek uygulama yöntemi durumu güncelleme: Sınıf bağlama süresinin sonunda, vtable doldurulduğunda ART, süper sınıfın vtable'iyle giriş bazında bir karşılaştırma yapar.
- Derleyici optimizasyonu: Derleyici, bir yöntemin tek uygulama bilgisinden yararlanır. A.foo yönteminde tek uygulama işareti ayarlanmışsa derleyici, sanal çağrıyı doğrudan çağrıya dönüştürür ve sonuç olarak doğrudan çağrıyı satır içi olarak yerleştirmeye çalışır.
- Derlenmiş kodun geçersiz kılınması: Ayrıca, tek uygulama bilgisinin güncellendiği sınıf bağlama süresinin sonunda, daha önce tek uygulamaya sahip olan ancak bu durumun artık geçersiz olduğu A.foo yöntemi varsa A.foo yönteminin tek uygulamaya sahip olduğu varsayımını temel alan tüm derlenmiş kodların geçersiz kılınması gerekir.
- Doğrudan optimizasyondan çıkarma: Yığınta bulunan canlı derlenmiş kod için, doğruluğu garanti etmek amacıyla geçersiz kılınan derlenmiş kodu yorumlayıcı moduna zorlamak üzere doğrudan optimizasyondan çıkarma işlemi başlatılır. Eşzamanlı ve asenkron optimize etme işlemlerinin bir karışımı olan yeni bir optimize etme işlemi mekanizması kullanılacak.
.oat dosyalarındaki satır içi önbellekler
ART artık satır içi önbellekler kullanıyor ve yeterli veri bulunan çağrı sitelerini optimize ediyor. Satır içi önbellekler özelliği, ek çalışma zamanı bilgilerini profillere kaydeder ve derlemeden önce dinamik optimizasyonlar eklemek için kullanır.
Dexlayout
Dexlayout, dex dosyalarını analiz etmek ve bir profile göre yeniden sıralamak için Android 8.0'da kullanıma sunulan bir kitaplıktır. Dexlayout, cihazda boşta bakım derlemesi sırasında dex dosyasının bölümlerini yeniden sıralamak için çalışma zamanındaki profilleme bilgilerini kullanmayı amaçlar. Dex dosyasının genellikle birlikte erişilen bölümleri bir arada gruplandırıldığında, programlar daha iyi yerellik sayesinde daha iyi bellek erişim kalıplarına sahip olabilir, RAM'den tasarruf edebilir ve başlatma süresini kısaltabilir.
Profil bilgileri şu anda yalnızca uygulamalar çalıştırıldıktan sonra kullanılabildiğinden, dexlayout, boşta bakım sırasında dex2oat'ın cihaz üzerinde derlemesine entegre edilir.
Dex önbelleğini kaldırma
Android 7.0'a kadar DexCache nesnesi, DexFile'deki belirli öğelerin sayısına orantılı olarak dört büyük diziye sahipti:
- dize (DexFile::StringId başına bir referans),
- türleri (DexFile::TypeId başına bir referans),
- yöntem (DexFile::MethodId başına bir yerel işaretçi),
- alan (DexFile::FieldId başına bir yerel işaretçi).
Bu diziler, daha önce çözdüğümüz nesnelerin hızlı bir şekilde getirilmesi için kullanılıyordu. Android 8.0'da, yöntem dizisi dışındaki tüm diziler kaldırıldı.
Çevirmen performansı
Android 7.0 sürümünde, temel bir getirme/kod çözme/yorumlama mekanizması içeren bir yorumlayıcı olan "mterp"in kullanıma sunulmasıyla yorumlayıcı performansı önemli ölçüde iyileştirildi. Hızlı Dalvik yorumlayıcısına göre modellenen Mterp; arm, arm64, x86, x86_64, mips ve mips64'ü destekler. Art'ın mterp işlevi, hesaplamalı kod için Dalvik'in hızlı yorumlayıcısına kıyasla yaklaşık olarak aynıdır. Ancak bazı durumlarda bu işlem önemli ölçüde hatta önemli ölçüde daha yavaş olabilir:
- Performansı çağırın.
- Dize değiştirme ve Dalvik'te dahili olarak tanınan yöntemlerin yoğun kullanıcıları.
- Daha yüksek yığın bellek kullanımı.
Android 8.0 bu sorunları giderir.
Daha fazla satır içi ekleme
Android 6.0'dan beri ART, aynı dex dosyaları içindeki tüm çağrıları satır içine alabilir ancak yalnızca farklı dex dosyalarındaki son yöntemleri satır içine alabilir. Bu sınırlamanın iki nedeni vardı:
- Başka bir dex dosyasından iç içe yerleştirme işlemi, çağıranın dex önbelleğini yeniden kullanabilen aynı dex dosyasından iç içe yerleştirme işleminin aksine, söz konusu diğer dex dosyasının dex önbelleğini kullanmalıdır. Derlenmiş kodda, statik çağrılar, dize yükleme veya sınıf yükleme gibi birkaç talimat için dex önbelleği gerekir.
- Yığın haritaları yalnızca mevcut dex dosyasındaki bir yöntem dizini kodlar.
Android 8.0, bu sınırlamaları gidermek için:
- Derlenmiş koddan dex önbelleği erişimini kaldırır ("Dex önbelleği kaldırma" bölümüne de bakın)
- Yığın haritası kodlamasını genişletir.
Senkronizasyon iyileştirmeleri
ART ekibi, MonitorEnter/MonitorExit kod yollarını ayarladı ve ARMv8'deki geleneksel bellek bariyerlerine olan bağımlılığımızı azalttı. Mümkün olduğunda bunları daha yeni (acquire/release) talimatlarla değiştirdi.
Daha hızlı yerel yöntemler
@FastNative
ve @CriticalNative
ek açıklamaları kullanılarak Java Native Interface'a (JNI) daha hızlı yerel çağrılar yapılabilir. Bu yerleşik ART çalışma zamanındaki optimizasyonlar, JNI geçişlerini hızlandırır ve artık desteği sonlandırılmış !bang JNI gösterimini değiştirir. Ek açıklamalar, yerel olmayan yöntemler üzerinde hiçbir etkisi yoktur ve yalnızca bootclasspath
'teki platform Java dili kodu tarafından kullanılabilir (Play Store güncellemeleri yoktur).
@FastNative
ek açıklaması, statik olmayan yöntemleri destekler. Bir yöntem, parametre veya döndürülen değer olarak jobject
'ye erişiyorsa bunu kullanın.
@CriticalNative
ek açıklaması, aşağıdaki kısıtlamalarla yerel yöntemleri çalıştırmanın daha da hızlı bir yolunu sunar:
-
Yöntemler statik olmalıdır. Parametreler, döndürülen değerler veya gizli
this
için nesne kullanılamaz. - Yerel yönteme yalnızca ilkel türler iletilir.
-
Yerel yöntem, işlev tanımında
JNIEnv
vejclass
parametrelerini kullanmıyor. -
Yöntem, dinamik JNI bağlantısına güvenmek yerine
RegisterNatives
ile kaydedilmelidir.
@FastNative
, yerel yöntem performansını 3 kata,
@CriticalNative
ise 5 kata kadar artırabilir. Örneğin, Nexus 6P cihazda ölçülen bir JNI geçişi:
Java Native Interface (JNI) çağrısı | Yürütme süresi (nanosaniye cinsinden) |
---|---|
Normal JNI | 115) |
!bang JNI | 60 |
@FastNative |
35 |
@CriticalNative |
25 |