Mikro Karşılaştırma Yazma

Uygulama kodunuzda değişiklikler yaparak Microbenchmark kitaplığını nasıl kullanacağınızı öğrenmek için Hızlı başlangıç bölümüne bakın. Kod tabanınızda daha karmaşık değişiklikler yaparak tam kurulumu nasıl tamamlayacağınızı öğrenmek için Tam proje kurulumu bölümüne bakın.

Hızlı başlangıç kılavuzu

Bu bölümde, kodu modüllere taşımaya gerek kalmadan karşılaştırmayı nasıl deneyeceğiniz ve tek seferlik ölçümleri nasıl çalıştıracağınız gösterilmektedir. Doğru performans sonuçları için bu adımlarda uygulamanızda hata ayıklamanın devre dışı bırakılması gerekir. Bu nedenle, değişiklikleri kaynak kontrol sisteminize kaydetmeden yerel bir çalışma kopyasında saklayın.

Tek seferlik karşılaştırma yapmak için aşağıdakileri yapın:

  1. Kitaplığı, modülünüzün build.gradle veya build.gradle.kts dosyasına ekleyin:

    Kotlin

    dependencies {
        implementation("androidx.benchmark:benchmark-junit4:1.2.4")
    }

    Modern

    dependencies {
        implementation 'androidx.benchmark:benchmark-junit4:1.2.4'
    }

    androidTestImplementation bağımlılığı yerine implementation bağımlılığı kullanın. androidTestImplementation kullanırsanız kitaplık manifest dosyası uygulama manifest dosyasıyla birleştirilmediği için karşılaştırmalar çalıştırılamaz.

  2. debug derleme türünü, hata ayıklanabilir olmayacak şekilde güncelleyin:

    Kotlin

    android {
        ...
        buildTypes {
            debug {
                isDebuggable = false
            }
        }
    }

    Modern

    android {
        ...
        buildTypes {
            debug {
                debuggable false
            }
        }
    }
  3. testInstrumentationRunner değerini AndroidBenchmarkRunner olarak değiştirin:

    Kotlin

    android {
        ...
        defaultConfig {
            testInstrumentationRunner = "androidx.benchmark.junit4.AndroidBenchmarkRunner"
        }
    }

    Modern

    android {
        ...
        defaultConfig {
            testInstrumentationRunner "androidx.benchmark.junit4.AndroidBenchmarkRunner"
        }
    }
  4. Karşılaştırmanızı eklemek için androidTest dizinindeki bir test dosyasına BenchmarkRule örneği ekleyin. Karşılaştırma testi yazma hakkında daha fazla bilgi için Mikro karşılaştırma sınıfı oluşturma başlıklı makaleyi inceleyin.

    Aşağıdaki kod snippet'inde, araçlı teste nasıl karşılaştırma ekleneceği gösterilmektedir:

    Kotlin

    @RunWith(AndroidJUnit4::class)
    class SampleBenchmark {
        @get:Rule
        val benchmarkRule = BenchmarkRule()
    
        @Test
        fun benchmarkSomeWork() {
            benchmarkRule.measureRepeated {
                doSomeWork()
            }
        }
    }

    Java

    @RunWith(AndroidJUnit4.class)
    class SampleBenchmark {
        @Rule
        public BenchmarkRule benchmarkRule = new BenchmarkRule();
    
        @Test
        public void benchmarkSomeWork() {
                BenchmarkRuleKt.measureRepeated(
                    (Function1<BenchmarkRule.Scope, Unit>) scope -> doSomeWork()
                );
           }
        }
    }

Karşılaştırma yazmayı öğrenmek için Mikro karşılaştırma sınıfı oluşturma bölümüne gidin.

Tam proje kurulumu

Tek seferlik karşılaştırma yerine düzenli karşılaştırma ayarlamak için karşılaştırmaları kendi modüllerine ayırın. Bu sayede, debuggable değerini false olarak ayarlamak gibi yapılandırmalarının normal testlerden ayrı olması sağlanır.

Microbenchmark, kodunuzu doğrudan çalıştırdığı için karşılaştırmak istediğiniz kodu ayrı bir Gradle modülüne yerleştirin ve Şekil 1'de gösterildiği gibi bu modüle bağımlılık ayarlayın.

uygulama yapısı
Şekil 1. :app, :microbenchmark ve :benchmarkable Gradle modüllerini içeren uygulama yapısı. Bu yapı, Microbenchmark'ların :benchmarkable modülündeki kodu karşılaştırmasına olanak tanır.

