تحديد المواصفات الشخصية استنادًا إلى التطبيق

توضّح هذه الصفحة كيفية تسجيل تتبُّع النظام باستخدام واجهة برمجة التطبيقات ProfilingManager.

يمكن لـ "ProfilingManager" أيضًا تسجيل أنواع أخرى من الملفات الشخصية. وتشبه هذه العملية تسجيل تتبُّع النظام. يكمن الاختلاف الرئيسي في أنّك ستستخدم أداة إنشاء محدّدة من القائمة التالية، وذلك حسب نوع الملف الشخصي الذي تحتاج إليه:

  • عمليات تفريغ الذاكرة المؤقتة: يتم تسجيلها باستخدام JavaHeapDumpRequestBuilder، وهي مفيدة في رصد تسرب الذاكرة وتحسينها.
  • ملفات تعريف الذاكرة لأخذ لقطات لعناصر متعدّدة: يتم تسجيلها باستخدام HeapProfileRequestBuilder، وهي مفيدة لتحسين استخدام الذاكرة.
  • الملفات الشخصية لمجموعة استدعاء الدوال البرمجية: يتم تسجيلها باستخدام StackSamplingRequestBuilder، وهي مفيدة لفهم وقت الاستجابة وتحليله.

إضافة التبعيات

للحصول على أفضل تجربة مع واجهة برمجة التطبيقات ProfilingManager، أضِف مكتبات Jetpack التالية إلى ملف build.gradle.kts.

Kotlin

   dependencies {
       implementation("androidx.tracing:tracing:1.3.0")
       implementation("androidx.core:core:1.17.0")
   }
   

Groovy

   dependencies {
       implementation 'androidx.tracing:tracing:1.3.0'
       implementation 'androidx.core:core:1.17.0'
   }
   

تسجيل عملية تتبُّع النظام

بعد إضافة التبعيات المطلوبة، استخدِم الرمز التالي لتسجيل تتبُّع النظام. يوضِّح هذا المثال عملية إعداد أساسية ضمن Activity لبدء جلسة تسجيل الأداء وإدارتها.

Kotlin

@RequiresApi(Build.VERSION_CODES.VANILLA_ICE_CREAM)
fun sampleRecordSystemTrace() {
    val mainExecutor: Executor =
        Dispatchers.IO.asExecutor() // Your choice of executor for the callback to occur on.
    val resultCallback = Consumer<ProfilingResult> { profilingResult ->
        if (profilingResult.errorCode == ProfilingResult.ERROR_NONE) {
            Log.d(
                "ProfileTest",
                "Received profiling result file=" + profilingResult.resultFilePath
            )
        } else {
            Log.e(
                "ProfileTest",
                "Profiling failed errorcode=" + profilingResult.errorCode + " errormsg=" + profilingResult.errorMessage
            )
        }
    }
    val stopSignal = CancellationSignal()

    val requestBuilder = SystemTraceRequestBuilder()
    requestBuilder.setCancellationSignal(stopSignal)
    requestBuilder.setTag("FOO") // Caller supplied tag for identification
    requestBuilder.setDurationMs(60000)
    requestBuilder.setBufferFillPolicy(BufferFillPolicy.RING_BUFFER)
    requestBuilder.setBufferSizeKb(20971520)
    requestProfiling(applicationContext, requestBuilder.build(), mainExecutor, resultCallback)

    // Wait some time for profiling to start.

    Trace.beginSection("MyApp:HeavyOperation")
    heavyOperation()
    Trace.endSection()

    // Once the interesting code section is profiled, stop profile
    stopSignal.cancel()
}

fun heavyOperation() {
    // Computations you want to profile
}

Java

void heavyOperation() {
  // Computations you want to profile
}

void sampleRecordSystemTrace() {
  Executor mainExecutor = Executors.newSingleThreadExecutor();
  Consumer<ProfilingResult> resultCallback =
      new Consumer<ProfilingResult>() {
        @Override
        public void accept(ProfilingResult profilingResult) {
          if (profilingResult.getErrorCode() == ProfilingResult.ERROR_NONE) {
            Log.d(
                "ProfileTest",
                "Received profiling result file=" + profilingResult.getResultFilePath());
            setupProfileUploadWorker(profilingResult.getResultFilePath());
          } else {
            Log.e(
                "ProfileTest",
                "Profiling failed errorcode="

                    + profilingResult.getErrorCode()
                    + " errormsg="
                    + profilingResult.getErrorMessage());
          }
        }
      };
  CancellationSignal stopSignal = new CancellationSignal();

  SystemTraceRequestBuilder requestBuilder = new SystemTraceRequestBuilder();
  requestBuilder.setCancellationSignal(stopSignal);
  requestBuilder.setTag("FOO");
  requestBuilder.setDurationMs(60000);
  requestBuilder.setBufferFillPolicy(BufferFillPolicy.RING_BUFFER);
  requestBuilder.setBufferSizeKb(20971520);
  Profiling.requestProfiling(getApplicationContext(), requestBuilder.build(), mainExecutor,
      resultCallback);

  // Wait some time for profiling to start.

  Trace.beginSection("MyApp:HeavyOperation");
  heavyOperation();
  Trace.endSection();

  // Once the interesting code section is profiled, stop profile
  stopSignal.cancel();
}

