0Pricing
Android Academy · Leçon

Mesurer les performances

Profileurs, traces et tests de performance.

Mesurer les performances est une leçon Android Academy gratuite sur CoddyKit. Ceci est la leçon 1 sur 4. Tu peux lire la leçon complète ci-dessous gratuitement — puis la pratiquer en direct dans le navigateur avec un éditeur de code intégré et un tuteur IA 24/7. Elle fait partie du parcours d'apprentissage Android Academy, et ta progression se synchronise sur le web et l'application CoddyKit. Le cours Android Academy comprend 4 leçons au total.

Mesurer avant d'optimiser

La règle d'or des travaux de performance : mesurez d'abord, ne devinez jamais. L'intuition humaine sur ce qui est lent est presque toujours erronée.

Dans cette leçon, vous découvrirez les outils qu'Android met à votre disposition pour observer les performances : les profileurs, les traces système et les micro-évaluations. Une fois que vous savez mesurer, chaque optimisation devient une décision fondée sur les données plutôt qu'une intuition.

  • Les profileurs affichent le processeur, la mémoire et l'énergie en temps réel.
  • Les traces système révèlent précisément où s'écoule le temps de chaque image.
  • Les évaluations de performance fournissent des valeurs reproductibles que vous pouvez comparer entre les compilations.

Le budget de trame de 16 ms

Sur un écran à 60 Hz, le système dessine une nouvelle trame toutes les 16,67 ms. Si votre application ne peut pas préparer une trame dans ce délai, celle-ci est ignorée et les utilisateurs perçoivent des saccades. Sur les appareils à 120 Hz, le budget diminue pour atteindre environ 8 ms.

Optimiser les performances consiste en réalité à rester dans ce budget. Le commentaire ci-dessous montre le calcul que vous devez garder à l'esprit.

// Frame budget math
// 60 Hz  -> 1000ms / 60  = 16.67ms per frame
// 90 Hz  -> 1000ms / 90  = 11.11ms per frame
// 120 Hz -> 1000ms / 120 =  8.33ms per frame
//
// Exceed the budget on the UI thread = a dropped frame = visible jank.
fun frameBudgetMs(refreshHz: Int): Double = 1000.0 / refreshHz

fun main() {
    println("60Hz  -> %.2f ms".format(frameBudgetMs(60)))
    println("120Hz -> %.2f ms".format(frameBudgetMs(120)))
}

Profileur d'Android Studio

Le profileur d'Android Studio (Afficher > Fenêtres d'outils > Profileur) se connecte à une application en cours d'exécution et affiche en direct les chronologies du CPU, de la mémoire, de l'énergie et du réseau.

  • CPU : enregistrez des traces de méthodes et des traces système pour trouver les chemins de code les plus sollicités.
  • Mémoire : surveillez les allocations et capturez des vidages du tas pour trouver les fuites.
  • Énergie : repérez les verrous de sortie de veille et les tâches excessives qui déchargent la batterie.

Profilez toujours une version de compilation de type publication sur un appareil réel. Les versions de débogage et les émulateurs donnent des chiffres trompeurs, car les optimisations sont désactivées.

Macrobenchmark pour des scénarios réels

La bibliothèque Macrobenchmark de Jetpack mesure des parcours utilisateur complets (démarrage, défilement, navigation) sur un appareil réel et fournit des métriques stables, comme la durée des trames et le temps de démarrage.

Vous écrivez un test qui lance votre application et exécute un parcours ; la bibliothèque le lance de nombreuses fois et vous fournit les valeurs médiane et du 99e percentile.

@RunWith(AndroidJUnit4::class)
class StartupBenchmark {
    @get:Rule val rule = MacrobenchmarkRule()

    @Test
    fun coldStartup() = rule.measureRepeated(
        packageName = "com.example.app",
        metrics = listOf(StartupTimingMetric()),
        iterations = 5,
        startupMode = StartupMode.COLD
    ) {
        pressHome()
        startActivityAndWait()
    }
}

Microbenchmark pour le code très sollicité

Lorsque vous devez savoir à quelle vitesse s'exécute une fonction unique, utilisez la bibliothèque Microbenchmark. Elle exécute votre code en boucle serrée, préchauffe le JIT et fournit le nombre de nanosecondes par opération en éliminant le bruit de mesure.