Yeni bir Gradle modülü eklemek için Android Studio'daki modül sihirbazını kullanabilirsiniz. Sihirbaz, karşılaştırma için önceden yapılandırılmış bir modül oluşturur. Bu modülde bir karşılaştırma dizini eklenir ve debuggable, false olarak ayarlanır.

  1. Android Studio'daki Proje panelinde projenizi veya modülünüzü sağ tıklayıp Yeni > Modül'ü tıklayın.

  2. Şablonlar bölmesinde Karşılaştırma'yı seçin.

  3. Karşılaştırma modülü türü olarak Microbenchmark'ı seçin.

  4. Modül adı için "microbenchmark" yazın.

  5. Son'u tıklayın.

Yeni kitaplık modülünü yapılandırma
Şekil 2. Android Studio Bumblebee'de yeni bir Gradle modülü ekleme

Modül oluşturulduktan sonra build.gradle veya build.gradle.kts dosyasını değiştirin ve karşılaştırma yapılacak kodu içeren modüle androidTestImplementation ekleyin:

Kotlin

dependencies {
    // The module name might be different.
    androidTestImplementation(project(":benchmarkable"))
}

Modern

dependencies {
    // The module name might be different.
    androidTestImplementation project(':benchmarkable')
}

Mikro karşılaştırma sınıfı oluşturma

Karşılaştırmalar, standart enstrümantasyon testleridir. Karşılaştırma oluşturmak için kitaplık tarafından sağlanan BenchmarkRule sınıfını kullanın. Etkinlikleri karşılaştırmak için ActivityScenario veya ActivityScenarioRule kullanın. Kullanıcı arayüzü kodunu karşılaştırmak için @UiThreadTest kullanın.

Aşağıdaki kodda örnek bir karşılaştırma gösterilmektedir:

Kotlin

@RunWith(AndroidJUnit4::class)
class SampleBenchmark {
    @get:Rule
    val benchmarkRule = BenchmarkRule()

    @Test
    fun benchmarkSomeWork() {
        benchmarkRule.measureRepeated {
            doSomeWork()
        }
    }
}
    

Java

@RunWith(AndroidJUnit4.class)
class SampleBenchmark {
    @Rule
    public BenchmarkRule benchmarkRule = new BenchmarkRule();

    @Test
    public void benchmarkSomeWork() {
        final BenchmarkState state = benchmarkRule.getState();
        while (state.keepRunning()) {
            doSomeWork();
        }
    }
}
    

Kurulum için zamanlamayı devre dışı bırakma

runWithTimingDisabled{} bloğuyla ölçmek istemediğiniz kod bölümleri için zamanlamayı devre dışı bırakabilirsiniz. Bu bölümler genellikle karşılaştırmanın her iterasyonunda çalıştırmanız gereken kodları temsil eder.

Kotlin

// using random with the same seed, so that it generates the same data every run
private val random = Random(0)

// create the array once and just copy it in benchmarks
private val unsorted = IntArray(10_000) { random.nextInt() }

@Test
fun benchmark_quickSort() {
    // ...
    benchmarkRule.measureRepeated {
        // copy the array with timing disabled to measure only the algorithm itself
        listToSort = runWithTimingDisabled { unsorted.copyOf() }

        // sort the array in place and measure how long it takes
        SortingAlgorithms.quickSort(listToSort)
    }

    // assert only once not to add overhead to the benchmarks
    assertTrue(listToSort.isSorted)
}
    

Java

private final int[] unsorted = new int[10000];

public SampleBenchmark() {
    // Use random with the same seed, so that it generates the same data every
    // run.
    Random random = new Random(0);

    // Create the array once and copy it in benchmarks.
    Arrays.setAll(unsorted, (index) -> random.nextInt());
}

@Test
public void benchmark_quickSort() {
    final BenchmarkState state = benchmarkRule.getState();

    int[] listToSort = new int[0];

    while (state.keepRunning()) {
        
        // Copy the array with timing disabled to measure only the algorithm
        // itself.
        state.pauseTiming();
        listToSort = Arrays.copyOf(unsorted, 10000);
        state.resumeTiming();
        
        // Sort the array in place and measure how long it takes.
        SortingAlgorithms.quickSort(listToSort);
    }

    // Assert only once, not to add overhead to the benchmarks.
    assertTrue(SortingAlgorithmsKt.isSorted(listToSort));
}
    

