Uygulamaya dayalı profilleme

Bu sayfada, ProfilingManager API kullanılarak sistem izinin nasıl kaydedileceği gösterilmektedir.

ProfilingManager, diğer profil türlerini de kaydedebilir. Bu işlem, sistem izi kaydetmeye benzer. Temel fark, ihtiyacınız olan profil türüne bağlı olarak aşağıdaki listeden belirli bir oluşturucu kullanmanızdır:

  • Yığın dökümleri: JavaHeapDumpRequestBuilder kullanılarak kaydedilir. Bellek sızıntısı algılama ve optimizasyon için faydalıdır.
  • Yığın profilleri: Bellek optimizasyonu için yararlı olan HeapProfileRequestBuilder kullanılarak kaydedilir.
  • Çağrı yığını profilleri: StackSamplingRequestBuilder kullanılarak kaydedilir. Bu profiller, gecikme analizini anlamak için yararlıdır.

Bağımlılık ekleme

ProfilingManager API ile en iyi deneyimi elde etmek için aşağıdaki Jetpack kitaplıklarını build.gradle.kts dosyanıza ekleyin.

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'
   }
   

Sistem izi kaydetme

Gerekli bağımlılıkları ekledikten sonra sistem izi kaydetmek için aşağıdaki kodu kullanın. Bu örnekte, bir profil oluşturma oturumunu başlatmak ve yönetmek için Activity içindeki temel kurulum gösterilmektedir.

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

Örnek kod, aşağıdaki adımları uygulayarak profilleme oturumunu kurar ve yönetir:

  1. Yürütücüyü ayarlayın. Profil oluşturma sonuçlarını alacak iş parçacığını tanımlamak için Executor oluşturun. Profil oluşturma işlemi arka planda gerçekleşir. Kullanıcı arayüzü iş parçacığı yürütücüsü dışında bir yürütücü kullanmak, geri çağırmaya daha sonra daha fazla işlem eklerseniz Uygulama Yanıt Vermiyor (ANR) hatalarını önlemeye yardımcı olur.

  2. Profil oluşturma sonuçlarını işleme Consumer<ProfilingResult> nesnesi oluşturun. Sistem, bu nesneyi kullanarak profil oluşturma sonuçlarını ProfilingManager uygulamanıza geri gönderir.

  3. Profillendirme isteğini oluşturun. Profil oluşturma oturumunuzu ayarlamak için SystemTraceRequestBuilder oluşturun. Bu oluşturucu, ProfilingManager izleme ayarlarını özelleştirmenize olanak tanır. Oluşturucuyu özelleştirmek isteğe bağlıdır. Özelleştirmezseniz sistem varsayılan ayarları kullanır.

    • Bir etiket tanımlayın. İzleme adına etiket eklemek için setTag() simgesini kullanın. Bu etiket, izlemeyi tanımlamanıza yardımcı olur.
    • İsteğe bağlı: Süreyi ayarlayın. Milisaniye cinsinden ne kadar süreyle profillendirileceğini belirtmek için setDurationMs() kullanın. Örneğin, 60000 60 saniyelik bir izleme ayarlar. Belirtilen süre içinde CancellationSignal tetiklenmezse izleme otomatik olarak sona erer.
    • Bir arabellek politikası seçin. İzleme verilerinin nasıl depolandığını tanımlamak için setBufferFillPolicy() kullanın. BufferFillPolicy.RING_BUFFER, arabellek dolduğunda yeni verilerin en eski verilerin üzerine yazılacağı ve son etkinliklerin sürekli olarak kaydedileceği anlamına gelir.
    • Arabellek boyutu ayarlayın. Çıkış izleme dosyasının boyutunu kontrol etmek için kullanabileceğiniz izleme arabellek boyutunu belirtmek üzere setBufferSizeKb() seçeneğini kullanın.
  4. İsteğe bağlı: Oturum yaşam döngüsünü yönetin. CancellationSignal oluşturun. Bu nesne, profil oluşturma oturumunu istediğiniz zaman durdurmanıza olanak tanıyarak süresi üzerinde hassas kontrol sahibi olmanızı sağlar.

  5. Başlatma ve sonuç alma requestProfiling()'ı aradığınızda, ProfilingManager arka planda bir profilleme oturumu başlatır. Profil oluşturma işlemi tamamlandıktan sonra ProfilingResult, resultCallback#accept yönteminize gönderilir. Profillendirme işlemi başarıyla tamamlanırsa ProfilingResult, ProfilingResult#getResultFilePath aracılığıyla izlemenin cihazınıza kaydedildiği yolu sağlar. Bu dosyayı programatik olarak veya yerel profilleme için bilgisayarınızdan adb pull <trace_path> komutunu çalıştırarak alabilirsiniz.

  6. Özel izleme noktaları ekleyin. Uygulamanızın koduna özel izleme noktaları ekleyebilirsiniz. Önceki kod örneğinde, Trace.beginSection() ve Trace.endSection() kullanılarak MyApp:HeavyOperation adlı bir iz dilimi ekleniyor. Bu özel dilim, oluşturulan profilde görünerek uygulamanızdaki belirli işlemleri vurgular.