Jestem nowy w gevents i greenlets. Znalazłem dobrą dokumentację, jak z nimi pracować, ale żadna nie podała mi uzasadnienia, jak i kiedy powinienem używać zielonych ulotek!
- W czym są naprawdę dobrzy?
- Czy warto używać ich na serwerze proxy, czy nie?
- Dlaczego nie wątki?
Nie jestem pewien, w jaki sposób mogą zapewnić nam współbieżność, jeśli są w zasadzie współprogramami.
threading.Thread
jest w rzeczywistości wątkiem systemu operacyjnego ze wszystkimi konsekwencjami. Więc to naprawdę nie jest takie proste. Nawiasem mówiąc, Jython nie ma GIL AFAIK, a PyPy również próbuje się go pozbyć.Odpowiedzi:
Greenlets zapewniają współbieżność, ale nie równoległość. Współbieżność występuje wtedy, gdy kod może działać niezależnie od innego kodu. Paralelizm to jednoczesne wykonywanie kodu współbieżnego. Równoległość jest szczególnie przydatna, gdy w przestrzeni użytkownika jest dużo pracy do wykonania, a jest to typowo obciążająca procesor. Współbieżność jest przydatna do rozdzielania problemów, umożliwiając równoległe planowanie i zarządzanie różnymi częściami.
Greenlets naprawdę błyszczą w programowaniu sieciowym, w którym interakcje z jednym gniazdem mogą zachodzić niezależnie od interakcji z innymi gniazdami. To jest klasyczny przykład współbieżności. Ponieważ każda zielona broszura działa w swoim własnym kontekście, możesz nadal używać synchronicznych interfejsów API bez tworzenia wątków. Jest to dobre, ponieważ wątki są bardzo drogie pod względem pamięci wirtualnej i narzutu jądra, więc współbieżność, którą można osiągnąć z wątkami, jest znacznie mniejsza. Ponadto wątki w Pythonie są droższe i bardziej ograniczone niż zwykle ze względu na GIL. Alternatywą dla współbieżności są zwykle projekty takie jak Twisted, libevent, libuv, node.js itp., W których cały kod ma ten sam kontekst wykonywania i rejestruje programy obsługi zdarzeń.
Doskonałym pomysłem jest używanie zielonych ulotek (z odpowiednim wsparciem sieciowym, takim jak gevent) do pisania proxy, ponieważ obsługa żądań może być wykonywana niezależnie i powinna być napisana jako taka.
Greenlety zapewniają współbieżność z powodów, które podałem wcześniej. Współbieżność nie jest równoległością. Ukrywając rejestrację zdarzeń i wykonując planowanie za Ciebie dla wywołań, które normalnie blokowałyby bieżący wątek, projekty takie jak gevent ujawniają tę współbieżność bez konieczności zmiany na asynchroniczny interfejs API i przy znacznie niższych kosztach dla systemu.
źródło
import hashlib def checksum_md5(filename): md5 = hashlib.md5() with open(filename,'rb') as f: for chunk in iter(lambda: f.read(8192), b''): md5.update(chunk) return md5.digest()
Biorąc odpowiedź @ Maxa i dodając do niej znaczenie przy skalowaniu, możesz zobaczyć różnicę. Osiągnąłem to, zmieniając adresy URL do wypełnienia w następujący sposób:
Musiałem zrezygnować z wersji wieloprocesowej, ponieważ spadła, zanim miałem 500; ale przy 10.000 iteracjach:
Możesz więc zobaczyć, że istnieje znacząca różnica we / wy przy użyciu gevent
źródło
Poprawiając powyższą odpowiedź @TemporalBeinga, greenlety nie są „szybsze” niż wątki i jest nieprawidłową techniką programowania, aby spawnować 60000 wątków w celu rozwiązania problemu współbieżności. Zamiast tego odpowiednia jest mała pula wątków. Oto bardziej rozsądne porównanie (z mojego posta reddit w odpowiedzi na osoby cytujące ten post SO).
Oto kilka wyników:
nieporozumieniem, jakie wszyscy mają na temat nieblokującego wejścia / wyjścia w Pythonie, jest przekonanie, że interpreter języka Python może zająć się pobieraniem wyników z gniazd na dużą skalę, szybciej niż same połączenia sieciowe mogą zwrócić IO. Chociaż jest to z pewnością prawdą w niektórych przypadkach, nie jest to prawdą prawie tak często, jak ludzie myślą, ponieważ interpreter Pythona jest naprawdę, bardzo powolny. W moim wpisie na blogu ilustruję kilka profili graficznych, które pokazują, że nawet w przypadku bardzo prostych rzeczy, jeśli masz do czynienia z wyraźnym i szybkim dostępem sieciowym do takich rzeczy, jak bazy danych lub serwery DNS, usługi te mogą wrócić o wiele szybciej niż kod Pythona może obsłużyć wiele tysięcy takich połączeń.
źródło
Jest to wystarczająco interesujące do przeanalizowania. Oto kod porównujący wydajność greenlets z pulą wieloprocesorową i wielowątkowością:
Oto wyniki:
Myślę, że Greenlet twierdzi, że nie jest związany GIL w przeciwieństwie do biblioteki wielowątkowej. Co więcej, doc Greenlet mówi, że jest przeznaczony do operacji sieciowych. W przypadku intensywnych operacji sieciowych przełączanie wątków jest dobre i widać, że podejście wielowątkowe jest dość szybkie. Ponadto zawsze lepiej jest używać oficjalnych bibliotek Pythona; Próbowałem zainstalować Greenlet w systemie Windows i napotkałem problem z zależnościami dll, więc przeprowadziłem ten test na maszynie wirtualnej z systemem Linux. Zawsze staraj się pisać kod z nadzieją, że będzie działał na dowolnej maszynie.
źródło
getsockbyname
buforuje wyniki na poziomie systemu operacyjnego (przynajmniej na moim komputerze tak robi). Po wywołaniu na wcześniej nieznanym lub wygasłym serwerze DNS, faktycznie wykona zapytanie sieciowe, co może zająć trochę czasu. Wywołane dla nazwy hosta, która niedawno została rozwiązana, zwróci odpowiedź znacznie szybciej. W rezultacie twoja metodologia pomiaru jest tutaj błędna. To wyjaśnia twoje dziwne wyniki - gevent nie może być tak naprawdę gorszy niż wielowątkowość - oba nie są tak naprawdę równoległe na poziomie VM.using_gevent() 421.442985535ms using_multiprocessing() 394.540071487ms using_multithreading() 402.48298645ms