Ürün Haberleri

R8 saklama kurallarını yapılandırma ve sorunlarını giderme

Okuma süresi: 7 dk.

Modern Android geliştirmede, küçük, hızlı ve güvenli bir uygulama sunmak temel bir kullanıcı beklentisidir. Android derleme sisteminin bunu başarmak için kullandığı birincil araç, R8  optimizasyon aracıdır. Bu derleyici, küçültme, kod yeniden adlandırma veya sadeleştirme ve uygulama optimizasyonu için kullanılmayan kod ve kaynak kaldırma işlemlerini gerçekleştirir.

R8'i etkinleştirmek, bir uygulamayı yayınlanmaya hazırlama sürecinde kritik bir adımdır ancak geliştiricilerin "Keep kuralları" şeklinde rehberlik sağlamasını gerektirir.

Bu makaleyi okuduktan sonra, YouTube'da R8 optimize ediciyi etkinleştirme, hata ayıklama ve sorun giderme ile ilgili Performance Spotlight Week videosuna göz atın.

 

 

Saklama kurallarına neden ihtiyaç duyulur?

Keep kuralları yazma ihtiyacı, temel bir çelişkiden kaynaklanır: R8 statik bir analiz aracıdır ancak Android uygulamaları genellikle yansıma gibi dinamik yürütme kalıplarına veya JNI (Java Yerel Arayüzü) kullanarak yerel kodun içine ve dışına yapılan çağrılara dayanır.

R8, doğrudan çağrıları analiz ederek kullanılan kodun grafiğini oluşturur. Koda dinamik bir şekilde erişildiğinde R8'in statik analizi bunu tahmin edemez ve bu kodu kullanılmayan olarak tanımlayıp kaldırır. Bu da çalışma zamanı kilitlenmelerine yol açar.

Saklama kuralı, R8 derleyicisine verilen açık bir talimattır: "Bu sınıf, yöntem veya alan, çalışma zamanında dinamik olarak erişilecek bir giriş noktasıdır. Doğrudan bir referans bulamasanız bile bu bilgiyi saklamanız gerekir."

Saklama kuralları hakkında daha fazla bilgi için resmi kılavuzu inceleyin.

Saklama kuralları nerede yazılır?

Bir uygulama için özel saklama kuralları metin dosyasına yazılır. Bu dosya, kural gereği proguard-rules.pro olarak adlandırılır ve uygulama veya kitaplık modülünün kök dizininde bulunur. Bu dosya daha sonra modülünüzün build.gradle.kts dosyasının release derleme türünde belirtilir.

release {

    isShrinkResources = true

    isMinifyEnabled = true

    proguardFiles(

        getDefaultProguardFile("proguard-android-optimize.txt"),

        "proguard-rules.pro",

    )

}

Doğru varsayılan dosyayı kullanma

getDefaultProguardFile yöntemi, Android SDK tarafından sağlanan varsayılan kural grubunu içe aktarır. Yanlış dosya kullanıldığında uygulamanız optimize edilmeyebilir. proguard-android-optimize.txt kullandığınızdan emin olun. Bu dosya, standart Android bileşenleri için varsayılan saklama kurallarını sağlar ve R8'in kod optimizasyonlarını etkinleştirir. Eski proguard-android.txt yalnızca saklama kurallarını sağlar ancak R8'in optimizasyonlarını etkinleştirmez.

progaurd.png

Bu ciddi bir performans sorunu olduğundan, Android Studio Narwhal 3 Feature Drop'tan itibaren geliştiricileri yanlış dosya kullanımı konusunda uyarmaya başlıyoruz. Ayrıca Android Gradle Eklentisi 9.0 sürümünden itibaren, eski proguard-android.txt dosyasını artık desteklemiyoruz. Bu nedenle, optimize edilmiş sürüme geçiş yaptığınızdan emin olun.

Saklama kuralları yazma

Saklama kuralı üç ana bölümden oluşur:

  1. -keep veya -keepclassmembers gibi bir seçenek 
  2. allowshrinking gibi isteğe bağlı değiştiriciler
  3. Eşleştirilecek kodu tanımlayan sınıf spesifikasyonu

Söz diziminin tamamı ve örnekler için Keep kuralları ekleme ile ilgili kılavuza bakın.

Saklama kuralı anti-pattern'leri

En iyi uygulamaların yanı sıra anti-pattern'leri de bilmek önemlidir. Bu anti-pattern'ler genellikle yanlış anlamalardan veya sorun giderme kısayollarından kaynaklanır ve üretim derlemesinin performansı açısından yıkıcı olabilir.

Genel seçenekler

