ऐप्लिकेशन के हिसाब से प्रोफ़ाइलिंग

इस पेज पर, ProfilingManager API का इस्तेमाल करके, सिस्टम ट्रेस रिकॉर्ड करने का तरीका बताया गया है.

ProfilingManager, अन्य तरह की प्रोफ़ाइलें भी रिकॉर्ड कर सकता है. यह प्रोसेस, सिस्टम ट्रेस रिकॉर्ड करने जैसी ही होती है. हालांकि, हर तरह की प्रोफ़ाइल के लिए अलग-अलग बिल्डर का इस्तेमाल किया जाता है. यहां उन प्रोफ़ाइलों और उनके बिल्डर के बारे में बताया गया है जिन्हें रिकॉर्ड किया जा सकता है:

  • सिस्टम ट्रेस: इन्हें SystemTraceRequestBuilder का इस्तेमाल करके रिकॉर्ड किया जाता है. ये, लेटेंसी का विश्लेषण करने और परफ़ॉर्मेंस से जुड़ी सामान्य गड़बड़ियां ठीक करने में मददगार होते हैं.

  • हीप डंप: इन्हें JavaHeapDumpRequestBuilder का इस्तेमाल करके रिकॉर्ड किया जाता है. ये, मेमोरी लीक का पता लगाने और उसे ऑप्टिमाइज़ करने में मददगार होते हैं.

  • हीप प्रोफ़ाइल: इन्हें HeapProfileRequestBuilder का इस्तेमाल करके रिकॉर्ड किया जाता है. ये, मेमोरी को ऑप्टिमाइज़ करने में मददगार होती हैं.

  • कॉल स्टैक प्रोफ़ाइल: इन्हें StackSamplingRequestBuilder का इस्तेमाल करके रिकॉर्ड किया जाता है. ये, कोड के एक्ज़ीक्यूशन और लेटेंसी का विश्लेषण करने में मददगार होती हैं.

डिपेंडेंसी जोड़ें

ProfilingManager API का बेहतर अनुभव पाने के लिए, अपनी build.gradle.kts फ़ाइल में Jetpack की ये लाइब्रेरी जोड़ें.

Kotlin

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

शानदार

   dependencies {
       implementation 'androidx.tracing:tracing:1.3.0'
       implementation 'androidx.core:core:1.18.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 बनाकर, उस थ्रेड को तय करें जो प्रोफ़ाइलिंग के नतीजे पाएगा. प्रोफ़ाइलिंग, बैकग्राउंड में होती है. अगर बाद में कॉलबैक में ज़्यादा प्रोसेसिंग जोड़ी जाती है, तो यूआई थ्रेड के अलावा किसी दूसरे एक्ज़ीक्यूटर का इस्तेमाल करने से, एएनआर (ऐप्लिकेशन काम नहीं कर रहा है) वाली गड़बड़ियों को रोकने में मदद मिलती है.

  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. कस्टम ट्रेस पॉइंट जोड़ना. आपके पास अपने ऐप्लिकेशन के कोड में, कस्टम ट्रेस पॉइंट जोड़ने का विकल्प होता है. कोड के पिछले उदाहरण में, Trace.beginSection() और Trace.endSection() का इस्तेमाल करके, MyApp:HeavyOperation नाम का ट्रेस स्लाइस जोड़ा गया है. यह कस्टम स्लाइस, जनरेट की गई प्रोफ़ाइल में दिखता है. इससे आपके ऐप्लिकेशन में की गई खास कार्रवाइयों को हाइलाइट किया जाता है.