198 votes

Signification des messages du Chorégraphe dans Logcat

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

06-29 23:11:17.796 : I/Choreographer(691) : Saut de 647 images ! Le site application effectue peut-être trop de travail sur son thread principal.

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

J'ai besoin de savoir comment déterminer la "surcharge de travail" de mon application, étant donné que tous mes traitements sont effectués dans le système de gestion de l'information. AsyncTask s.

0 votes

À partir de votre lien : Coordonne le timing des animations, des entrées et des dessins. On dirait qu'il est utilisé pour faire des animations dans l'interface utilisateur.

0 votes

Exécutez-vous dans l'émulateur ?

0 votes

Oui, je le suis. Je comprends que le Chorégraphe est probablement le composant qui gère les animations et que lorsqu'il n'a pas assez de cycles de processeur, il saute des images et affiche ce message de débogage. Ce qui me préoccupe, c'est de savoir ce qui, dans mon thread principal, pourrait être à l'origine de ce problème et comment le repérer. Pour l'instant, tous mes traitements sont effectués dans des threads d'arrière-plan.

137voto

CuriousChettai Points 1154

Choreographer permet aux applications de se connecter à la vsync, et de chronométrer correctement les choses pour améliorer les performances.

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

Comme Choreographer est informé de tous les événements vsync, il peut savoir si l'un des Runnables transmis par l'apis Choreographer.post* ne se termine pas dans le temps d'une image, ce qui entraîne le saut d'images.

D'après ce que j'ai compris, Choreographer ne peut détecter que les sauts de trame. Il n'a aucun moyen de dire pourquoi cela se produit.

Le message "L'application effectue peut-être trop de travail sur son thread principal" peut être trompeur.

41 votes

+1 pour le "pourrait être trompeur". Mon application n'utilise aucune animation, ni aucun graphique, et pourtant je reçois ces messages. À un moment donné, Google Maps (pas mon application) se ferme de force... Un autre service de l'application Google (pas mon application !) se bloque également... Je n'ai aucune idée de ce à quoi Google pensait en introduisant ces nouveaux trucs Jelly Bean qui cassent des choses qui fonctionnent encore merveilleusement bien sur Froyo.

0 votes

Si trop de travail est effectué sur le thread principal, Android peut ne pas être aussi déterministe qu'il le souhaite, mais il ne tue aucune tâche, n'est-ce pas ?

0 votes

Je pense que "Je peux dire si l'un des Runnables transmis par l'apis Choreographer.post* ne se termine pas dans le temps d'une image, ce qui fait sauter des images" n'est pas très correct. Je viens de jeter un coup d'oeil au code du Chorégraphe, il exécute tous les runnables dont le dueTime <= now quand il reçoit un VSYNC. ce qui signifie que tous les runnables postés au Chorégraphe dont le temps d'exécution est inférieur au temps actuel ne se terminent pas dans un temps de trame, ce qui fera sauter des trames.

66voto

Stevie Points 1515

Je suis en retard pour la fête, mais j'espère que cela sera un complément utile aux autres réponses données ici...

Répondre à la question / tl:dr ;

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

Les personnes suivantes sont toutes candidates :

  • IO ou des traitements coûteux sur le thread principal (chargement des éléments graphiques, gonflement des mises en page et réglage des paramètres). Uri sur ImageView Tout est constitué d'entrées-sorties sur le fil principal.)
  • Rendu large/complexe/profond View hiérarchies
  • L'invalidation de grandes parties d'un View hiérarchie
  • Coûteux onDraw dans les méthodes personnalisées View 's
  • Calculs coûteux dans les animations
  • Exécution de threads "travailleurs" à une priorité trop élevée pour être considérée comme "d'arrière-plan" ( AsyncTask sont "en arrière-plan" par défaut, java.lang.Thread est no )
  • Générer beaucoup de déchets, ce qui amène le ramasseur de déchets à "arrêter le monde" - y compris le fil principal - pendant qu'il nettoie.

En fait, pour déterminer la cause spécifique dont vous aurez besoin pour profiler votre application.

Plus de détails

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

La documentation de Choreographer s'ouvre sur "Coordonne le timing des animations, de la saisie et du dessin", ce qui est une bonne description, mais le reste met trop l'accent sur les animations.

