Capturer un profil

Cette page explique comment enregistrer une trace système à l'aide de l'API ProfilingManager.

Ajouter des dépendances

Pour une expérience optimale avec l'API ProfilingManager, ajoutez les bibliothèques Jetpack suivantes à votre fichier build.gradle.kts.

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

Enregistrer une trace système

Après avoir ajouté les dépendances requises, utilisez le code suivant pour enregistrer une trace système. Cet exemple montre une configuration de base dans un Activity pour démarrer et gérer une session de profilage.

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

L'exemple de code configure et gère la session de profilage en suivant les étapes suivantes :

  1. Configurez l'exécuteur. Créez un Executor pour définir le thread qui recevra les résultats du profilage. Le profilage s'effectue en arrière-plan. L'utilisation d'un exécuteur de thread non UI permet d'éviter les erreurs ANR (Application Not Responding) si vous ajoutez ultérieurement un traitement au rappel.

  2. Gérez les résultats du profilage. Créez un objet Consumer<ProfilingResult>. Le système utilise cet objet pour renvoyer les résultats du profilage de ProfilingManager à votre application.

  3. Créez la requête de profilage. Créez un SystemTraceRequestBuilder pour configurer votre session de profilage. Ce générateur vous permet de personnaliser les paramètres de trace ProfilingManager. La personnalisation du compilateur est facultative. Si vous ne la faites pas, le système utilise les paramètres par défaut.

    • Définissez une balise. Utilisez setTag() pour ajouter un tag au nom de la trace. Cette balise vous aide à identifier la trace.
    • (Facultatif) Définissez la durée. Utilisez setDurationMs() pour spécifier la durée du profilage en millisecondes. Par exemple, 60000 définit une trace de 60 secondes. La trace se termine automatiquement après la durée spécifiée si CancellationSignal n'est pas déclenché avant.
    • Choisissez une règle de mise en mémoire tampon. Utilisez setBufferFillPolicy() pour définir la façon dont les données de trace sont stockées. BufferFillPolicy.RING_BUFFER signifie que lorsque le tampon est plein, les nouvelles données écrasent les plus anciennes, ce qui permet de conserver un enregistrement continu de l'activité récente.
    • Définissez une taille de mémoire tampon. Utilisez setBufferSizeKb() pour spécifier une taille de tampon pour le traçage, que vous pouvez utiliser pour contrôler la taille du fichier de trace de sortie.
  4. Facultatif : Gérez le cycle de vie de la session. Créez un CancellationSignal. Cet objet vous permet d'arrêter la session de profilage quand vous le souhaitez, ce qui vous permet de contrôler précisément sa durée.

  5. Lancer et recevoir des résultats Lorsque vous appelez requestProfiling(), ProfilingManager démarre une session de profilage en arrière-plan. Une fois le profilage terminé, il envoie le ProfilingResult à votre méthode resultCallback#accept. Si le profilage se termine correctement, ProfilingResult indique le chemin d'accès où la trace a été enregistrée sur votre appareil via ProfilingResult#getResultFilePath. Vous pouvez obtenir ce fichier de manière programmatique ou, pour le profilage local, en exécutant adb pull <trace_path> depuis votre ordinateur.

  6. Ajoutez des points de trace personnalisés. Vous pouvez ajouter des points de trace personnalisés dans le code de votre application. Dans l'exemple de code précédent, une tranche de trace nommée MyApp:HeavyOperation est ajoutée à l'aide de Trace.beginSection() et Trace.endSection(). Cette tranche personnalisée apparaît dans le profil généré, mettant en évidence des opérations spécifiques dans votre application.