Que vous capturiez un profil basé sur l'application ou un profil basé sur un déclencheur, ProfilingManager enregistre le fichier terminé sur l'appareil et envoie un ProfilingResult à votre rappel enregistré. Appelez ProfilingResult.getResultFilePath pour obtenir le chemin d'accès au profil enregistré :
- Lors des tests en local : récupérez le fichier sur votre ordinateur à l'aide de
adb. - En production : transmettez le chemin d'accès à une tâche
WorkManagerqui compresse et importe le profil sur votre serveur.
Récupérer des profils depuis un appareil
Cette section décrit l'emplacement où ProfilingManager stocke les profils sur l'appareil, le fonctionnement du nettoyage automatique des fichiers et la manière d'extraire les fichiers localement à l'aide de adb.
Emplacements des fichiers et formats de dénomination
ProfilingManager enregistre les profils masqués dans votre répertoire de stockage spécifique à l'application à l'emplacement /data/user/0/<app>/files/profiling/. Le format du nom de fichier dépend de la manière dont le profil a été capturé :
Profils basés sur l'application :
profile_<tag>_<datetime>_uid-<uid>.<profile-type-ext>Si aucun tag n'a été fourni lors de la demande du profil,
<tag>_est omis :profile_<datetime>_uid-<uid>.<profile-type-ext>.Profils basés sur des déclencheurs :
profile_trigger-type-<trigger_type>_<datetime>_uid-<uid>.<profile-type-ext>
Où :
<app>est le nom du package de votre application.<tag>correspond aux 20 premiers caractères alphanumériques (et traits d'union) du tag fourni par l'appelant, configuré avecsetTagou transmis àrequestProfiling, converti en minuscules, avec tous les caractères en dehors dea-z,0-9et-supprimés.<trigger_type>est le code de constante entière du déclencheur deProfilingTrigger. Appelez toujoursProfilingResult.getTriggerTypedans le code au lieu d'analyser le nom du fichier.<datetime>correspond à la date et à l'heure d'enregistrement du profil (yyyy-MM-dd-HH-mm-ss-SSS).<uid>est l'ID utilisateur Linux de votre application (inclus dans les versions récentes du moduleProfiling).<profile-type-ext>est l'extension de fichier du type de profil capturé :.perfetto-tracepour les traces système.perfetto-java-heap-dumppour les empreintes de la mémoire Java.perfetto-heap-profilepour les profils de tas.perfetto-stack-samplepour les profils d'échantillonnage de pile
Stockage et nettoyage sur l'appareil
Pour libérer rapidement de l'espace de stockage sur l'appareil, supprimez chaque fichier de profil de votre worker d'importation immédiatement après une importation réussie (car le nettoyage automatique ne s'exécute que lorsque ProfilingManager fournit des résultats à votre application, les fichiers non importés peuvent rester sur le disque si votre application cesse d'enregistrer des rappels après la fin d'une campagne). En tant que solution de secours sur les versions récentes du module Profiling, ProfilingManager supprime également automatiquement les fichiers livrés dans le répertoire de stockage spécifique à votre application qui datent de plus de cinq jours lorsque de nouveaux résultats sont livrés.
Importer des profils en production avec WorkManager
Étant donné que les fichiers de profil peuvent faire plusieurs mégaoctets, planifiez les importations de production en arrière-plan lorsque l'appareil est connecté à un réseau sans compteur (Wi-Fi), qu'il est en charge et qu'il est inactif.
Avant d'importer, compressez le fichier de profil (par exemple, à l'aide de GZIPOutputStream ou ZipOutputStream). Les profils protobuf Perfetto et les empreintes de la mémoire Java sont compressés de manière significative, ce qui réduit la bande passante réseau et les coûts de stockage du backend.
Ajouter des dépendances WorkManager
ProfilingManager est indépendant du cloud. Vous pouvez donc planifier l'importation de profils vers n'importe quel backend à l'aide de WorkManager. Ajoutez la bibliothèque WorkManager à votre fichier build.gradle.kts :
Kotlin
dependencies { implementation("androidx.work:work-runtime:2.12.0") }
Groovy
dependencies { implementation 'androidx.work:work-runtime:2.12.0' }
Planifier un job d'importation
Lorsque votre application reçoit un ProfilingResult, planifiez le job d'importation. L'exemple suivant omet la requête de profilage initiale. Pour obtenir un exemple de requête complet, consultez Enregistrer une trace système.
Kotlin
class TraceUploadWorker(context: Context, workerParams: WorkerParameters) : Worker(context, workerParams) { override fun doWork(): Result { // Perform your uploading work here Log.d("ProfileTest", "Uploading trace: " + inputData.getString("PROFILE_PATH")) return Result.success() } } fun setupProfileUploadWorker(profileFilepath: String?) { val workMgr = WorkManager.getInstance(applicationContext) val workRequestBuilder = OneTimeWorkRequest.Builder(TraceUploadWorker::class) val constraints = Constraints.Builder() .setRequiredNetworkType(NetworkType.UNMETERED) .setRequiresDeviceIdle(true) .setRequiresCharging(true) .build() workRequestBuilder.setConstraints(constraints) val inputDataBuilder = Data.Builder() inputDataBuilder.putString("PROFILE_PATH", profileFilepath) workRequestBuilder.setInputData(inputDataBuilder.build()) workMgr.enqueue(workRequestBuilder.build()) }
Java
public static class TraceUploadWorker extends Worker { public TraceUploadWorker( @androidx.annotation.NonNull Context context, @androidx.annotation.NonNull WorkerParameters workerParams) { super(context, workerParams); } @androidx.annotation.NonNull @Override public Result doWork() { // Perform your uploading work here Log.d("ProfileTest", "Uploading trace: " + getInputData().getString("PROFILE_PATH")); return Result.success(); } } public void setupProfileUploadWorker(String profileFilepath) { WorkManager workMgr = WorkManager.getInstance(getApplicationContext()); OneTimeWorkRequest.Builder workRequestBuilder = new OneTimeWorkRequest.Builder( TraceUploadWorker.class); Constraints constraints = new Constraints.Builder() .setRequiredNetworkType(NetworkType.UNMETERED) .setRequiresDeviceIdle(true) .setRequiresCharging(true) .build(); workRequestBuilder.setConstraints(constraints); Data.Builder inputDataBuilder = new Data.Builder(); inputDataBuilder.putString("PROFILE_PATH", profileFilepath); workRequestBuilder.setInputData(inputDataBuilder.build()); workMgr.enqueue(workRequestBuilder.build()); }
Tutoriel du code
L'exemple précédent effectue les étapes suivantes :
- Définir le nœud de calcul : créez une classe
TraceUploadWorkerqui étendWorker. ImplémentezdoWorkpour vérifier que le fichier de profil existe toujours, compressez-le et importez-le à l'aide de votre SDK de backend ou de votre client HTTP, puis supprimez le fichier local une fois l'importation réussie. - Planifier le travail :
- Créez un
OneTimeWorkRequestpour votre nœud de calcul. - Définir des contraintes : utilisez
setRequiredNetworkType(NetworkType.UNMETERED),setRequiresDeviceIdle(true)etsetRequiresCharging(true)pour que l'importation ne s'exécute que lorsque l'appareil est connecté au Wi-Fi, en charge et inactif. - Transmettre des données : utilisez
setInputDatapour transmettre le chemin d'accès au profil degetResultFilePathau nœud de calcul. - Enqueue : envoyez la requête à
WorkManageren appelantWorkManager.enqueue.
- Créez un
Étapes suivantes
Après avoir récupéré ou importé des profils, visualisez-les dans l'UI Perfetto, interrogez des profils individuels avec PerfettoSQL, analysez des traces de manière groupée ou analysez des profils avec l'IA. Pour savoir comment configurer un pipeline d'analyse côté serveur évolutif, consultez Déployer Bigtrace sur Kubernetes.