52 votes

Faible performance de CGEventPost sous la charge du GPU

Nous sommes tombés sur un problème de performance avec les événements Quartz, et plus particulièrement avec CGEventPost : lors d'une forte charge GPU, CGEventPost peut se bloquer. Nous avons créé une petite application de référence pour démontrer le problème . Cette application est juste une boucle qui crée, affiche et libère des événements.

Vous pouvez voir ci-dessous les résultats de l'exécution de l'application. La première exécution se fait sur un système inactif. Le deuxième est avec FurMark (test de stress du GPU) avec les cadrans augmentés autant que possible.

  • Inner est la durée de la boucle interne, c'est-à-dire la création, la publication et la diffusion d'un événement avec Quartz Events.
  • Outer est le temps que notre programme attend pour être réveillé (un sommeil). Cette durée devrait être proche de celle de notre sommeil, mais si le système est sous pression, elle peut être retardée.
  • Post est le temps que prend le post de l'événement.

    18:58:01.683 EventPerformance[4946:707] Measurements: (outer should be close to 10) 18:58:01.684 EventPerformance[4946:707] inner (ms): 0.04, outer (ms): 11.02, CGEventPost (ms): 0.03 18:58:01.684 EventPerformance[4946:707] inner (ms): 0.04, outer (ms): 11.02, CGEventPost (ms): 0.03 18:58:01.685 EventPerformance[4946:707] inner (ms): 0.07, outer (ms): 10.26, CGEventPost (ms): 0.03 18:58:01.685 EventPerformance[4946:707] inner (ms): 0.06, outer (ms): 10.85, CGEventPost (ms): 0.05 18:58:01.686 EventPerformance[4946:707] inner (ms): 0.07, outer (ms): 10.41, CGEventPost (ms): 0.04 18:58:01.686 EventPerformance[4946:707] inner (ms): 0.04, outer (ms): 10.39, CGEventPost (ms): 0.03 18:58:01.686 EventPerformance[4946:707] inner (ms): 0.05, outer (ms): 11.02, CGEventPost (ms): 0.03 18:58:01.687 EventPerformance[4946:707] inner (ms): 0.03, outer (ms): 10.67, CGEventPost (ms): 0.03 18:58:01.687 EventPerformance[4946:707] inner (ms): 0.08, outer (ms): 10.09, CGEventPost (ms): 0.05 18:58:01.688 EventPerformance[4946:707] Averages: (outer should be close to 10) 18:58:01.688 EventPerformance[4946:707] avg inner (ms): 0.05, avg outer (ms): 10.64, avg post (ms): 0.03

Ici, nous pouvons voir que l'affichage de l'événement prend environ 0,03 ms en moyenne. De plus, le fil de discussion semble être réveillé environ 0,5 ms trop tard. Pas de pics dans CGEventPost.

19:02:02.150 EventPerformance[5241:707] Measurements: (outer should be close to 10)
19:02:02.151 EventPerformance[5241:707] inner (ms): 0.03, outer (ms): 10.23, CGEventPost (ms): 0.02
19:02:02.151 EventPerformance[5241:707] inner (ms): 0.02, outer (ms): 10.54, CGEventPost (ms): 0.02
19:02:02.151 EventPerformance[5241:707] inner (ms): 0.02, outer (ms): 11.01, CGEventPost (ms): 0.01
19:02:02.152 EventPerformance[5241:707] inner (ms): 0.02, outer (ms): 10.74, CGEventPost (ms): 0.01
19:02:02.152 EventPerformance[5241:707] inner (ms): 0.02, outer (ms): 10.20, CGEventPost (ms): 0.01
19:02:02.152 EventPerformance[5241:707] inner (ms): 10.35, outer (ms): 11.01, CGEventPost (ms): 10.35
19:02:02.152 EventPerformance[5241:707] inner (ms): 0.03, outer (ms): 10.02, CGEventPost (ms): 0.02
19:02:02.153 EventPerformance[5241:707] inner (ms): 58.90, outer (ms): 10.11, CGEventPost (ms): 58.90
19:02:02.153 EventPerformance[5241:707] inner (ms): 0.03, outer (ms): 10.12, CGEventPost (ms): 0.02
19:02:02.153 EventPerformance[5241:707] Averages: (outer should be close to 10)
19:02:02.371 EventPerformance[5241:707] avg inner (ms): 7.71, avg outer (ms): 10.44, avg post (ms): 7.71

Lorsque le système est soumis à une forte charge du GPU, l'affichage d'un événement peut prendre (pics) des millisecondes au lieu de microsecondes. En cas de stress extrême du GPU (< 1 FPS), cette valeur peut prendre des secondes. CGEventPost parfois semble attendre que le GPU termine son travail avant de revenir. Notre thread est toujours programmé normalement, sans retard ni pics notables (extérieur).

Toute idée est la bienvenue.

5voto

nielsbot Points 9551

Je suppose que vous remplissez la file d'attente (port mach sous-jacent)...

Vous pouvez le confirmer en utilisant l'instrument "scheduling" ou "system call" dans Instruments. (Créez un nouveau document vierge, ajoutez l'instrument, puis dans la rubrique File > Record Options... assurez-vous que la case "mode différé" est cochée). Cela montrera toute l'activité des threads dans votre application (quand les threads se bloquent, quand ils dorment, quand ils sont activés, et pourquoi).

J'essaierais d'abord d'augmenter la priorité du fil (cf. man 3 PTHREAD_SCHEDPARAM ) du thread qui appelle CGEventPost . Si votre thread est bloqué sur un thread de priorité inférieure, le noyau devrait temporairement élever la priorité du thread bloquant pour éviter l'inversion de priorité et aider votre tâche à se terminer plus tôt.

Globalement, je pense que vous devrez mettre en place un Solution à 2 fils comme ci-dessous :

Créez une file d'attente pour les événements que vous souhaitez publier. Publiez les événements dans cette file d'attente à partir de votre thread principal (ou thread de publication d'événements), puis signalez à un second thread (un thread de consommation d'événements que vous créez) de parcourir la file d'attente et de publier tous les événements en suspens à l'aide de la commande CGEventPost .

Lorsque CGEventPost se bloque, votre deuxième fil d'affichage d'événement se bloquera, mais cela ne bloquera pas d'autres fils. Lorsque CGEventPost se débloque finalement, il consommera tous les événements en suspens postés par votre thread de consommateur d'événements et le thread de consommateur d'événements pourra recommencer à poster des événements.

Autre possibilité : pouvez-vous coaliser des événements ? Il y a certains types d'événements (mouvements de la souris ?) que vous pourriez regrouper en moins d'événements. Vous vous heurterez probablement encore à la limite de la file d'attente de CGEventPost Parfois, je pense que l'approche à deux fils est probablement la meilleure solution.

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