Bu işaretler, yayınlanan derlemelerde asla kullanılmaması gereken genel açma/kapatma düğmeleridir. Yalnızca bir sorunu izole etmek için geçici olarak hata ayıklama amacıyla kullanılır.

-dontotptimize kullanıldığında R8'in performans optimizasyonları devre dışı bırakılır ve uygulama yavaşlar.

-dontobfuscate kullanıldığında tüm yeniden adlandırma işlemleri devre dışı bırakılır, -dontshrink kullanıldığında ise ölü kod kaldırma işlemi devre dışı bırakılır. Bu genel kuralların her ikisi de uygulama boyutunu artırır.

Daha yüksek performanslı bir uygulama kullanıcı deneyimi için mümkün olduğunca bu global işaretleri üretim ortamında kullanmaktan kaçının.

Aşırı geniş saklama kuralları

R8'in avantajlarını geçersiz kılmanın en kolay yolu, aşırı geniş kapsamlı saklama kuralları yazmaktır. Aşağıdaki gibi saklama kuralları, R8 optimize ediciye bu paketteki veya alt paketlerindeki hiçbir sınıfı küçültmemesini, karartmamasını ve optimize etmemesini söyler. Bu, R8'in tüm paket için sağladığı avantajları tamamen ortadan kaldırır. Bunun yerine dar kapsamlı ve spesifik saklama kuralları yazmaya çalışın.
 

-keep class com.example.package.** { *;} // WIDE KEEP RULES CAUSE PROBLEMS

Ters çevirme operatörü (!)

Ters çevirme operatörü (!), bir paketi kuraldan hariç tutmanın etkili bir yolu gibi görünüyor. Ancak bu o kadar basit değil. Şu örneği ele alalım:

-keep class !com.example.my_package.** { *; } // USE WITH CAUTION

Bu kuralın "com.example.package içindeki sınıfları saklama" anlamına geldiğini düşünebilirsiniz. Ancak aslında "com.example.package içinde olmayan tüm uygulama genelindeki her sınıfı, yöntemi ve özelliği sakla " anlamına gelir. Bu durum sizi şaşırttıysa R8 yapılandırmanızda olumsuzlama olup olmadığını kontrol etmenizi öneririz.

Android bileşenleri için gereksiz kurallar

Sık yapılan bir diğer hata da uygulamanızın Activities, Services veya BroadcastReceivers için manuel olarak saklama kuralları eklemektir. Bu gereksizdir. Varsayılan proguard-android-optimize.txt dosyası, bu standart Android bileşenlerinin kullanıma hazır şekilde çalışması için gereken kuralları zaten içerir.

Ayrıca birçok kitaplık kendi saklama kurallarını getirir. Bu nedenle, bunlar için kendi kurallarınızı yazmanız gerekmez. Kullandığınız bir kitaplıktaki saklama kurallarıyla ilgili sorun varsa sorunun ne olduğunu öğrenmek için kitaplık yazarıyla iletişime geçmeniz önerilir.

Saklama kuralıyla ilgili en iyi uygulamalar

Nelerden kaçınmanız gerektiğini öğrendiğinize göre, şimdi en iyi uygulamalardan bahsedelim.

Dar kapsamlı saklama kuralları yazma

İyi saklama kuralları, mümkün olduğunca dar kapsamlı ve spesifik olmalıdır. Yalnızca gerekli olanları korumalı, diğer her şeyi R8'in optimize etmesine izin vermelidirler.
 

KuralKalite

 

-keep class com.example.** { ; }

 

Düşük: Bir paketin tamamını ve alt paketlerini saklar.

 

-keep class com.example.MyClass { ; }

 

Düşük: Sınıfın tamamını korur. Bu sınıf muhtemelen hâlâ çok geniştir.
-keepclassmembers class com.example.MyClass {

    private java.lang.String secretMessage;

    public void onNativeEvent(java.lang.String);

}
Yüksek: Yalnızca belirli bir sınıftaki alakalı yöntemler ve özellikler korunur.

Ortak üst öğeleri kullanma

Birden fazla farklı veri modeli için ayrı saklama kuralları yazmak yerine, ortak bir temel sınıfı veya arayüzü hedefleyen tek bir kural yazın. Aşağıdaki kural, R8'e bu arayüzü uygulayan sınıfların tüm üyelerini tutmasını söyler ve yüksek düzeyde ölçeklenebilirdir.

# Keep all fields of any class that implements SerializableModel

-keepclassmembers class * implements com.example.models.SerializableModel {

    <fields>;

}

Birden fazla sınıfı hedeflemek için notları kullanma