Utilisez-la pour les analyseurs, les sérialiseurs, le tri ou toute fonction utilitaire limitée par le CPU que vous appelez fréquemment.

@RunWith(AndroidJUnit4::class)
class JsonParseBenchmark {
    @get:Rule val benchmarkRule = BenchmarkRule()

    @Test
    fun parseLargePayload() {
        val raw = loadSampleJson()
        benchmarkRule.measureRepeated {
            val parsed = parseUsers(raw) // code under test
            // assertEquals avoids the compiler dropping the result
            assertTrue(parsed.isNotEmpty())
        }
    }
}

Traçage du système avec Perfetto

Le traçage du système capture ce que chaque thread et le système ont fait, trame par trame. Le profileur CPU d'Android Studio peut en enregistrer un, et vous pouvez également en capturer un avec adb, puis l'ouvrir dans Perfetto (ui.perfetto.dev).

Une trace montre les fameuses trames rouges, le travail effectué sur le thread principal et le temps passé par le GPU. C'est le meilleur outil pour diagnostiquer les saccades.

# Record a 5-second system trace from the command line
adb shell perfetto -o /data/misc/perfetto-traces/trace.perfetto-trace \
  -t 5s sched freq idle am wm gfx view

# Pull it to your machine, then open in https://ui.perfetto.dev
adb pull /data/misc/perfetto-traces/trace.perfetto-trace

Sections de trace personnalisées

Par défaut, les traces affichent le travail du framework. Pour étiqueter votre propre code, placez-le dans une section de trace nommée. Ces noms apparaissent ensuite sous forme de blocs étiquetés dans Perfetto, ce qui permet de repérer facilement les points sensibles.

Utilisez l'API androidx.tracing afin que les sections apparaissent dans les traces de débogage comme dans les traces de benchmark.

import androidx.tracing.trace

fun loadDashboard(repo: Repo): Dashboard {
    return trace("loadDashboard") {
        val user = trace("fetchUser") { repo.user() }
        val feed = trace("fetchFeed") { repo.feed() }
        Dashboard(user, feed)
    }
}
// In Perfetto you will now see named slices:
// loadDashboard > fetchUser, fetchFeed

Suivi des trames ignorées à l'exécution

Vous n'avez pas toujours un profileur connecté. JankStats est une bibliothèque Jetpack qui signale les trames saccadées depuis votre application en cours d'exécution, afin que vous puissiez les enregistrer ou envoyer des agrégats à vos outils d'analyse.

Elle s'intègre à la fenêtre et vous rappelle chaque fois qu'une trame dépasse son budget.

val jankStats = JankStats.createAndTrack(window) { frameData ->
    if (frameData.isJank) {
        Log.w("Jank", "Janky frame: ${frameData.frameDurationUiNanos} ns")
        analytics.logJank(frameData.frameDurationUiNanos)
    }
}

// Pause/resume with your screen lifecycle
override fun onResume() { super.onResume(); jankStats.isTrackingEnabled = true }
override fun onPause() { super.onPause(); jankStats.isTrackingEnabled = false }

Lire les chiffres : les percentiles

Une simple moyenne masque les problèmes. Si votre trame moyenne dure 10 ms, mais que le 99e percentile est de 40 ms, 1 % des trames sont saccadées et les utilisateurs le ressentent. Examinez toujours P50, P90 et P99, et pas uniquement la moyenne.

Les benchmarks les calculent pour vous. L'utilitaire ci-dessous illustre le principe à partir d'échantillons bruts de trames.

fun percentile(samplesMs: List<Double>, p: Int): Double {
    val sorted = samplesMs.sorted()
    val index = ((p / 100.0) * (sorted.size - 1)).toInt()
    return sorted[index]
}

fun main() {
    val frames = listOf(8.0, 9.0, 10.0, 9.5, 11.0, 40.0, 9.0, 10.5)
    println("P50 = %.1f ms".format(percentile(frames, 50)))
    println("P99 = %.1f ms".format(percentile(frames, 99)))
}

Un processus de mesure reproductible

