Ürün Haberleri

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

Okuma süresi: 7 dakika

Modern Android geliştirmede, küçük, hızlı ve güvenli bir uygulama yayınlamak temel bir kullanıcı beklentisidir. Android derleme sisteminin bunu sağlamak için kullandığı temel araç, kullanılmayan kodları ve kaynakları kaldırma, kod yeniden adlandırma veya sadeleştirme ve uygulama optimizasyonu için ölü kodu ve kaynak kaldırma işlemlerini gerçekleştiren derleyici olan R8  optimizasyon aracıdır.

R8'i etkinleştirmek, bir uygulamayı yayınlamaya hazırlarken önemli bir adımdır ancak geliştiricilerin "Keep Rules" şeklinde rehberlik sağlamasını gerektirir.

Bu makaleyi okuduktan sonra YouTube'da R8 optimize edicisini etkinleştirme, hata ayıklama ve sorun giderme ile ilgili Performans Öne Çıkarma Haftası videosuna göz atın.

 

 

Neden Keep kurallarına ihtiyaç duyulur?

Keep kurallarını yazma ihtiyacı temel bir çakışmadan kaynaklanır: R8 bir statik analiz aracıdır ancak Android uygulamaları genellikle yansıtma veya JNI (Java Native Interface) kullanılarak yerel kodda ve yerel koddan yapılan çağrılar gibi dinamik yürütme kalıplarına 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 kodu kullanılmayan olarak tanımlayıp kaldırır. Bu da çalışma zamanında kilitlenmelere neden olur.

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

Saklama kuralları hakkında daha fazla bilgi için resmi kılavuza bakın.

Keep kurallarını nereye yazmalısınız?

Bir uygulama için özel Keep kuralları metin dosyasına yazılır. Bu dosya, kural olarak proguard-rules.pro olarak adlandırılır ve uygulamanın veya kitaplık modülünün kök dizininde bulunur. Bu dosya daha sonra modülünüzün build.gradle.kts dosyasındaki 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 bir kural kümesini içe aktarır. Yanlış dosya kullanıldığında uygulamanız optimize edilmeyebilir. proguard-android-optimize.txt uzantısını kullandığınızdan emin olun. Bu dosya, standart Android bileşenleri için varsayılan Keep 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ış dosyayı kullanma konusunda uyarmaya başlıyoruz. Ayrıca Android Gradle eklentisi 9.0 sürümünden itibaren eski proguard-android.txt dosyası desteklenmeyecek. Bu nedenle, optimize edilmiş sürüme yükselttiğinizden emin olun.

Keep kurallarını 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 bir sınıf spesifikasyonu

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

Keep kuralı anti-pattern'leri

En iyi uygulamaların yanı sıra anti-pattern'ler hakkında da bilgi sahibi olmak önemlidir. Bu anti-pattern'ler genellikle yanlış anlamalardan veya sorun giderme kısayollarından kaynaklanır ve üretim derlemesinin performansı açısından felaketle sonuçlanabilir.

Genel seçenekler

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

-dontotptimize kullanımı, R8'in performans optimizasyonlarını etkili bir şekilde devre dışı bırakarak uygulamanın yavaşlamasına neden olur.

-dontobfuscate kullanılırken tüm yeniden adlandırma işlemleri devre dışı bırakılır ve -dontshrink kullanılırken gereksiz kod kaldırma işlemi devre dışı bırakılır. Bu genel kuralların her ikisi de uygulama boyutunu artırır.

Daha iyi performanslı bir uygulama kullanıcı deneyimi için mümkün olduğunda bu genel işaretleri üretim ortamında kullanmaktan kaçının.

Gereğinden fazla geniş kapsamlı 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 kurallar, R8 optimize edicisinin bu paketteki hiçbir sınıfı veya alt paketlerinin hiçbirini küçültmemesini, karartmamasını ve optimize etmemesini sağlar. Bu, R8'in tüm paketteki avantajlarını tamamen kaldırır. Bunun yerine dar ve spesifik Keep kuralları yazmayı deneyin.
 

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

