Profil erfassen

Auf dieser Seite wird beschrieben, wie Sie mit der ProfilingManager API einen System-Trace aufzeichnen.

Abhängigkeiten hinzufügen

Für eine optimale Nutzung der ProfilingManager API fügen Sie die folgenden Jetpack-Bibliotheken in Ihre build.gradle.kts-Datei ein.

Kotlin

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

Groovy

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

System-Trace aufzeichnen

Nachdem Sie die erforderlichen Abhängigkeiten hinzugefügt haben, können Sie mit dem folgenden Code einen System-Trace aufzeichnen. In diesem Beispiel wird eine einfache Einrichtung in einem Activity zum Starten und Verwalten einer Profilerstellungssitzung gezeigt.

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

Im Beispielcode wird die Profilerstellungssitzung durch die folgenden Schritte eingerichtet und verwaltet:

  1. Executor einrichten: Erstellen Sie eine Executor, um den Thread zu definieren, der die Profiling-Ergebnisse empfängt. Das Profiling erfolgt im Hintergrund. Die Verwendung eines Executors für Threads, die nicht zur Benutzeroberfläche gehören, kann ANR-Fehler (Application Not Responding) verhindern, wenn Sie dem Callback später weitere Verarbeitung hinzufügen.

  2. Profiler-Ergebnisse verarbeiten Erstellen Sie ein Consumer<ProfilingResult>-Objekt. Das System verwendet dieses Objekt, um Profilergebnisse von ProfilingManager an Ihre App zurückzusenden.

  3. Profilanfrage erstellen Erstellen Sie eine SystemTraceRequestBuilder, um die Profilerstellungssitzung einzurichten. Mit diesem Builder können Sie die ProfilingManager-Trace-Einstellungen anpassen. Das Anpassen des Builders ist optional. Andernfalls verwendet das System Standardeinstellungen.

    • Tag definieren Mit setTag() können Sie dem Namen des Traces ein Tag hinzufügen. Mit diesem Tag können Sie den Trace identifizieren.
    • Optional: Dauer festlegen Mit setDurationMs() können Sie angeben, wie lange das Profiling in Millisekunden dauern soll. Mit 60000 wird beispielsweise ein 60-Sekunden-Trace festgelegt. Die Aufzeichnung wird nach der angegebenen Dauer automatisch beendet, wenn CancellationSignal nicht vorher ausgelöst wird.
    • Pufferrichtlinie auswählen Mit setBufferFillPolicy() können Sie festlegen, wie Tracedaten gespeichert werden. BufferFillPolicy.RING_BUFFER bedeutet, dass neue Daten die ältesten Daten überschreiben, wenn der Puffer voll ist. So wird ein kontinuierlicher Datensatz der letzten Aktivitäten erstellt.
    • Puffergröße festlegen Mit setBufferSizeKb() können Sie eine Puffergröße für das Tracing angeben, mit der Sie die Größe der Ausgabetracedatei steuern können.
  4. Optional: Sitzungslebenszyklus verwalten Erstellen Sie einen CancellationSignal. Mit diesem Objekt können Sie die Profiling-Sitzung jederzeit beenden und so die Länge genau steuern.

  5. Starten und Ergebnisse erhalten Wenn Sie requestProfiling() anrufen, startet ProfilingManager im Hintergrund eine Profilerstellungssitzung. Nach dem Profiling wird ProfilingResult an Ihre resultCallback#accept-Methode gesendet. Wenn das Profiling erfolgreich abgeschlossen wurde, gibt ProfilingResult den Pfad an, unter dem der Trace auf Ihrem Gerät über ProfilingResult#getResultFilePath gespeichert wurde. Sie können diese Datei programmatisch oder für das lokale Profiling durch Ausführen von adb pull <trace_path> auf Ihrem Computer abrufen.

  6. Benutzerdefinierte Trace-Punkte hinzufügen: Sie können benutzerdefinierte Trace-Punkte im Code Ihrer App hinzufügen. Im vorherigen Codebeispiel wird mit Trace.beginSection() und Trace.endSection() ein Trace-Abschnitt namens MyApp:HeavyOperation hinzugefügt. Dieser benutzerdefinierte Slice wird im generierten Profil angezeigt und hebt bestimmte Vorgänge in Ihrer App hervor.