كتابة مقياس أداء مصغّر

للتعرّف على كيفية استخدام مكتبة Microbenchmark من خلال إضافة تغييرات إلى код التطبيق، اطّلِع على قسم البدء السريع. للتعرّف على كيفية إكمال عملية إعداد كاملة مع إجراء تغييرات أكثر تعقيدًا على قاعدة بياناتك، اطّلِع على القسم إعداد المشروع بالكامل.

البدء السريع

يوضّح هذا القسم كيفية تجربة قياس الأداء وإجراء قياسات لمرة واحدة بدون الحاجة إلى نقل الرمز إلى وحدات. للحصول على نتائج دقيقة عن الأداء، تتضمن هذه الخطوات إيقاف تصحيح الأخطاء في تطبيقك، لذا عليك الاحتفاظ بهذه الخطوات في نسخة عمل محلية بدون تأكيد التغييرات في نظام التحكّم في المصدر.

لإجراء تقييم أداء لمرة واحدة، اتّبِع الخطوات التالية:

  1. أضِف المكتبة إلى ملف build.gradle أو build.gradle.kts الخاص بالوحدة:

    Kotlin

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

    رائع

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

    استخدِم تبعية implementation بدلاً من تبعية androidTestImplementation. في حال استخدام androidTestImplementation، يتعذّر تشغيل معايير الأداء لأنّه لم يتم دمج بيان المكتبة في بيان التطبيق.

  2. عدِّل نوع الإصدار debug لكي لا يمكن تصحيح أخطاءه:

    Kotlin

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

    رائع

    android {
        ...
        buildTypes {
            debug {
                debuggable false
            }
        }
    }
    
  3. غيِّر testInstrumentationRunner إلى AndroidBenchmarkRunner:

    Kotlin

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

    رائع

    android {
        ...
        defaultConfig {
            testInstrumentationRunner "androidx.benchmark.junit4.AndroidBenchmarkRunner"
        }
    }
    
  4. أضِف مثيلًا من BenchmarkRule في ملف اختباري في دليل androidTest لإضافة مقياس الأداء. لمزيد من المعلومات حول كتابة مقاييس الأداء، يُرجى الاطّلاع على مقالة إنشاء فئة اختبارات الأداء الدقيقة.

    يوضّح مقتطف الرمز البرمجي التالي كيفية إضافة مقياس أداء إلى اختبار مزوّد بأدوات قياس الأداء:

    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()
                );
           }
        }
    }
    

للتعرّف على كيفية كتابة مقياس أداء، انتقِل إلى إنشاء فئة اختبار أداء صغير.

إعداد المشروع بالكامل

لإعداد قياسات الأداء العادية بدلاً من قياسات الأداء لمرة واحدة، عليك عزل قياسات الأداء في وحدة خاصة بها. يساعد ذلك في ضمان أن تكون الإعدادات، مثل ضبط debuggable على false، منفصلة عن الاختبارات العادية.

بما أنّ أداة Microbenchmark تُشغّل الرمز البرمجي مباشرةً، ضَع الرمز الذي تريد قياس أدائه في وحدة Gradle منفصلة واضبط الاعتماد على هذه الوحدة كما هو موضح في الشكل 1.

بنية التطبيق
الشكل 1. بنية التطبيق التي تتضمّن وحدات Gradle :app و:microbenchmark و:benchmarkable، ما يتيح لأدوات قياس الأداء على مستوى الوحدات الصغيرة قياس أداء الرمز البرمجي في ملف IDE :benchmarkable.

لإضافة وحدة Gradle جديدة، يمكنك استخدام معالج الوحدة في "استوديو Android". ينشئ المعالج وحدة تم إعدادها مسبقًا لقياس الأداء، مع إضافة directory benchmark وضبط debuggable على false.

  1. انقر بزر الماوس الأيمن على مشروعك أو وحدتك في لوحة المشروع في "استوديو Android"، ثم انقر على جديد > وحدة.

  2. اختَر مقاييس الأداء في لوحة النماذج.

  3. اختَر اختبار الأداء الصغير كنوع وحدة اختبار الأداء.

  4. اكتب "microbenchmark" لاسم الوحدة.

  5. انقر على إنهاء.

ضبط وحدة المكتبة الجديدة
الشكل 2. أضِف وحدة Gradle جديدة في الإصدار Bumblebee من "استوديو Android" .

بعد إنشاء الوحدة، غيِّر ملف build.gradle أو build.gradle.kts وأضِف androidTestImplementation إلى الوحدة التي تحتوي على الرمز البرمجي لقياس الأداء:

Kotlin

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

رائع

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

إنشاء فئة اختبار أداء صغير