يُعدّ نموذج الرمز البرمجي جلسة تحديد المشاكل ويُديرها من خلال اتّباع الخطوات التالية:

  1. إعداد المنفّذ أنشئ Executor لتحديد سلسلة التعليمات البرمجية التي ستتلقّى نتائج تحديد المشاكل. تتم عملية إنشاء الملفات الشخصية في الخلفية. يساعد استخدام منفّذ سلسلة تعليمات غير تابعة لواجهة المستخدم في تجنُّب أخطاء "التطبيق لا يستجيب" (ANR) في حال أضفت المزيد من المعالجة إلى دالة الرجوع لاحقًا.

  2. التعامل مع نتائج التحليل: أنشئ عنصر Consumer<ProfilingResult>. يستخدم النظام هذا العنصر لإرسال نتائج إنشاء الملفات الشخصية من ProfilingManager إلى تطبيقك.

  3. إنشاء طلب إنشاء الملف الشخصي أنشئ SystemTraceRequestBuilder لإعداد جلسة إنشاء الملفات الشخصية. يتيح لك هذا المنشئ تخصيص ProfilingManager إعدادات التتبُّع. تخصيص أداة الإنشاء أمر اختياري، وفي حال عدم تخصيصها، سيستخدم النظام الإعدادات التلقائية.

    • تحديد علامة: استخدِم setTag() لإضافة علامة إلى اسم التتبُّع. تساعدك هذه العلامة في تحديد التتبُّع.
    • اختياري: حدِّد المدة. استخدِم setDurationMs() لتحديد مدة إنشاء الملف الشخصي بالمللي ثانية. على سبيل المثال، تضبط 60000 عملية تتبُّع لمدة 60 ثانية. ينتهي التتبُّع تلقائيًا بعد المدة المحدّدة إذا لم يتم تشغيل CancellationSignal قبل ذلك.
    • اختَر سياسة التخزين المؤقت. استخدِم setBufferFillPolicy() لتحديد طريقة تخزين بيانات التتبُّع. يعني BufferFillPolicy.RING_BUFFER أنّه عندما تمتلئ المخزن المؤقت، تحلّ البيانات الجديدة محل البيانات الأقدم، ما يؤدي إلى الاحتفاظ بسجلّ متواصل للنشاط الحديث.
    • ضبط حجم المخزن المؤقت: استخدِم setBufferSizeKb() لتحديد حجم المخزن المؤقت للتتبُّع، ويمكنك استخدام هذا الحجم للتحكّم في حجم ملف التتبُّع الناتج.
  4. اختياري: إدارة دورة حياة الجلسة أنشئ CancellationSignal. يتيح لك هذا العنصر إيقاف جلسة إنشاء الملفات الشخصية متى أردت، ما يمنحك تحكّمًا دقيقًا في مدتها.

  5. بدء الاختبار وتلقّي النتائج عند الاتصال بالرقم requestProfiling()، يبدأ تطبيق ProfilingManager جلسة إنشاء ملفات شخصية في الخلفية. بعد اكتمال عملية إنشاء الملف الشخصي، يتم إرسال ProfilingResult إلى طريقة resultCallback#accept. في حال انتهاء إنشاء الملف الشخصي بنجاح، يوفّر ProfilingResult المسار الذي تم فيه حفظ التتبُّع على جهازك من خلال ProfilingResult#getResultFilePath. يمكنك الحصول على هذا الملف آليًا أو من خلال تشغيل adb pull <trace_path> من جهاز الكمبيوتر لإجراء تحليل محلي.

  6. إضافة نقاط تتبُّع مخصّصة يمكنك إضافة نقاط تتبُّع مخصّصة في رمز تطبيقك. في مثال الرمز البرمجي السابق، تتم إضافة شريحة تتبُّع باسم MyApp:HeavyOperation باستخدام Trace.beginSection() وTrace.endSection(). يظهر هذا المقياس المخصّص في الملف الشخصي الذي تم إنشاؤه، مع إبراز عمليات معيّنة داخل تطبيقك.