measureRepeated bloğunda ve runWithTimingDisabled içinde yapılan iş miktarını en aza indirmeye çalışın. measureRepeated bloğu birden çok kez çalıştırılır ve karşılaştırmayı çalıştırmak için gereken toplam süreyi etkileyebilir. Bir karşılaştırmanın bazı sonuçlarını doğrulamanız gerekiyorsa karşılaştırmanın her iterasyonunda bunu yapmak yerine son sonucu onaylayabilirsiniz.

Karşılaştırmayı çalıştırma

Android Studio'da, Şekil 3'te gösterildiği gibi test sınıfınızın veya yönteminizin yanındaki gutter işlemini kullanarak karşılaştırmanızı herhangi bir @Test gibi çalıştırın.

Mikro karşılaştırmayı çalıştır
Şekil 3. Bir test sınıfının yanındaki gutter işlemini kullanarak Microbenchmark testini çalıştırın.

Alternatif olarak, belirtilen Gradle modülündeki tüm testleri çalıştırmak için komut satırından connectedCheck komutunu çalıştırın:

./gradlew benchmark:connectedCheck

Tek bir test de çalıştırabilirsiniz:

./gradlew benchmark:connectedCheck -P android.testInstrumentationRunnerArguments.class=com.example.benchmark.SampleBenchmark#benchmarkSomeWork

Karşılaştırma sonuçları

Başarılı bir Microbenchmark çalıştırmasından sonra metrikler doğrudan Android Studio'da gösterilir. Ek metrikler ve cihaz bilgileri içeren tam bir karşılaştırma raporu JSON biçiminde sunulur.

Mikro karşılaştırma sonuçları
Şekil 4. Mikro karşılaştırma sonuçları.

JSON raporları ve profil oluşturma izleri de cihazdan ana makineye otomatik olarak kopyalanır. Bunlar, ana makinede aşağıdaki konuma yazılır:

project_root/module/build/outputs/connected_android_test_additional_output/debugAndroidTest/connected/device_id/

JSON raporu, varsayılan olarak test APK'sının harici paylaşılan medya klasöründe (genellikle /storage/emulated/0/Android/media/**app_id**/**app_id**-benchmarkData.json konumunda bulunur) cihaz üzerindeki diske yazılır.

Yapılandırma hataları

Kitaplık, projenizin ve ortamınızın sürüm için doğru performans sağlayacak şekilde ayarlandığından emin olmak amacıyla aşağıdaki koşulları algılar:

  • Hata ayıklanabilir, false olarak ayarlandı.
  • Fiziksel bir cihaz kullanılıyor (emülatörler desteklenmez).
  • Cihaz rootlanmışsa saatler kilitlenir.
  • Cihazda en az %25 oranında yeterli pil seviyesi.

Yukarıdaki kontrollerden herhangi biri başarısız olursa karşılaştırma, yanlış ölçümleri önlemek için bir hata bildirir.

Belirli hata türlerini uyarı olarak bastırmak ve karşılaştırmayı durdurmalarını önlemek için hata türünü virgülle ayrılmış bir liste halinde androidx.benchmark.suppressErrors araç bağımsız değişkenine iletin.

Aşağıdaki örnekte gösterildiği gibi, bunu Gradle komut dosyanızdan ayarlayabilirsiniz:

Kotlin

android {
    defaultConfig {
       …
      testInstrumentationRunnerArguments["androidx.benchmark.suppressErrors"] = "DEBUGGABLE,LOW-BATTERY"
    }
}

Modern

android {
    defaultConfig {
       …
      testInstrumentationRunnerArguments["androidx.benchmark.suppressErrors"] = "DEBUGGABLE,LOW-BATTERY"
    }
}

Hataları komut satırından da gizleyebilirsiniz:

$ ./gradlew :benchmark:connectedCheck -P andoidtestInstrumentationRunnerArguments.androidx.benchmark.supperssErrors=DEBUGGABLE,LOW-BATTERY

Hataların gizlenmesi, karşılaştırmanın yanlış yapılandırılmış bir durumda çalışmasına olanak tanır ve karşılaştırmanın çıkışı, test adlarının önüne hata eklenerek kasıtlı olarak yeniden adlandırılır. Örneğin, önceki snippet'teki engelleme ile hata ayıklanabilir bir karşılaştırma çalıştırmak, test adlarının önüne DEBUGGABLE_ ekler.