Özel bir ek açıklama (ör. @Serialize) oluşturun ve bunu, alanlarının korunması gereken sınıfları "etiketlemek" için kullanın. Bu da başka bir temiz, açıklayıcı ve yüksek düzeyde ölçeklenebilir kalıptır. Kullandığınız çerçevelerdeki mevcut ek açıklamalar için de saklama kuralları oluşturabilirsiniz.

# Keep all fields of any class annotated with @Serialize

-keepclassmembers class * {

    @com.example.annotations.Serialize <fields>;

}

Doğru saklama seçeneğini belirleme

Saklama seçeneği, kuralın en önemli kısmıdır. Yanlış seçeneği belirlemek, optimizasyonun gereksiz yere devre dışı bırakılmasına neden olabilir.

Keep seçeneğiİşlevi
-keepBildirimde belirtilen sınıfın ve üyelerin  kaldırılmasını veya yeniden adlandırılmasını engeller.
-keepclassmembersBelirtilen üyelerin kaldırılmasını veya yeniden adlandırılmasını engeller ancak sınıfın kendisinin kaldırılmasına izin verir. Bu işlem yalnızca başka bir şekilde kaldırılmamış sınıflarda yapılabilir.
-keepclasseswithmembersKombinasyon: Yalnızca belirtilen tüm üyeler mevcutsa sınıfı ve üyelerini korur.

Saklama seçeneği hakkında daha fazla bilgiyi Saklama Seçenekleri ile ilgili dokümanlarımızda bulabilirsiniz.

Değiştiricilerle optimizasyona izin ver

allowshrinking ve allowobfuscation gibi değiştiriciler, geniş bir -keep kuralını esneterek optimizasyon gücünü R8'e geri verir. Örneğin, eski bir kitaplık sizi tüm bir sınıfta -keep kullanmaya zorluyorsa küçültme ve kod karartmaya izin vererek optimizasyonun bir kısmını geri kazanabilirsiniz:

# Keep this class, but allow R8 to remove it if it's unused and allow R8 to rename it.

-keep,allowshrinking,allowobfuscation class com.example.LegacyClass

Ek optimizasyon için genel seçenekler ekleme

Saklama kurallarının yanı sıra, daha fazla optimizasyon için R8 yapılandırma dosyanıza genel işaretler ekleyebilirsiniz.

-repackageclasses, R8'e tüm kod karartılmış sınıfları tek bir pakete taşıma talimatı veren güçlü bir seçenektir. Bu sayede, gereksiz paket adı dizeleri kaldırılarak DEX dosyasında önemli ölçüde yer tasarrufu sağlanır.

-allowaccessmodification, R8'in daha agresif satır içi eklemeyi etkinleştirmek için erişimi genişletmesine (ör. private - public) olanak tanır. Bu özellik artık proguard-android-optimize.txt kullanılırken varsayılan olarak etkindir.

Uyarı: Kitaplık yazarları, bu genel optimizasyon işaretlerini tüketici kurallarına asla eklememelidir. Aksi takdirde, bu işaretler tüm uygulamaya zorunlu olarak uygulanır.

Bu durumu daha da netleştirmek için Android Gradle eklentisinin 9.0 sürümünde, kitaplıklardaki genel optimizasyon işaretlerini tamamen yok saymaya başlayacağız. 

Kitaplıklar için en iyi uygulamalar

Her Android uygulaması şu veya bu şekilde kitaplıklardan yararlanır. Şimdi kütüphanelerle ilgili en iyi uygulamalardan bahsedelim.

Kitaplık geliştiricileri için

Kitaplığınızda yansıma veya JNI kullanılıyorsa gerekli saklama kurallarını tüketicilerine sağlamak sizin sorumluluğunuzdadır. Bu kurallar bir consumer-rules.pro dosyasına yerleştirilir ve ardından otomatik olarak kitaplığın AAR dosyasında paketlenir.

android {

    defaultConfig {

        consumerProguardFiles("consumer-rules.pro")

    }

    ...

}

Kitaplık kullanıcıları için

Sorunlu saklama kurallarını filtreleme

Sorunlu Keep kuralları içeren bir kitaplık kullanmanız gerekiyorsa AGP 9.0'dan itibaren bunları build.gradle.kts dosyanızda filtreleyebilirsiniz. Bu, R8'e belirli bir bağımlılıktan gelen kuralları yoksaymasını söyler.

release {

    optimization.keepRules {

        // Ignore all consumer rules from this specific library

        it.ignoreFrom("com.somelibrary:somelibrary")

    }

}

En iyi saklama kuralı, saklama kuralı olmamasıdır

