Comment obtenir une vitesse plus rapide lors de l'utilisation de multi-threading en python
Maintenant, je suis en train d'étudier comment extraire les données de site aussi vite que possible. Pour obtenir une vitesse plus rapide, im vu de l'utilisation de multi-thread. Voici le code que j'ai utilisé pour tester la différence entre le multi-thread et simple post.
import threading
import time
import urllib
import urllib2
class Post:
def __init__(self, website, data, mode):
self.website = website
self.data = data
#mode is either "Simple"(Simple POST) or "Multiple"(Multi-thread POST)
self.mode = mode
def post(self):
#post data
req = urllib2.Request(self.website)
open_url = urllib2.urlopen(req, self.data)
if self.mode == "Multiple":
time.sleep(0.001)
#read HTMLData
HTMLData = open_url.read()
print "OK"
if __name__ == "__main__":
current_post = Post("http://forum.xda-developers.com/login.php", "vb_login_username=test&vb_login_password&securitytoken=guest&do=login", \
"Simple")
#save the time before post data
origin_time = time.time()
if(current_post.mode == "Multiple"):
#multithreading POST
for i in range(0, 10):
thread = threading.Thread(target = current_post.post)
thread.start()
thread.join()
#calculate the time interval
time_interval = time.time() - origin_time
print time_interval
if(current_post.mode == "Simple"):
#simple POST
for i in range(0, 10):
current_post.post()
#calculate the time interval
time_interval = time.time() - origin_time
print time_interval
comme vous pouvez le voir, c'est un code très simple. j'ai d'abord définir le mode "Simple", et je peux obtenir l'intervalle de temps: années 50(peut-être que ma vitesse est un peu lent :(). puis j'ai mis le mode "Multiple", et je obtenir l'intervalle de temps: 35. à partir de ce que je peux voir, multi-thread peut en fait augmenter la vitesse, mais le résultat n'est pas aussi bon que je l'imagine. je veux obtenir une vitesse beaucoup plus rapide.
de débogage, j'ai trouvé que le programme principalement des blocs à la ligne: open_url = urllib2.urlopen(req, self.data)
, cette ligne de code prend beaucoup de temps pour poster et recevoir les données provenant de ce site web. je suppose que je peux peut-être obtenir une vitesse plus rapide par ajout de time.sleep()
et de l'utilisation de multi-threading à l'intérieur de la urlopen
fonction, mais je ne peux pas le faire parce que ses le python, la fonction.
si ne pas considérer le prossible limites que le serveur bloque le post de vitesse, que puis-je faire pour obtenir la plus grande vitesse? ou tout autre code, je peux modifier? merci beaucoup!
- threading est une mauvaise idée en python, il devient un goulot d'étranglement facilement et peut se faire piéger par le GIL, essayez de multitraitement.
- les threads sont un détail de l'implémentation ici, l'accent est d'avoir de multiples connexions ouvertes. Le GIL aspect de threads en Python n'a pas de rôle ici que ce soit.
- vous devriez vraiment lire sur GIL et le filetage avant de faire des déclarations comme ça... commencez ici: PyCon 2010: la Compréhension de l'Python GIL
Vous devez vous connecter pour publier un commentaire.
Dans de nombreux cas, le python de thread n'est pas d'améliorer la vitesse d'exécution très bien... parfois, il fait qu'empirer les choses. Pour plus d'informations, voir David Beazley de PyCon2010 présentation Mondiale de l'Interprète de Verrouillage /Pycon2010 GIL dias. Cette présentation est très instructif, je le recommande fortement à toute personne qui envisage de filetage...
Même si David Beazley parler explique que le trafic réseau qui améliore la planification de Python module threading, vous devez utiliser le module multiprocessing. J'ai inclus cette option dans votre code (voir en bas de ma réponse).
L'exécution de ce sur une de mes anciennes machines (Python 2.6.6):
Je suis d'accord avec TokenMacGuy commentaire et les chiffres ci-dessus comprennent le déplacement des
.join()
à une autre boucle. Comme vous pouvez le voir, python multitraitement est nettement plus rapide que le filetage.La plus grande chose que vous faites mal, c'est de blesser votre débit le plus, c'est la façon dont vous appelez
thread.start()
etthread.join()
:Chaque passage dans la boucle, vous créer un thread, le lancer, et puis attendez la fin de la Avant de passer à la suivante fil. Vous ne faites rien, simultanément, à tous!
Ce que vous devriez probablement faire de la place, c'est:
threading
au lieu demultiprocessing
est une solution raisonnable. Cela va doubler si un Keep-Alive http client ont été utilisés (urlib3
était d'environ 30% plus rapide que laurllib2
dans mon fixe de filetage tests, aucune amélioration du contraire), ce qui ne serait pas disponible à travers le processus.Gardez à l'esprit que le seul cas où le multi-threading peut "augmenter la vitesse" en Python, c'est quand vous avez opérations comme celui-ci qui sont fortement I/O bound. Sinon le multi-threading n'augmente pas de "vitesse" car il ne peut pas fonctionner sur plus d'un CPU (non, pas même si vous disposez de plusieurs cœurs, python ne fonctionne pas de cette façon). Vous devez utiliser le multi-threading lorsque vous souhaitez que deux choses à faire en même temps, pas quand vous avez besoin de deux choses pour être parallèle (c'est à dire deux processus en cours d'exécution séparément).
Maintenant, ce que vous êtes en train de faire ne sera pas réellement d'augmenter la vitesse de recherche DNS, mais il permettra aussi de multiples demandes à être tiré en attendant les résultats de certains autres, mais vous devez faire attention à la façon dont beaucoup vous faire ou vous faites juste le temps de réponse encore pire qu'ils ne le sont déjà.
Aussi s'il vous plaît arrêter d'utiliser urllib2, et l'utilisation des Demandes: http://docs.python-requests.org
Une recherche DNS prend du temps. Il n'y a rien que vous pouvez faire à ce sujet. De grosses latences sont l'une des raisons pour l'utilisation de plusieurs threads en premier lieu - de multiples recherches site de petite annonce GET/POST, peut alors se produire en parallèle.
De vidage de la fonction sleep() - ce n'est pas aider.
time.sleep()
est inutile. En effet, il fonctionne aussi bien après dumpingsleep()
, mais comment peut-il réaliser multi-thread sanssleep()
? python exécuter les threads différents intervalles aléatoires automatiquement? si oui, qui est l'utilisation desleep()
fonction?