Des chiffres fiables proviennent d'un processus rigoureux. Suivez cette liste de contrôle à chaque fois :

  • Utilisez une version de publication / non débogable (R8 activé).
  • Exécutez l'application sur un appareil physique, branché, dont l'état thermique est stable.
  • Répétez le scénario plusieurs fois et indiquez la médiane.
  • Modifiez une seule chose à la fois et mesurez à nouveau.
  • Comparez les résultats à une base de référence enregistrée afin de pouvoir prouver l'amélioration.

Si vous négligez ces étapes, vous poursuivrez le bruit de mesure au lieu de résoudre de vrais problèmes.

Où le temps est réellement dépensé

La plupart des saccades Android proviennent d'un petit nombre de causes. Les connaître vous indique vers où orienter vos outils :

  • Travail sur le thread principal : accès au disque ou au réseau et traitement JSON sur le thread d'interface.
  • Recompositions excessives : Compose redessine beaucoup trop d'éléments.
  • Allocations incessantes : pauses dues au ramasse-miettes.
  • Passages de mise en page : mises en page profondément imbriquées ou mesurées à répétition.

Les prochaines leçons de ce cours abordent directement la recomposition, les fuites mémoire et le démarrage. C'est la mesure qui vous indique lequel de ces problèmes résoudre en premier.

Vérification rapide

Vous souhaitez mesurer de manière stable et reproductible la durée du démarrage à froid de votre application sur un appareil réel, lors de plusieurs exécutions. Quel outil convient le mieux ?

Récapitulatif : vous savez maintenant mesurer

Vous avez appris à rendre les performances visibles avant de modifier quoi que ce soit :

  • Le budget de trame de 16 ms définit la différence entre une interface fluide et des saccades.
  • Le profileur d'Android Studio affiche en direct l'utilisation du CPU, de la mémoire et de l'énergie.
  • Les macrobenchmarks et les microbenchmarks fournissent des chiffres reproductibles.
  • Les traces Perfetto et les sections trace() personnalisées révèlent où le temps est dépensé.
  • JankStats signale les saccades depuis l'application en cours d'exécution.
  • Lisez P50/P90/P99, profilez les versions de publication sur des appareils réels et ne modifiez qu'une seule chose à la fois.

Ensuite, nous appliquerons ces principes à l'une des principales sources de saccades dans Compose : la recomposition.

Questions Fréquemment Posées

La leçon « Mesurer les performances » est-elle gratuite ?

Oui — le texte complet de « Mesurer les performances » est gratuit à lire ici sur le web. Pour la pratiquer de manière interactive (un éditeur de code intégré et un tuteur IA 24/7) et déverrouiller le reste du cours Android Academy, passe à CoddyKit PRO. Le cours Android Academy comprend 4 leçons au total.

Qu'est-ce que j'apprendrai dans « Mesurer les performances » ?

Profileurs, traces et tests de performance. Tu pratiques Android Academy avec du code pratique que tu exécutes directement dans le navigateur, et un tuteur IA 24/7 répond à tes questions au fur et à mesure que tu avances dans la leçon.

Dois-je avoir de l'expérience pour commencer Android Academy ?

Aucune expérience préalable n'est requise. Android Academy sur CoddyKit est structuré pour les débutants jusqu'aux apprenants avancés, donc tu peux commencer ici ou depuis le début et avancer à ton rythme. Ceci est la leçon 1 sur 4.

Combien de temps prend la leçon « Mesurer les performances » ?

La plupart des leçons CoddyKit prennent environ 5–10 minutes. Chacune est courte et interactive, tu progresses régulièrement et tu repiques exactement où tu t'es arrêté sur le web et l'app.

Peux-tu écrire et exécuter du code dans cette leçon Android Academy ?

Oui. Chaque leçon Android Academy inclut un éditeur de code intégré, tu écris et exécutes du vrai code directement dans ton navigateur et tu reçois des retours IA instantanés — aucune configuration locale requise.

Toutes les leçons de ce cours

  1. Mesurer les performances
  2. Maîtriser la recomposition
  3. Fuites mémoire et corrections
  4. Démarrage et profils de référence
← Retour à Android Academy