En iyi R8 yapılandırma stratejisi, saklama kuralları yazma ihtiyacını tamamen ortadan kaldırmaktır. Birçok uygulama için bu, yansıma yerine kod oluşturmayı tercih eden modern kitaplıklar seçilerek sağlanabilir. Kod oluşturma sayesinde optimize edici, çalışma zamanında hangi kodun kullanıldığını ve hangi kodun kaldırılabileceğini daha kolay belirleyebilir. Ayrıca, dinamik yansıtma kullanılmaması "gizli" giriş noktalarının olmadığı ve bu nedenle Keep kurallarına gerek olmadığı anlamına gelir. Yeni bir kitaplık seçerken her zaman yansıma yerine kod oluşturma kullanan bir çözümü tercih edin.

Kitaplık seçme hakkında daha fazla bilgi için Kitaplıkları akıllıca seçme başlıklı makaleyi inceleyin.

R8 yapılandırmanızda hata ayıklama ve sorun giderme

R8, tutması gereken kodu kaldırdığında veya APK'nız beklenenden daha büyük olduğunda sorunu teşhis etmek için bu araçları kullanın.

Yinelenen ve genel saklama kurallarını bulma

R8, onlarca kaynaktan gelen kuralları birleştirdiği için "nihai" kural kümesinin ne olduğunu bilmek zor olabilir. Bu işareti proguard-rules.pro dosyanıza eklediğinizde eksiksiz bir rapor oluşturulur:

# Outputs the final, merged set of rules to the specified file

-printconfiguration build/outputs/logs/configuration.txt

Gereksiz kuralları bulmak veya sorunlu bir kuralı (ör. -dontoptimize) içeren belirli kitaplığa kadar izlemek için bu dosyada arama yapabilirsiniz.

R8'e sorun: Bunu neden saklıyorsunuz?

Kaldırılmasını beklediğiniz bir sınıf hâlâ uygulamanızda görünüyorsa R8 bunun nedenini size söyleyebilir. Şu kuralı eklemeniz yeterlidir:

# Asks R8 to explain why it's keeping a specific class

class com.example.MyUnusedClass

-whyareyoukeeping 

Derleme sırasında R8, bu sınıfı tutmasına neden olan tam referans zincirini yazdırır. Böylece referansı izleyebilir ve kurallarınızı düzenleyebilirsiniz.

Tam kılavuz için R8 sorunlarını giderme bölümüne göz atın.

Sonraki adımlar

R8, Android uygulama performansını artırmak için güçlü bir araçtır. Etkinliği, statik analiz motoru olarak işleyişinin doğru anlaşılmasına bağlıdır.

Üye düzeyinde belirli kurallar yazarak, üst öğelerden ve ek açıklamalardan yararlanarak ve doğru saklama seçeneklerini dikkatlice belirleyerek tam olarak gerekli olan verileri saklayabilirsiniz. En gelişmiş uygulama, yansıma tabanlı öncülleri yerine modern, kod oluşturma tabanlı kitaplıkları seçerek kurallara olan ihtiyacı tamamen ortadan kaldırmaktır.

Performans Öne Çıkanlar Haftası'nı takip ederken YouTube'daki bugünkü Öne Çıkanlar Haftası videosuna göz atmayı ve R8 yarışmamıza devam etmeyi unutmayın. R8'i etkinleştirme veya sorun giderme ile ilgili sorularınız için #optimizationEnabled etiketini kullanın. Yardımcı olmaya hazırız.

Avantajları kendiniz görme zamanı geldi.

Uygulamanız için R8 tam modunu bugün etkinleştirmenizi öneririz.

  1. Başlamak için geliştirici kılavuzlarımızı inceleyin: Uygulama optimizasyonunu etkinleştirme.
  2. Hâlâ proguard-android.txt kullanıp kullanmadığınızı kontrol edin ve proguard-android-optimize.txt ile değiştirin.
  3. Ardından etkiyi ölçün. Farkı yalnızca hissetmekle kalmayın, doğrulayın. Başlatma sürelerinizi öncesi ve sonrası olarak ölçmek için  GitHub'daki Macrobenchmark örnek uygulamamızın kodunu uyarlayarak performans artışınızı ölçün.

Uygulamanızın performansında önemli bir iyileşme göreceğinizden eminiz.

Bu arada, sorularınızı sormak için #AskAndroid sosyal etiketini kullanabilirsiniz. Uzmanlarımız hafta boyunca sorularınızı takip edip yanıtlayacak.

Yarın, Temel ve Başlangıç Profilleri ile Profile Göre Optimizasyon'dan bahsedecek, Compose oluşturma performansının son sürümlerde nasıl iyileştirildiğini ve arka plan çalışmalarıyla ilgili performans konularını paylaşacağız.

Yazan:
Okumaya devam et