Sürekli Entegrasyonda Karşılaştırma

Sürekli Entegrasyon (CI) modunda karşılaştırmalar çalıştırarak uygulamanız henüz yayınlanmadan önce zaman içindeki performansı izleyebilir ve performans regresyonlarını veya iyileştirmeleri belirleyebilirsiniz. Bu sayfada, CI'da karşılaştırma hakkında temel bilgiler verilmektedir.

CI'da karşılaştırmaya başlamadan önce, sonuçları yakalama ve değerlendirmenin normal testlerden ne açıdan farklı olduğunu düşünün.

Bulanık sonuçlar

Karşılaştırmalar araçlı testlerdir, ancak sonuçlar yalnızca başarılı veya başarısız değildir. Karşılaştırmalar, çalıştıkları cihaz için zamanlama ölçümleri sağlar. Sonuçların zaman içindeki grafiğini oluşturmak, ölçüm sistemindeki değişimi izlemenize ve gürültüyü gözlemlemenize olanak tanır.

Gerçek cihazlar kullan

Fiziksel Android cihazlarda karşılaştırmalar yapabilirsiniz. Emülatörlerde çalışabilseler de gerçekçi bir kullanıcı deneyimi sunmadığı ve bunun yerine ana makinenin işletim sistemine ve donanım özelliklerine bağlı sayılar sağladığı için bu kullanım kesinlikle önerilmez. Gerçek cihazlar veya gerçek cihazlarda test çalıştırmanızı sağlayan Firebase Test Lab gibi bir hizmet kullanmayı düşünün.

Karşılaştırmaları çalıştırın

Karşılaştırmaları CI ardışık düzeninizin bir parçası olarak çalıştırmak, Android Studio'dan yerel olarak çalıştırmaktan farklı olabilir. Yerel olarak, Android entegrasyon testlerini genellikle bir Gradle connectedCheck göreviyle çalıştırırsınız. Bu görev, otomatik olarak APK'nızı oluşturup APK'yı test eder ve testleri CI sunucusuna bağlı cihazlarda çalıştırır. CI'da çalışırken bu akışın genellikle ayrı aşamalara bölünmesi gerekir.

Topluluk

Microbenchmark kitaplığı için assemble[VariantName]AndroidTest numaralı Gradle görevini çalıştırın. Bu görev, hem uygulama kodunuzu hem de test ettiğiniz kodu içeren test APK'nızı oluşturur.

Alternatif olarak, Makrobenchmark kitaplığı hedef APK'nızı oluşturmanızı ve APK'yı ayrı olarak test etmenizi gerektirir. Bu nedenle :app:assemble[VariantName] ve :macrobenchmark:assemble[VariantName] Gradle görevlerini çalıştırın.

Yükle ve çalıştır

Bu adımlar genellikle Gradle görevlerini çalıştırmaya gerek kalmadan gerçekleştirilir. Bu metriklerin, gerçek cihazlarda test çalıştırmanızı sağlayan bir hizmet kullanıp kullanmamanıza bağlı olarak soyutlanabileceğini unutmayın.

Yükleme için adb install komutunu kullanın ve test APK'sını veya hedef APK'yı belirtin.

Tüm karşılaştırmaları çalıştırmak için adb shell am aracı komutunu çalıştırın:

adb shell am instrument -w com.example.benchmark/androidx.benchmark.junit4.AndroidBenchmarkRunner

Makrobenchmark kitaplığını kullanırken araç çalıştırıcı olarak normal androidx.test.runner.AndroidJUnitRunner kullanın.

-e bağımsız değişkenini kullanarak, Gradle yapılandırmasındaki aynı araç bağımsız değişkenlerini aktarabilirsiniz. Tüm araç bağımsız değişkeni seçenekleri için Makrobenchmark için Microbenchmark Enstrümantasyon Bağımsız Değişkenleri veya Araç bağımsız değişkenleri ekleme bölümüne bakın.

Örneğin, dryRunMode bağımsız değişkenini, pull isteği doğrulama işleminizin bir parçası olarak mikro karşılaştırmaları çalıştıracak şekilde ayarlayabilirsiniz. Bu işaret etkinleştirildiğinde, mikro karşılaştırmalar yalnızca tek bir döngüde çalıştırılır ve böylece doğru bir şekilde çalıştıklarını (ancak yürütülmesi çok uzun sürmez) doğrulanır.

adb shell am instrument -w -e "androidx.benchmark.dryRunMode.enable" "true" com.example.benchmark/androidx.benchmark.junit4.AndroidBenchmarkRunner

Araç testlerinin komut satırından nasıl çalıştırılacağı hakkında daha fazla bilgi edinmek için ADB ile testleri çalıştırma bölümüne bakın.

Kilitli saatler

Microbenchmark Gradle eklentisi, rootlanmış bir cihazın CPU saatlerini kilitlemek için ./gradlew lockClocks komutunu sağlar. Bu, "userdebug" derlemeleri gibi rootlanmış cihazlara erişiminiz olduğunda kararlılık sağlamak için faydalıdır. Bu işlemi, kitaplığın kaynağında bulunan lockClocks.sh kabuk komut dosyasıyla çoğaltabilirsiniz.

Komut dosyasını doğrudan bir Linux veya Mac ana makinesinden çalıştırabilir veya birkaç adb komutuyla cihaza aktarabilirsiniz:

adb push path/lockClocks.sh /data/local/tmp/lockClocks.sh
adb shell /data/local/tmp/lockClocks.sh
adb shell rm /data/local/tmp/lockClocks.sh