Le Chorégraphe est en fait responsable de l'exécution de 3 types de callbacks, qui se déroulent dans cet ordre :

  1. les rappels de traitement des entrées (traitement des entrées de l'utilisateur telles que les événements tactiles)
  2. les callbacks d'animation pour le tweening entre les images, fournissant un temps de départ d'image stable à toutes les animations en cours. L'exécution de ces callbacks en second 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 callback est invoqué...
  3. les callbacks de traversée de vue pour dessiner la hiérarchie de la vue.

L'objectif est de faire correspondre le taux auquel les vues invalidées sont redessinées (et les animations interpolées) avec la vsync de l'écran - généralement 60fps.

L'avertissement concernant les images sautées semble être une réflexion après coup : Le message est enregistré si un simple passer par les 3 étapes prend plus de 30x la durée prévue de la trame, de sorte que le plus petit nombre que vous pouvez vous attendre à voir dans les messages de log est "sauté". 30 cadres" ; Si chaque prend 50% plus de temps qu'il ne devrait, vous sauterez quand même 30 images ( vilain ! ) mais vous ne serez pas prévenu.

D'après les trois étapes concernées, il est clair que les animations ne sont pas les seules à pouvoir déclencher l'avertissement : L'invalidation d'une partie significative d'une grande View ou une View avec une méthode onDraw compliquée pourrait suffire.

Par exemple, ceci déclenchera l'avertissement de manière répétée :

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

... ce qui produit un enregistrement comme celui-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 sur la pile pendant onDraw que le chorégraphe est impliqué, que vous animiez ou non :

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

... pas mal de répétitions...

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

Enfin, en cas de conflit avec d'autres threads qui réduisent la quantité de travail que le thread principal peut effectuer, le risque de sauter des images augmente considérablement, même si vous n'effectuez pas réellement le travail sur le thread principal.

Dans cette situation, il pourrait être considéré comme trompeur de suggérer que l'application en fait trop sur le thread principal, mais Android souhaite vraiment que les threads de travail soient exécutés en basse priorité. afin de les empêcher d'affamer le fil principal. Si vos threads de travail sont peu prioritaires, la seule façon de déclencher l'avertissement du Chorégraphe est d'en faire trop sur le thread principal.

0 votes

C'était une excellente réponse, dans mon cas, j'ai plusieurs threads pour gérer les autres travaux, et j'accède de façon répétée au thread principal de l'interface utilisateur à partir de ces autres threads. Ces accès sont nécessaires, quelle peut être une solution pour cela à votre avis ?

1 votes

"à plusieurs reprises j'accède au main-ui-thread" -- vous voulez dire que vous utilisez View.post , Activity.runOnUiThread ou directement à l'aide d'un Handler pour envoyer le travail au fil principal ? Si ce n'est pas un travail d'interface utilisateur, ne le donnez pas à faire au thread principal :). Si c'est du travail d'interface utilisateur, vous n'avez pas le choix, et si cela cause des images perdues, vous devez probablement chercher d'autres moyens d'optimiser votre code d'interface utilisateur. Peut-être avez-vous un cas qui mérite d'être posté dans une nouvelle question ?

0 votes

J'ai déjà posté en fait, maintenant je vais y ajouter du code. stackoverflow.com/questions/29767997/

24voto

RacZo Points 5731

Il s'agit d'un message d'information qui peut apparaître dans votre LogCat dans de nombreuses situations.

Dans mon cas, cela s'est produit lorsque j'ai gonflé plusieurs vues à partir de fichiers de mise en page XML de manière programmatique. Le message est inoffensif en soi, mais il pourrait être le signe d'un problème ultérieur qui utiliserait toute la RAM que votre application est autorisée à utiliser et provoquerait le méga-maléfique "Force Close". Je suis devenu le genre de développeur qui aime voir son journal sans WARN/INFO/ERROR ;)

Donc, c'est ma propre expérience :

J'ai reçu 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 multi-section super-complexe" en gonflant une vue à partir de XML et en remplissant ses champs (images, texte, etc...) avec les données provenant de la réponse d'un service web REST/JSON (sans possibilité de pagination), ces vues agissaient comme des lignes, des en-têtes de sous-section et des en-têtes de section en les ajoutant toutes dans l'ordre correct à un LinearLayout (avec une orientation verticale dans un ScrollView). Tout cela pour simuler une listView avec des éléments cliquables... mais bon, c'est pour une autre question.

En tant que développeur responsable, vous voulez rendre l'application vraiment efficace avec les ressources du système, donc la meilleure pratique pour les listes (quand vos listes ne sont pas si complexes) est d'utiliser une ListActivity ou ListFragment avec un Loader et de remplir la ListView avec un Adapter, c'est supposé être plus efficace, en fait ça l'est et vous devriez le faire tout le temps, encore une fois... si votre liste n'est pas si complexe.

La solution : J'ai implémenté la pagination sur mon service web REST/JSON pour éviter les "grosses tailles de réponse" et j'ai enveloppé le code qui ajoute les vues "rows", "section headers" et "sub-section headers" dans une AsyncTask pour garder le Main Thread cool.

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

Bon piratage !

0 votes

Comment utilisez-vous AsyncTask pour éviter ce problème ?

11voto

Buzz Points 115

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.

36 votes

J'ai aussi ça sur le journal de mon téléphone parfois.

3 votes

Oui, le processus est très lent lorsque ce message s'imprime dans le logcat. Il semble que dvm ignore si nous fonctionnons en mode release en changeant la valeur de débogage à false.

1 votes

C'est arrivé sur un vrai téléphone pour moi : Motorola Droid Bionic

11voto

Julien Deflaux Points 448

Dans mon cas, j'ai ces messages lorsque je montre la barre d'action sherlock dans la barre de progression inderterminée. Comme ce n'est pas ma bibliothèque, j'ai décidé de cacher les sorties Chorégraphe.

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

tag:^((!Choreographer).*)$

J'ai utilisé une regex expliquée ailleurs : Expression régulière pour correspondre à une ligne qui ne contient pas de mot ?

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X