Ters çevirme operatörü (!)

Olumsuzluk operatörü (!), bir paketi kuralın dışında bırakmak için etkili bir yöntem gibi görünüyor. Ancak bu o kadar basit değildir. Şu örneği ele alalım:

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

Bu kuralın "com.example.package içinde sınıf tutma" anlamına geldiğini düşünebilirsiniz. Ancak bu kural aslında "com.example.package içinde olmayan tüm uygulamadaki her sınıfı, yöntemi ve özelliği tut " anlamına gelir. Bu durum sizi şaşırttıysa R8 yapılandırmanızda olumsuzluk olup olmadığını kontrol etmeniz önerilir.

Android bileşenleri için gereksiz kurallar

Diğer bir yaygın hata ise uygulamanızın Activities, Services veya BroadcastReceivers için saklama kurallarını manuel olarak eklemektir. Bu gereksizdir. Varsayılan proguard-android-optimize.txt dosyası, bu standart Android bileşenlerinin kutudan çıkar çıkmaz çalışması için gerekli 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 Keep Rules ile ilgili sorun varsa sorunun ne olduğunu öğrenmek için kitaplığın yazarıyla iletişime geçmeniz önerilir.

Kural en iyi uygulamaları

Neler yapmamanız gerektiğini öğrendiğinize göre şimdi en iyi uygulamalardan bahsedelim.

Dar kapsamlı Keep kuralları yazma

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

KuralKalite

 

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

 

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

 

-keep class com.example.MyClass { ; }

 

Düşük: Muhtemelen hâlâ çok geniş olan bir sınıfın tamamını korur.
-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 ataları kullanma

Birden fazla farklı veri modeli için ayrı 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 üyelerini tutmasını söyler ve oldukça ö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 ek açıklamaları kullanma

Özel bir açıklama (ör. @Serialize) oluşturun ve alanlarının korunması gereken sınıfları "etiketlemek" için kullanın. Bu da başka bir temiz, bildirimsel ve son derece ölçeklenebilir kalıptır. Kullandığınız çerçevelerdeki mevcut notlar için de Keep kuralları oluşturabilirsiniz.

# Keep all fields of any class annotated with @Serialize

-keepclassmembers class * {

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

}

Doğru Keep seçeneğini belirleme

Kuralın en önemli kısmı, saklama seçeneğidir. Yanlış olanı seçmek, optimizasyonu gereksiz yere devre dışı bırakabilir.

Keep SeçeneğiNe yapar?
-keepSınıfın ve bildirimde belirtilen üyelerin  kaldırılmasını veya yeniden adlandırılmasını önler.
-keepclassmembersBelirtilen üyelerin kaldırılmasını veya yeniden adlandırılmasını önler ancak sınıfın kendisinin kaldırılmasına izin verir. Bu işlem yalnızca başka şekilde kaldırılmayan sınıflarda yapılabilir.
-keepclasseswithmembersBirleştirme: Belirtilen tüm üyeler mevcut olduğu takdirde sınıf ve üyeleri korunur.

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

Değiştiricilerle optimizasyona izin ver

allowshrinking ve allowobfuscation gibi değiştiriciler, geniş bir -keep kuralını gevşeterek optimizasyon gücünü R8'e geri verir. Örneğin, eski bir kitaplık tüm sınıfta -keep kullanmanızı gerektiriyorsa küçültme ve karartmaya izin vererek bir miktar optimizasyon elde edebilirsiniz:

# 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

Daha fazla optimizasyon sağlamak için saklama kurallarının yanı sıra R8 yapılandırma dosyanıza genel işaretler de ekleyebilirsiniz.

-repackageclasses, R8'e tüm karartılmış sınıfları tek bir pakete taşımasını söyleyen güçlü bir seçenektir. Bu, gereksiz paket adı dizelerini kaldırarak DEX dosyasında önemli ölçüde yer tasarrufu sağlar.

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

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

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. 