Kabuk komut dosyasını doğrudan bir ana makinede çalıştırırsanız bu komutları bağlı bir cihaza gönderir.

CPU saatlerini kilitlemenin neden yararlı olduğu hakkında daha fazla bilgi edinmek için tutarlı karşılaştırmalar elde etme konusunu inceleyin.

Sonuçları toplama

Karşılaştırma kitaplıkları, her karşılaştırma çalıştırmasından sonra Android destekli cihazdaki bir dizinde profil oluşturma izleriyle birlikte JSON'deki ölçümleri gösterir. Makrobenchmark kitaplığı, her MacrobenchmarkRule.measureRepeated döngüsünün her iterasyonu için bir adet olmak üzere birden fazla perfetto izleme dosyası verir. Bununla birlikte, Microbenchmark her bir BenchmarkRule.measureRepeated yinelemesinin tüm iterasyonları için yalnızca bir izleme dosyası oluşturur. Profil oluşturma izleme dosyalarının çıktısı da aynı dizinde verilir.

Dosyaları kaydedin ve bulun

Karşılaştırmaları Gradle ile çalıştırırsanız bu dosyalar otomatik olarak ana bilgisayarınızın build/outputs/connected_android_test_additional_output/debugAndroidTest/connected/ altındaki çıkışlar dizinine kopyalanır.

Doğrudan adb komutuyla çalışıyorsanız dosyaları manuel olarak almanız gerekir. Varsayılan olarak raporlar, cihaz üzerinde test edilen uygulamanın harici depolama alanının medya dizinine kaydedilir. Kitaplık, kolaylık sağlamak için dosyanın yolunu Logcat'e yazdırır. Karşılaştırmaların çalıştırıldığı Android sürümüne bağlı olarak çıkış klasörünün farklı olabileceğini unutmayın.

Benchmark: writing results to /storage/emulated/0/Android/media/com.example.macrobenchmark/com.example.macrobenchmark-benchmarkData.json

Ayrıca, additionalTestOutputDir araç bağımsız değişkenini kullanarak karşılaştırma raporlarının cihazda kaydedildiği konumu yapılandırabilirsiniz. Bu klasör, uygulamanız tarafından yazılabilir olmalıdır.

adb shell am instrument -w -e additionalTestOutputDir /sdcard/Download/ com.example.benchmark/androidx.benchmark.junit4.AndroidBenchmarkRunner

Android 10 (API düzeyi 29) ve sonraki sürümlerde uygulamanızın testleri varsayılan olarak bir depolama korumalı alanında çalıştırılır. Bu durum, uygulamanızın uygulamaya özel dizin dışındaki dosyalara erişmesini engeller. /sdcard/Download gibi global bir dizine kaydedebilmek için aşağıdaki araç bağımsız değişkenini iletin:

-e no-isolated-storage true

Karşılaştırmanızın manifest dosyasında eski depolama seçeneklerine açıkça izin vermeniz de gerekir:

<application android:requestLegacyExternalStorage="true" ... >

Daha fazla bilgi için Kapsamlı depolamayı geçici olarak devre dışı bırakma bölümüne bakın.

Dosyaları alma

Oluşturulan dosyaları cihazdan almak için, belirtilen dosyayı ana makinenizdeki geçerli dizine çeken adb pull komutunu kullanın:

adb pull /storage/emulated/0/Android/media/com.example.macrobenchmark/com.example.macrobenchmark-benchmarkData.json

Belirtilen klasörden tüm benchmarkData öğelerini almak için aşağıdaki snippet'i kontrol edin:

# The following command pulls all files ending in -benchmarkData.json from the directory
# hierarchy starting at the root /storage/emulated/0/Android.
adb shell find /sdcard/Download -name "*-benchmarkData.json" | tr -d '\r' | xargs -n1 adb pull

İzleme dosyaları (.trace veya .perfetto-trace) benchmarkData.json ile aynı klasöre kaydedildiği için bu dosyaları aynı şekilde toplayabilirsiniz.

Karşılaştırma verileri örneği

Karşılaştırma kitaplıkları, karşılaştırmaların çalıştırıldığı cihaz ve çalıştırılan gerçek karşılaştırmalarla ilgili bilgileri içeren JSON dosyaları oluşturur. Aşağıdaki snippet, oluşturulan JSON dosyasını temsil eder:

{
    "context": {
        "build": {
            "brand": "google",
            "device": "blueline",
            "fingerprint": "google/blueline/blueline:12/SP1A.210812.015/7679548:user/release-keys",
            "model": "Pixel 3",
            "version": {
                "sdk": 31
            }
        },
        "cpuCoreCount": 8,
        "cpuLocked": false,
        "cpuMaxFreqHz": 2803200000,
        "memTotalBytes": 3753299968,
        "sustainedPerformanceModeEnabled": false
    },
    "benchmarks": [
        {
            "name": "startup",
            "params": {},
            "className": "com.example.macrobenchmark.startup.SampleStartupBenchmark",
            "totalRunTimeNs": 4975598256,
            "metrics": {
                "timeToInitialDisplayMs": {
                    "minimum": 347.881076,
                    "maximum": 347.881076,
                    "median": 347.881076,
                    "runs": [
                        347.881076
                    ]
                }
            },
            "sampledMetrics": {},
            "warmupIterations": 0,
            "repeatIterations": 3,
            "thermalThrottleSleepSeconds": 0
        }
    ]
}

Ek kaynaklar