2016-07-25 11 views
0

Ich denke requests.get sollte Block sein, also sollte es keinen Unterschied zwischen run und run2 geben.Warum kann gevent Anfragen zum Herunterladen beschleunigen?

import sys 

import gevent 
import requests 
from gevent import monkey 
monkey.patch_all() 
def download(): 
    requests.get('http://www.baidu.com').status_code 
def run(): 
    ls = [gevent.spawn(download) for i in range(100)] 
    gevent.joinall(ls) 
def run2(): 
    for i in range(100): 
     download() 
if __name__ == '__main__': 
    from timeit import Timer 
    t = Timer(stmt="run();", setup="from __main__ import run") 
    print('good', t.timeit(3)) 
    t = Timer(stmt="run2();", setup="from __main__ import run2") 
    print('bad', t.timeit(3)) 
    sys.exit(0) 

aber Ergebnis ist:

good 5.006664161000117 
bad 29.077525214999696 

so gibt es alle Arten lesen, schreiben von GEVENT beschleunigen könnte?

PS: Ich betreibe es auf dem Mac/python3/Anfragen 2.10.0/GEVENT 1.1.2

+0

Ich bin nicht vertraut mit 'gevent', aber ich könnte mir vorstellen, dass es wegen I/O ist. Wenn Sie eine Webanfrage stellen, müssen Sie eine Verbindung mit dem Server aufbauen, den Handshake machen, usw. Vieles davon endet im Leerlauf, währenddessen der Client auf eine Antwort wartet. Während es im Leerlauf ist, sendet 'gevent' höchstwahrscheinlich andere Anfragen. Die Python-only-Implementierung wartet jedoch darauf, dass jede Anforderung abgeschlossen wird, bevor eine andere gesendet wird. –

+0

das macht Sinn, so r'equests.get' nicht die ganze Zeit blockieren, ein Teil seiner Arbeit sind durch gevent ersetzen, die etwas anderes tun können, wenn blockieren. der Punkt ist, wie viel 'gevent' kann' Anfragen' ändern, zum Beispiel kann er fast alle 'urllib' ändern.so das ist viel schneller als Anfragen. –

Antwort

-1

Von der gevent website:

Schnelle Ereignisschleife auf libev (epoll auf Linux basiert, kqueue auf FreeBSD).

Leichte Ausführungseinheiten auf Basis von Greenlet.

API, die Konzepte aus der Python-Standardbibliothek wiederverwendet (zum Beispiel gibt es gevent.event.Events und gevent.queue.Queues).

Cooperative Steckdosen mit SSL-Unterstützung

DNS-Abfragen durch Thread oder c-ares durchgeführt.

Affen Dienstprogramm Patchen 3rd-Party-Module erhalten kooperativ zu werden

Grundsätzlich nur for ein Bündel von requests.get() Anrufen Looping langsam ist aufgrund der Tatsache, dass du bist, na ja, for durch ein Bündel von looping requests.get() Anrufe. Gevent'ing eine Reihe von requests.get() Anrufe ist nicht langsam aufgrund der Tatsache, dass Sie diese Anrufe in eine Thread-Queue statt, die dann nutzt gevents mächtige API, um diese Anrufe unglaublich effizient durchlaufen.

+1

de, ich weiß, was du meinst, aber du bringst diese Anrufe stattdessen in eine Thread-Queue, die nichts ändert, wenn der Job blockiert ist, einmal einen Job macht und der Job "sleep to wait" ist !! ! niemand bewegt sich, bis seine Arbeit erledigt ist. –

+0

In Ihrem Beispiel wirkt sich die Blockierung eigentlich nicht auf irgendetwas aus. Sie sind nur 'requests.get()' ing. Ja wirklich. Der Thread 'Queue' feuert so viele Jobs ab, wie gevent/Ihr Prozessor es zulässt. Nun, wenn Sie eine Variable ändern würden (sagen wir, ein String-Wert basierend auf der Seite Text), würde die Blockierung definitiv dort wegen der GIL ins Spiel kommen. – crashfocus