2017-10-03 5 views
0

C'est fou! J'ai entendu que les threads Python sont lents mais c'est au-delà de la normale.La même vitesse de socket est 66% plus lente sur un nouveau thread?

Voici le pseudo-code:

class ReadThread: 

    v = [] 
    def __init__(self, threaded = True): 
     self.v = MySocket('127.0.0.1') 
     if threaded: 
      thread.start_new_thread(self._scan,()) 

    def read(self): 
     t0 = datetime.now() 
     self.v.read('SomeVariable') 
     t = datetime.now() 
     dt = (t-t0).total_seconds() 

     print dt 

    def _scan(self): 
     while True: 
      self.read() 

Si je lance la lecture() dans une boucle while dans le thread principal comme ceci:

r = ReadThread(threaded = False) 
while True: 
    r.read() 

dt est d'environ 78 ms avec petite variation. Maintenant, si je le lance dans un nouveau fil comme celui-ci:

r = ReadThread(threaded = True) 
while True: 
    pass 

dt est d'environ 130 ms avec + -10ms variance!

Pourquoi est-ce si lent? Est-ce que je fais quelque chose de vraiment mal? C'est la même chose juste dans un nouveau fil! MySocket() est un objet qui utilise un socket pour lire/écrire des variables sur un serveur et read() reçoit juste une variable pour le test.

Répondre

2

Il est difficile de reproduire ce problème localement sans savoir ce que MySocket est, et l'exemple complet. Cependant, je peux essayer de deviner, que le problème est ce cycle:

while True: 
    pass 

Il est très CPU-consommation. Le processeur tourne littéralement tout le temps, prenant les cycles de CPU à lui-même, et ne laissant pas le socket fonctionner. Contrairement à cela, les opérations de lecture de socket sont généralement bloquantes et inactives pour l'arrivée des données, de sorte qu'elles ne consomment quasiment aucune unité centrale.

Dans le premier exemple, vous exécutez votre socket alors que rien d'autre ne consomme du CPU. Dans le deuxième exemple, le thread principal consomme 1 CPU complètement. Essayez de remplacer ce cycle par une opération de ralenti habituelle, par ex. time.sleep(60). Ainsi, le thread principal restera inactif pendant 60 secondes pendant que le thread socket lira et traitera les données.

r = ReadThread(threaded = True) 
time.sleep(60) 

Quelle sera la mesure dans ce cas alors?

+0

Vous avez raison. Je suis stupide. Même vitesse maintenant ... – Carlos

+0

Dans le code réel, chaque thread demande des valeurs en les écrivant dans une liste. Un autre thread lit la liste et écrit les réponses. Il surveille de manière continue les nouvelles demandes. Les threads de consommation surveillent constamment les réponses. J'ai trouvé qu'un petit time.sleep() fait l'affaire mais quelles seraient les autres façons de mieux résoudre le problème? Des événements peut-être? – Carlos

+1

Vous devez apprendre les primitives de synchronisation de threads (https://docs.python.org/3.4/library/threading.html). Je pense que 'Event' et/ou' Condition' sont les plus adaptés à votre cas d'utilisation, en fonction du nombre de threads qui doivent réagir. –