[Python-de] probleme mit threads die nicht zum zug kommen -- vermutlich pygame.Clock.tick() schuld?

Bastian Venthur venthur at debian.org
Mi Dez 12 23:05:29 UTC 2007


N'abend Liste,

ich habe ein Programm das mit vier Threads arbeitet und bemerke immer
mal wieder (wie das bei nebenläufigen Anwendungen halt so ist)
eigenartige Fehler die darauf hinweisen, dass mindestens ein Thread
scheinbar nicht mehr zum Zug kommt. Es handelt sich nicht um einen
Deadlock oder etwas in der Richtung, das Problem löst sich irgendwann
auch wieder von alleine auf, aber es darf trotzdem nicht passieren ;)

Hier mal der grobe Aufbau der Threads

* T1: blockierendes empfangen von UDP Daten über socket in einer
Endlosschleife. Die Daten gehen ziemlich genau mit 25Hz ein und sind
Pakete die ein paar Hundert Byte groß sind.

* T2: blockierendes empfangen von UDP Daten auf einem zweiten Port in
einer Endlosschleife. Die Pakete sind hier auch recht klein und kommen
nur alle paar Minuten an

Die obigen beiden Treads basteln etwas an den Empfangenen Daten herum
(nicht CPU intensiv und ziemlich fix) und packen das Ergebnis in eine
Queue (meine Eventqueue)

* T3: Abarbeiten der Queue in einer Endlosschleife (auch sehr fix)

* T4: (vermutlich der Übeltäter) eine Endlosschleife in der
pygame.Clock.tick() aufgerufen wird. In dieser Schleife passieren
eigentlich auch keine rechenintensiven Sachen, tick(60) gibt immernoch
16ms zurück!

Im Grunde bin ich etwas verwundert dass manchmal manche Threads
sekundenlang nicht zum Zug kommen, da eigentlich alles mit max mit 25Hz
durchlaufen wird und dabei auch nichts rechen- oder IO-Intensives
passiert. Und 25Hz ist doch eigentlich sehr langsam oder?!

Wenn ich bei Clock.tick() eine Framerate von 60Hz wünsche tritt das
Problem recht häufig auf, bei moderateren 25Hz eher selten. Ich hab
gelesen, das ein time.wait(10) kurz vor oder nach einem Clock.tick()
helfen soll, weil die CPU dann mal kurz freigegeben wird. Ich find das
aber etwas hack'ish und würde ne sauberere Lösung bevorzugen.

Ich hab mich ein bisschen zu Threads in Python eingelesen und erfahren,
dass es keine wirkliche Nebenläufigkeit gibt, da Python nur einen
Prozessor benutzt. Erschreckend, aber ok. Ich könnte die ersten drei
Threads zur Not zu einem Zusammenfassen indem ich asyncore benutze.

Erste Frage: ist asyncore CPU intensiv? Oder besser: CPU intensiver als
zwei threads die jeweils blockierend auf einem Port lauschen?

Und dann bleibt noch die Frage ob das wirklich das Problem beheben würde
oder nur das Risiko vermindert. Ich glaube weniger als zwei Threads
gehen bei dieser Anwendung wirklich nicht, einmal die pygame-loop und
einmal meine Netzwerkschleife die nebenbei Daten empfangen muss.

Ich weis meine Infos sind nicht sehr konkret, aber hat vielleicht jemand
ne Ahnung was hier schief läuft oder ne Idee wie ich das Problem
umschiffen könnte?


Schöne Grüße,

Bastian


-- 
Bastian Venthur                                      http://venthur.de
Debian Developer                                 venthur at debian org