web-dev-qa-db-fra.com

Signification des messages de chorégraphe dans Logcat

J'ai installé les dernières versions de SDK (API 16) et obtenu le dernier ADT. Je vois maintenant ces messages dans le logcat, que je suis tout à fait sûr, je n'avais jamais vu auparavant. Est-ce que quelqu'un a une idée à ce sujet?

06-29 23: 11: 17.796: I/Chorégraphe (691): sauté 647 images! L'application effectue peut-être trop de travail sur son thread principal.

J'ai fait une recherche et trouvé ce lien: http://developer.Android.com/reference/Android/view/Choreographer.html . C'est une nouvelle classe introduite dans l'API 16.

J'ai besoin de savoir comment je peux déterminer le "trop ​​de travail" que ma demande peut faire car tout mon traitement est effectué dans AsyncTasks.

194
Code Poet

Chorégraphe permet aux applications de se connecter au vsync et de programmer correctement les performances pour améliorer leurs performances.

Les animations de vue Android utilisent en interne Choreographer dans le même but: synchroniser correctement les animations et éventuellement améliorer les performances.

Puisque Choreographer est informé de tous les événements vsync, je peux dire si l’un des Runnables transmis par Choreographer.post * apis ne se termine pas dans le temps d’une image, ce qui entraîne l’omission des images.

Selon ma compréhension, Choreographer ne peut détecter que le saut de trame. Il n'y a aucun moyen de dire pourquoi cela se produit.

Le message "L'application exécute peut-être trop de travail sur son thread principal." pourrait être trompeur.

133
CuriousChettai

Je suis en retard à la fête, mais j'espère que c'est un ajout utile aux autres réponses ici ...

Répondre à la question/tl: dr;

J'ai besoin de savoir comment je peux déterminer le "trop ​​de travail" que ma demande peut faire car tout mon traitement est effectué en AsyncTasks.

Sont tous candidats:

  • E/S ou traitement coûteux sur le thread principal (le chargement de dessinables, l’agrandissement des dispositions et la définition de Uri sur ImageView constituent tous IO sur le thread principal)
  • Affichage de hiérarchies grandes/complexes/profondes View
  • Invalidation de grandes portions d'une hiérarchie View
  • Méthodes onDraw coûteuses dans les noms personnalisés View '
  • Calculs coûteux dans les animations
  • Exécution de threads "worker" avec une priorité trop élevée pour être considéré comme "background" (AsyncTask sont "background" par défaut, Java.lang.Thread est et pas
  • Générer beaucoup de déchets, ce qui amène le ramasse-miettes à "arrêter le monde" - y compris le thread principal - pendant qu'il nettoie

Pour réellement déterminer la cause spécifique dont vous aurez besoin pour profiler votre application.

Plus de détails

J'ai essayé de comprendre Chorégraphe en expérimentant et en regardant code .

La documentation de Choreographer s'ouvre par "Coordonne le minutage des animations, des saisies et des dessins." ce qui est en fait une bonne description, mais le reste continue à sur-souligner les animations.

Le chorégraphe est en fait responsable de l'exécution de 3 types de callbacks, qui s'exécutent dans cet ordre:

  1. callbacks de traitement des entrées (traitement des entrées utilisateur telles que les événements tactiles)
  2. callbacks d'animation pour interpoler entre les images, fournissant un frame-start-time stable à toutes les animations en cours d'exécution. L’exécution de ces deuxièmes rappels signifie que tous les calculs liés à l’animation (par exemple, le changement de position des vues) ont déjà été effectués au moment où le troisième type de rappel est appelé ...
  3. rappels de traversée de vues pour dessiner la hiérarchie de vues.

L'objectif est de faire correspondre la vitesse à laquelle les vues invalidées sont redessinées (et les animations interpolées) avec l'écran vsync - généralement 60 images par seconde.

L’avertissement concernant les images ignorées ressemble à une idée après coup: le message est enregistré si un simple passe par les 3 étapes prend plus de 30 fois la durée d’image attendue; le nombre le plus petit que vous pouvez attendre à voir dans les messages du journal est "skipped 30 frames"; Si chaque passe prend 50% plus de temps que prévu, vous passerez quand même 30 images ( vilain! ), mais vous ne serez pas averti à ce sujet.

Parmi les 3 étapes impliquées, il est clair que ce ne sont pas seulement les animations qui peuvent déclencher l'avertissement: Invalider une partie importante d'une grande hiérarchie View ou d'un View avec une méthode onDraw compliquée peut suffire.

Par exemple, cela déclenchera l'avertissement à plusieurs reprises:

public class AnnoyTheChoreographerActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        setContentView(R.layout.simple_linear_layout);

        ViewGroup root = (ViewGroup) findViewById(R.id.root);

        root.addView(new TextView(this){
            @Override
            protected void onDraw(Canvas canvas) {
                super.onDraw(canvas);
                long sleep = (long)(Math.random() * 1000L);
                setText("" + sleep);
                try {
                    Thread.sleep(sleep);
                } catch (Exception exc) {}
            }
        });
    }
}

... qui produit une journalisation comme celle-ci:

11-06 09:35:15.865  13721-13721/example I/Choreographer﹕ Skipped 42 frames!  The application may be doing too much work on its main thread.
11-06 09:35:17.395  13721-13721/example I/Choreographer﹕ Skipped 59 frames!  The application may be doing too much work on its main thread.
11-06 09:35:18.030  13721-13721/example I/Choreographer﹕ Skipped 37 frames!  The application may be doing too much work on its main thread.

