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

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

QuickStart

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

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

  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 لإضافة مقياس الأداء. لمزيد من المعلومات حول كتابة مقاييس الأداء، يُرجى الاطّلاع على إنشاء فئة Microbenchmark.

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

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

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

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

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

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

بنية التطبيق
الشكل 1: بنية التطبيق التي تتضمّن وحدات Gradle‏ :app و:microbenchmark و:benchmarkable، والتي تتيح لمكتبة Microbenchmarks قياس أداء الرمز البرمجي في وحدة :benchmarkable

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

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

  2. انقر على مقياس الأداء في لوحة النماذج.

  3. اختَر Microbenchmark كنوع وحدة قياس الأداء.

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

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

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

بعد إنشاء الوحدة، غيِّر ملف 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')
}

إنشاء فئة Microbenchmark

معايير الأداء هي اختبارات قياس حالة التطبيق العادية. لإنشاء مقياس أداء، استخدِم الفئة 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"، شغِّل مقياس الأداء كما تفعل مع أي @Test باستخدام إجراء الهامش بجانب فئة الاختبار أو الطريقة، كما هو موضّح في الشكل 3.

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

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

./gradlew benchmark:connectedCheck

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

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

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

بعد تشغيل Microbenchmark بنجاح، يتم عرض المقاييس مباشرةً في Android Studio، ويتوفّر تقرير قياس أداء كامل يتضمّن مقاييس إضافية ومعلومات عن الجهاز بتنسيق 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.

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

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

  • تم ضبط السمة "قابل للتصحيح" على 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_ إلى أسماء الاختبارات.