Kütüphaneler için en iyi uygulamalar

Her Android uygulaması, kitaplıklara bir şekilde bağımlıdır. Şimdi de kitaplıklarla ilgili en iyi uygulamalardan bahsedelim.

Kitaplık geliştiriciler için

Kitaplığınız yansıtma veya JNI kullanıyorsa tüketicilerine gerekli Keep kurallarını sağlama sorumluluğu size aittir. Bu kurallar, consumer-rules.pro dosyasına yerleştirilir ve ardından kitaplığın AAR dosyası içinde otomatik olarak paketlenir.

android {

    defaultConfig {

        consumerProguardFiles("consumer-rules.pro")

    }

    ...

}

Kitaplık tüketicileri için

Sorunlu Keep kurallarını filtreleme

Sorunlu Keep kuralları içeren bir kitaplık kullanmanız gerekiyorsa AGP 9.0'dan itibaren bu kuralları 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, Keep kurallarını yazma ihtiyacını tamamen ortadan kaldırmaktır. Birçok uygulama için, yansıtma yerine kod oluşturmayı tercih eden modern kitaplıklar seçilerek bu hedefe ulaşılabilir.Kod oluşturma sayesinde optimize edici, çalışma zamanında hangi kodun gerçekten kullanıldığını ve hangi kodun kaldırılabileceğini daha kolay belirleyebilir. Ayrıca dinamik yansıtma kullanılmadığı için "gizli" giriş noktaları yoktur ve bu nedenle Keep kurallarına gerek yoktur. Yeni bir kitaplık seçerken her zaman yansıtma yerine kod oluşturma kullanan bir çözümü tercih edin.

Kitaplık seçme hakkında daha fazla bilgi için Kitaplık seçimiyle ilgili önemli noktalar 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 büyük olduğunda sorunu teşhis etmek için bu araçları kullanın.

Yinelenen ve genel Keep kurallarını bulma

R8, kuralları düzinelerce kaynaktan 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

Bu dosyada arama yaparak gereksiz kuralları bulabilir veya sorunlu bir kuralı (ör. -dontoptimize) onu içeren belirli kitaplığa kadar takip edebilirsiniz.

R8'e sorun: Bunu neden saklıyorsunuz?

Kaldırılmasını beklediğiniz bir sınıf uygulamanızda hâlâ varsa 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 

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

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 çalışmasının 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 dikkatli bir şekilde seçerek tam olarak gerekli olanları saklayabilirsiniz. En gelişmiş uygulama, yansımaya dayalı olanların yerine modern, kod oluşturmaya dayalı kitaplıklar seçerek kurallara olan ihtiyacı tamamen ortadan kaldırmaktır.

Performans Işığı Haftası'nı takip ederken YouTube'daki Işığı Haftası videolarını izlemeyi ve R8 mücadelemize katılmayı unutmayın. R8'i etkinleştirme veya R8 ile ilgili sorun giderme hakkında sorularınız varsa #optimizationEnabled etiketini kullanın. Size yardım etmek için buradayız.

Avantajları kendiniz keşfetme zamanı.

Uygulamanızda 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 kullanıyorsanız proguard-android-optimize.txt ile değiştirin.
  3. Ardından etkiyi ölçün. Farkı sadece hissetmeyindoğrulayın. Başlangıç sürelerinizi önce ve sonra ölçmek için  GitHub'daki Macrobenchmark örnek uygulamamızdaki kodu uyarlayarak performans kazançlarınızı ölçün.

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

Sorularınızı iletmek için #AskAndroid sosyal medya etiketini kullanabilirsiniz. Uzmanlarımız hafta boyunca sorularınızı takip edip yanıtlar.

Yarın, temel ve başlangıç profilleriyle profile guided optimization hakkında konuşacağımız, Compose oluşturma performansının son sürümlerde nasıl iyileştiğini ve arka plan çalışmasıyla ilgili performans değerlendirmelerini paylaşacağımız için bizi takip etmeye devam edin.

Yazan:

Okumaya devam edin