Indipendentemente dal fatto che tu acquisisca un profilo basato sull'app o un profilo basato su trigger,
ProfilingManager salva il file completato sul dispositivo e invia un
ProfilingResult al tuo callback registrato. Chiama
ProfilingResult.getResultFilePath per ottenere il percorso del profilo salvato:
- Durante i test locali: esegui il pull del file sul computer utilizzando
adb. - In produzione: passa il percorso a un job
WorkManagerche comprime e carica il profilo sul tuo server.
Recupera i profili da un dispositivo
Questa sezione descrive dove ProfilingManager archivia i profili sul dispositivo, come funziona la pulizia automatica dei file e come estrarre i file localmente utilizzando adb.
Posizioni dei file e formati di denominazione
ProfilingManager salva i profili oscurati nella directory di archiviazione specifica dell'app in /data/user/0/<app>/files/profiling/. Il formato del nome file dipende da come è stato acquisito il profilo:
Profili basati su app:
profile_<tag>_<datetime>_uid-<uid>.<profile-type-ext>Se non è stato fornito alcun tag durante la richiesta del profilo,
<tag>_viene omesso:profile_<datetime>_uid-<uid>.<profile-type-ext>.Profili basati su trigger:
profile_trigger-type-<trigger_type>_<datetime>_uid-<uid>.<profile-type-ext>
Dove:
<app>è il nome del pacchetto della tua app.<tag>è composto dai primi 20 caratteri alfanumerici (e trattini) del tag fornito dal chiamante configurato consetTago passato arequestProfiling, convertito in minuscolo con la rimozione di tutti i caratteri al di fuori dia-z,0-9e-.<trigger_type>è il codice della costante intera per l'attivatore diProfilingTrigger. Chiama sempreProfilingResult.getTriggerTypenel codice anziché analizzare il nome file.<datetime>è la data e l'ora in cui è stato registrato il profilo (yyyy-MM-dd-HH-mm-ss-SSS).<uid>è l'ID utente Linux della tua app (incluso nelle versioni recenti del moduloProfiling).<profile-type-ext>è l'estensione del file per il tipo di profilo acquisito:.perfetto-traceper i tracciamenti del sistema.perfetto-java-heap-dumpper i dump dell'heap Java.perfetto-heap-profileper i profili heap.perfetto-stack-sampleper i profili di campionamento dello stack
Spazio di archiviazione on-device e pulizia
Per liberare rapidamente lo spazio sul dispositivo, elimina ogni file del profilo nel worker di caricamento immediatamente dopo un caricamento riuscito (poiché la pulizia automatica viene eseguita solo quando ProfilingManager fornisce i risultati alla tua app, i file non caricati possono altrimenti rimanere sul disco se l'app interrompe la registrazione dei callback dopo la fine di una campagna). Come opzione di riserva nelle versioni recenti del modulo Profiling,
ProfilingManager elimina automaticamente anche i file recapitati nella directory di archiviazione specifica dell'app che risalgono a più di 5 giorni prima quando vengono recapitati nuovi risultati.
Carica i profili in produzione con WorkManager
Poiché i file dei profili possono avere dimensioni di diversi megabyte, pianifica i caricamenti di produzione in background quando il dispositivo è connesso a una rete non a consumo (Wi-Fi), è in carica e non è in uso.
Prima di caricarlo, comprimi il file del profilo (ad esempio, utilizzando GZIPOutputStream o ZipOutputStream). I profili protobuf Perfetto e i dump dell'heap Java si comprimono in modo significativo, riducendo la larghezza di banda della rete e i costi di archiviazione del backend.
Aggiungi le dipendenze di WorkManager
ProfilingManager è indipendente dal cloud, quindi puoi pianificare il caricamento dei profili su qualsiasi backend utilizzando WorkManager. Aggiungi la libreria WorkManager al file build.gradle.kts:
Kotlin
dependencies { implementation("androidx.work:work-runtime:2.12.0") }
Alla moda
dependencies { implementation 'androidx.work:work-runtime:2.12.0' }
Pianifica un job di caricamento
Quando la tua app riceve un ProfilingResult, pianifica il job di caricamento. L'esempio seguente omette la richiesta di profilazione iniziale. Per un esempio di richiesta completo, consulta Registra un tracciamento del sistema.
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()); }
Procedura dettagliata del codice
L'esempio precedente esegue i seguenti passaggi:
- Definisci il worker: crea una classe
TraceUploadWorkerche estendeWorker. ImplementadoWorkper verificare che il file del profilo esista ancora, comprimilo e caricalo utilizzando l'SDK di backend o il client HTTP ed elimina il file locale una volta completato il caricamento. - Pianifica il lavoro:
- Crea un
OneTimeWorkRequestper il tuo worker. - Imposta i vincoli: utilizza
setRequiredNetworkType(NetworkType.UNMETERED),setRequiresDeviceIdle(true)esetRequiresCharging(true)in modo che il caricamento venga eseguito solo quando il dispositivo è connesso al Wi-Fi, in carica e inattivo. - Passa i dati: utilizza
setInputDataper passare il percorso del profilo dagetResultFilePathal worker. - Enqueue: invia la richiesta a
WorkManagerchiamandoWorkManager.enqueue.
- Crea un
Passaggi successivi
Dopo aver recuperato o caricato i profili, visualizzali nell'interfaccia utente di Perfetto, esegui query sui singoli profili con PerfettoSQL, analizza le tracce in blocco o analizza i profili con l'AI. Per indicazioni sulla configurazione di una pipeline di analisi lato server scalabile, consulta Deployment di Bigtrace su Kubernetes.