web-dev-qa-db-fra.com

android - qu'est-ce qu'un sondage natif de file d'attente de messages une fois dans android?

Je sais que les threads ont une file d'attente de messages et les gestionnaires peuvent leur envoyer des runnables ou des messages, mais lorsque je profile mon Android en utilisant Android outils Studio, il y a un processus étrange:

Android.os.MessageQueue.nativePollOnce

Il utilise le CPU plus que tous les autres processus. Qu'est-ce que c'est et comment puis-je réduire le temps que le processeur y consacre? Vous pouvez trouver le résultat du profileur ci-dessous.

enter image description here

23
Sajad Norouzi

Réponse courte:

La méthode nativePollOnce est utilisée pour "attendre" jusqu'à ce que le prochain Message devienne disponible. Si le temps passé pendant cet appel est long, votre thread principal (UI) n'a pas vraiment de travail à faire et attend que les prochains événements soient traités. Il n'y a pas lieu de s'en inquiéter.

Explication:

Parce que le thread "principal" est chargé de dessiner l'interface utilisateur et de gérer divers événements, il est Runnable a une boucle qui traite tous ces événements. La boucle est gérée par un Looper et son travail est assez simple: il traite tous les messages dans le MessageQueue .

Un Message est ajouté à la file d'attente par exemple en réponse aux événements d'entrée, comme rappel de rendu de trame ou même vos propres appels _Handler.post_. Parfois, le thread principal n'a aucun travail à faire (c'est-à-dire, aucun message dans la file d'attente), ce qui peut arriver par exemple juste après avoir terminé le rendu d'une seule image (le fil vient de dessiner une image et est prêt pour la suivante, attend juste le bon moment). Deux méthodes Java de la classe MessageQueue nous intéressent: Message next() et boolean enqueueMessage(Message, long). Message next(), comme son nom l'indique, prend et renvoie le message suivant de la file d'attente. Si la file d'attente est vide (et qu'il n'y a rien à retourner), la méthode appelle native void nativePollOnce(long, int) qui se bloque jusqu'à ce qu'un nouveau message soit ajouté. À ce stade, vous pourriez vous demander comment nativePollOnce sait quand se réveiller. Voilà une très bonne question. Lorsqu'un Message est ajouté à la file d'attente, le framework appelle la méthode enqueueMessage, qui non seulement insère le message dans la file d'attente, mais appelle également native static void nativeWake(long), si nécessaire pour réveiller la file d'attente. La magie de base de nativePollOnce et nativeWake se produit dans le code natif (en fait, C++) . Native MessageQueue utilise un appel système Linux nommé epoll , qui permet de surveiller un descripteur de fichier pour les événements IO. nativePollOnce appelle _epoll_wait_ sur un certain descripteur de fichier, tandis que nativeWake écrit dans le descripteur, qui est l'une des opérations IO, _epoll_wait_ attend. Le noyau retire alors le thread en attente d'epoll de l'état d'attente et le thread procède à la gestion du nouveau message. Si vous connaissez les méthodes Object.wait() et Object.notify() de Java, vous pouvez imaginer que nativePollOnce est un équivalent approximatif de Object.wait() et nativeWake pour Object.notify(), sauf qu'ils sont implémentés de manière complètement différente: nativePollOnce utilise epoll et Object.wait() utilise futex Appel Linux. Il convient de noter que ni nativePollOnce ni Object.wait() ne gaspillent les cycles de processeur, car lorsqu'un thread entre dans l'une ou l'autre méthode, il devient désactivé à des fins de planification des threads (en citant le javadoc pour le Object classe). Cependant, certains profileurs peuvent reconnaître par erreur les threads en attente d'époll (ou même en attente d'objet) comme exécutant et consommant du temps CPU, ce qui est incorrect. Si ces méthodes gaspillaient réellement les cycles de processeur, toutes les applications inactives utiliseraient 100% du processeur, chauffant et ralentissant l'appareil.

Conclusion:

Vous ne devriez pas vous soucier de nativePollOnce. Cela indique simplement que le traitement de tous les messages est terminé et que le thread attend le prochain. Eh bien, cela signifie simplement que vous ne donnez pas trop de travail à votre thread principal;)

34
Lawiusz