Vous pouvez voir dans la pile pendant onDraw que le chorégraphe est impliqué, que vous animiez ou non:

at exemple.AnnoyTheChoreographerActivity $ 1.onDraw (AnnoyTheChoreographerActivity.Java:25) sur Android.view.View.draw (View.Java:13759)

... un peu de répétition ...

sur Android.view.ViewGroup.drawChild (ViewGroup.Java:3169) sur Android.view.ViewGroup.dispatchDraw (ViewGroup.Java:3039) sur Android.view.View.draw (View.Java:13762) sur Android.widget. FrameLayout.draw (FrameLayout.Java:467) à l'adresse com.Android.internal.policy.impl.PhoneWindow $ DecorView.draw (PhoneWindow.Java:2396) à Android.view.View.getDisplayList (View.Java:12710) sur Android .view.View.getDisplayList (View.Java:12754) sur Android.view.HardwareRenderer $ GlRenderer.draw (HardwareRenderer.Java:1144) sur Android.view.ViewRootImpl.draw (ViewRootImpl.Java:2273) sur Android.view. ViewRootImpl.performDraw (ViewRootImpl.Java:2145) à Android.view.ViewRootImpl.performTraversals (ViewRootImpl.Java:1956) à Android.view.ViewRootImpl.doTraversal (ViewRootImpl.Java:1112) à Android.view.ViewRoot (ViewRootImpl.Java:4472) sur Android.view.Choreographer $ CallbackRecord.run (Choreographer.Java:725) sur Android.view.Choreographer.doCallbacks (Choreographer.Java:555) sur Android .view.Choreographer.do Frame (Choreographer.Java:525) sur Android.view.Choreographer $ FrameDisplayEventReceiver.run (Choreographer.Java:711) sur Android.os.Handler.handleCallback (Handler.Java:615) sur Android.os.Handler.dispatchMessage (Handler.Java:92) sur Android.os.Looper.loop (Looper.Java:137) sur Android.app.ActivityThread.main (ActivityThread.Java:4898)

Enfin, s'il existe des conflits d'autres threads qui réduisent la quantité de travail que le thread principal peut exécuter, les chances de sauter des images augmentent considérablement, même si vous ne faites pas réellement le travail sur le thread principal.

Dans cette situation, il peut être considéré comme trompeur de suggérer que l'application en fait trop sur le fil principal, mais Android veut vraiment que les threads de travail fonctionnent en priorité basse afin qu'ils ne puissent pas affamer le fil principal. . Si vos threads de travail ont une priorité basse, le seul moyen de déclencher l'avertissement de Choreographer consiste à en faire trop sur le thread principal.

64
Stevie

Ceci s’il s’agit d’un message d’information qui pourrait apparaître dans votre LogCat dans de nombreuses situations.

Dans mon cas, cela s'est produit lorsque je gonflais par programme plusieurs vues à partir de fichiers de présentation XML. Le message est inoffensif en soi, mais pourrait être le signe d'un problème ultérieur qui utiliserait tous les RAM que votre application est autorisée à utiliser et qui provoque la fermeture de la méga-perversité Force. Je suis devenu le genre de développeur qui aime voir son journal WARN/INFO/ERROR Free. ;)

Donc, ceci est ma propre expérience:

J'ai eu le message:

10-09 01:25:08.373: I/Choreographer(11134): Skipped XXX frames!  The application may be doing too much work on its main thread.

... lorsque je créais ma propre "liste à plusieurs sections super complexe" en gonflant une vue à partir de XML et en renseignant ses champs (images, texte, etc.) avec les données provenant de la réponse d'un REST/Service Web JSON (sans capacités de pagination), cette vue agirait en tant que lignes, en-têtes de sous-section et en-têtes de section en les ajoutant tous dans le bon ordre à LinearLayout (avec une orientation verticale à l'intérieur d'une ScrollView). Tout cela pour simuler un listView avec des éléments cliquables ... mais bon, c'est une autre question.

En tant que développeur responsable, vous souhaitez rendre l'application vraiment efficace avec les ressources système. La meilleure pratique pour les listes (lorsque vos listes ne sont pas si complexes) consiste à utiliser un ListActivity ou un ListFragment avec un chargeur et de remplir le ListView avec un adaptateur. c’est soi-disant plus efficace, c’est en fait et vous devriez le faire tout le temps, encore une fois… si votre liste n’est pas si complexe.

Solution: J'ai implémenté la pagination sur mon service Web REST/JSON pour empêcher les "tailles de réponse importantes" et j'ai enveloppé le code qui ajoutait les vues "lignes", "en-têtes de section" et "en-têtes de sous-section" sur une tâche asynchrone pour conserver la vue principale. Fil cool.

Alors ... J'espère que mon expérience aidera quelqu'un d'autre à se casser la tête avec ce message d'information.

Bonne piratage!

24
Oscar S.

Dans mon cas, j'ai ces messages lorsque je montre la barre d’action sherlock inderterminate progressbar. Comme ce n’est pas ma bibliothèque, j’ai décidé de masquer les sorties de Choreographer.

Vous pouvez masquer les sorties de Choreographer dans la vue Logcat, en utilisant cette expression de filtre:

balise: ^ ((?! Chorégraphe). *) $

J'ai utilisé une expression rationnelle expliquée ailleurs: expression régulière pour faire correspondre une ligne qui ne contient pas un mot?

11
Julien

Cela se produit généralement lors du débogage à l'aide de l'émulateur, qui est connu pour être lent de toute façon.

11
Buzz