معايير الأداء هي اختبارات قياس حالة التطبيق العادية. لإنشاء مقياس أداء، استخدِم فئة BenchmarkRule التي تقدّمها المكتبة. لمقارنة الأنشطة، استخدِم ActivityScenario أو ActivityScenarioRule. لقياس أداء رمز واجهة المستخدم، استخدِم @UiThreadTest.

تعرِض التعليمة البرمجية التالية نموذجًا لمقياس الأداء:

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();
        }
    }
}
    

إيقاف التوقيت لعملية الإعداد

يمكنك إيقاف توقيت أقسام الرمز البرمجي التي لا تريد قياسها باستخدام العنصر runWithTimingDisabled{}. تمثّل هذه الأقسام عادةً بعضًا من الرمز البرمجي الذي تحتاج إلى تشغيله في كلّ تكرار من الاختبار القياسي.

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 وداخل runWithTimingDisabled. يتم تشغيل الرمز البرمجي measureRepeated عدة مرات ويمكن أن يؤثر ذلك في إجمالي الوقت اللازم لتنفيذ الاختبار القياسي. إذا كنت بحاجة إلى التحقّق من بعض نتائج أحد مقاييس الأداء، يمكنك تأكيد النتيجة الأخيرة بدلاً من إجراء ذلك في كلّ تكرار لمقياس الأداء.

تشغيل مقياس الأداء

في Android Studio، يمكنك تنفيذ اختبار الأداء كما تفعل مع أي @Test باستخدام إجراء الفاصل بجانب فئة الاختبار أو طريقته، كما هو موضّح في الشكل 3.

إجراء اختبار أداء صغير
الشكل 3. يمكنك إجراء اختبار Microbenchmark باستخدام إجراء الحافة بجانب فئة اختبار.

بدلاً من ذلك، يمكنك تشغيل connectedCheck من سطر الأوامر لإجراء كل الاختبارات من وحدة Gradle المحدّدة:

./gradlew benchmark:connectedCheck

أو اختبار واحد:

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

نتائج قياس الأداء

بعد إجراء اختبار Microbenchmark بنجاح، يتم عرض المقاييس مباشرةً في Android IDE، ويتوفّر تقرير اختبار أداء كامل بتنسيق JSON يحتوي على مقاييس إضافية ومعلومات عن الجهاز.

نتائج اختبارات الأداء الدقيقة
الشكل 4. نتائج اختبارات الأداء الصغيرة

تتم أيضًا نسخ تقارير JSON وأي عمليات تتبُّع لإعداد الملف الشخصي تلقائيًا من الجهاز إلى المضيف. يتم تسجيل هذه المعلومات على الجهاز المضيف في الموقع التالي:

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

يتم تلقائيًا كتابة تقرير JSON على القرص على الجهاز في مجلد الوسائط المشتركة الخارجي لحزمة APK الاختبارية، والذي يقع عادةً في /storage/emulated/0/Android/media/**app_id**/**app_id**-benchmarkData.json.

أخطاء في الإعدادات

ترصد المكتبة الشروط التالية لضمان إعداد مشروعك وبيئة العمل لتحقيق أداء دقيق في الإصدار:

  • تم ضبط القيمة Debuggable على false.
  • يتم استخدام جهاز مادي، وأدوات المحاكاة غير متوافقة.
  • يتم قفل الساعات إذا تم تحديد جذر الجهاز.
  • يجب أن يكون مستوى شحن البطارية في الجهاز كافيًا بنسبة لا تقل عن %25.

إذا تعذّر إجراء أيّ من عمليات التحقّق السابقة، يُبلغ مقياس الأداء عن خطأ بهدف تجنّب إجراء قياسات غير دقيقة.

لإخفاء أنواع أخطاء معيّنة كتحذيرات ومنعها من إيقاف الأداء المرجعي، يمكنك تمرير نوع الخطأ في قائمة مفصولة بفواصل إلى مَعلمة القياس androidx.benchmark.suppressErrors.

يمكنك ضبط هذا الإعداد من نص Gradle البرمجي، كما هو موضّح في المثال التالي:

Kotlin

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

رائع

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

يمكنك أيضًا إخفاء الأخطاء من سطر الأوامر:

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

يؤدي إخفاء الأخطاء إلى تشغيل الاختبار القياسي في حالة تم ضبطها بشكل غير صحيح، ويتم إعادة تسمية نتيجة الاختبار القياسي عن قصد من خلال إضافة الخطأ إلى أسماء الاختبار. على سبيل المثال، يؤدي تشغيل معيار قابل لتصحيح الأخطاء باستخدام ميزة الإلغاء في المقتطف السابق إلى إضافة DEBUGGABLE_ إلى أسماء الاختبارات.