Co blokuje Ruby, Python, aby uzyskać prędkość Javascript V8? [Zamknięte]


261

Czy są jakieś funkcje Ruby / Python, które blokują implementację optymalizacji (np. Buforowanie wbudowane ) ma silnik V8?

Python jest opracowywany wspólnie przez facetów Google, więc nie powinien być blokowany przez patenty na oprogramowanie.

Lub jest to raczej kwestia zasobów umieszczonych w projekcie V8 przez Google.


6
Introspekcja i przeciążenie operatora są prawdopodobnie duże, ale nie znam JS wystarczająco dobrze, aby dać prawdziwą odpowiedź. Projekt PyPy jest prawdopodobnie najlepszą szansą Pythona na osiągnięcie prędkości JS.
ncoghlan,

11
Czy masz jakieś przykłady, w których PyPy jest wolniejszy niż V8, z wyjątkiem strzelanin w języku komputerowym, które są kompletnymi pierdołami (wystarczy spojrzeć, jak inaczej rzeczy są zaimplementowane w różnych językach). A może to tylko pole zniekształceń rzeczywistości Google?
fijal

3
V8 nie jest w pełni porównywalny z Pythonem. Poczekaj, aż V8 będzie musiało wdrożyć specyfikację 1.8 JavaScript, aby dokonać lepszego porównania. W tym momencie jestem pewien, że ktoś spróbuje wdrożyć PyPy na silniku V8 zamiast Javascript.
Michael Dillon

14
Dlaczego jesteś pewien, że V8 jest szybszy niż Python lub Ruby? W czym?
jcoffland 5.12

6
V8 jest absolutnie szybszy niż Python / Ruby. Wykonaj dowolny test porównawczy, od prostego mikrobenchmarku do kompleksowej aplikacji w świecie rzeczywistym napisanej idiomatycznie w obu środowiskach. Jest to rząd wielkości szybszy dla większości operacji natywnych dla języka (tj. Rzeczy, które nie są delegowane do kodu C w Pythonie).
Hejazzman

Odpowiedzi:


519

Co blokuje Ruby, Python, aby uzyskać prędkość Javascript V8?

Nic.

No dobra: pieniądze. (I czas, ludzie, zasoby, ale jeśli masz pieniądze, możesz je kupić.)

V8 ma zespół genialnych, wysoko wyspecjalizowanych, doświadczonych (a więc i dobrze płatnych) inżynierów pracujących nad nim, którzy mają dziesięciolecia doświadczenia (mówię indywidualnie - razem to wieki) w tworzeniu wysokowydajnego wykonania silniki dla dynamicznych języków OO. Są to w zasadzie te same osoby, które również stworzyły Sun HotSpot JVM (między innymi).

Lars Bak, główny programista, dosłownie pracuje nad maszynami wirtualnymi od 25 lat (i wszystkie te maszyny mają wersję V8), która jest zasadniczo jego całym (zawodowym) życiem. Niektóre osoby piszące Ruby VM nie mają nawet 25 lat.

Czy są jakieś funkcje Ruby / Python, które blokują implementację optymalizacji (np. Buforowanie wbudowane) ma silnik V8?

Biorąc pod uwagę, że przynajmniej IronRuby, JRuby, MagLev, MacRuby i Rubinius mają buforowanie monomorficzne (IronRuby) lub polimorficzne wbudowane, odpowiedź jest oczywiście przecząca.

Nowoczesne implementacje Ruby już dokonują wielu optymalizacji. Na przykład dla niektórych operacji Hashklasa Rubiniusa jest szybsza niż klasa YARV. Teraz nie brzmi to zbyt ekscytująco, dopóki nie uświadomisz sobie, że Hashklasa Rubiniusa jest zaimplementowana w 100% czystym Ruby, podczas gdy YARV jest zaimplementowane w 100% zoptymalizowanej ręcznie C.

Tak więc przynajmniej w niektórych przypadkach Rubinius może wygenerować lepszy kod niż GCC!

Lub jest to raczej kwestia zasobów umieszczonych w projekcie V8 przez Google.

Tak. Nie tylko Google. Linia kodu źródłowego V8 ma już 25 lat. Ludzie, którzy pracują nad V8, również stworzyli Self VM (do dziś jeden z najszybszych dynamicznych mechanizmów wykonywania języka OO, jaki kiedykolwiek stworzono), Animorphic Smalltalk VM (do dziś jeden z najszybszych silników wykonywania Smalltalk, jaki kiedykolwiek stworzono), HotSpot JVM (najszybszy JVM, jaki kiedykolwiek stworzono, prawdopodobnie najszybszy okres VM) i OOVM (jedna z najbardziej wydajnych maszyn wirtualnych Smalltalk, jakie kiedykolwiek stworzono).

W rzeczywistości Lars Bak, główny programista V8, pracował nad każdym z nich oraz kilkoma innymi.


1
Czy możemy znaleźć literaturę na temat „Biorąc pod uwagę, że przynajmniej IronRuby, JRuby, MagLev, MacRuby i Rubinius mają buforowanie monomorficzne (IronRuby) lub polimorficzne wbudowane, odpowiedź jest oczywiście nie”. Proszę?
WDRust,

14
SpiderMonkey ma porównywalną wydajność, więc jak to wtedy zrobiła Mozilla? Mają bardzo ograniczone pieniądze ..
Salman von Abbas

8
@SalmanPK: to nie jest ich pierwsza maszyna wirtualna, a w Mozilli pracują też inteligentni ludzie.
Matthieu M.

3
@SalmanPK, miguel: Mozilla przynajmniej częściowo utworzyła maszynę wirtualną JS za pomocą inżynierii wstecznej V8. blog.mozilla.org/dmandelin/2010/09/08/presenting-jagermonkey
Ian

2
@Ian V8 jest oprogramowaniem typu open source (licencja BSD), więc nie trzeba dokonywać inżynierii wstecznej, wystarczy spojrzeć na to, co robią.
dbkk

78

Jest o wiele większy impuls do wysoce zoptymalizowanych interpretatorów JavaScript, dlatego widzimy, jak wiele zasobów jest w nich umieszczanych między Mozillą, Google i Microsoft. JavaScript musi być pobierany, analizowany, kompilowany i uruchamiany w czasie rzeczywistym, podczas gdy (zwykle niecierpliwa) istota ludzka czeka na niego, musi być uruchomiona PODCZAS interakcji z nim i robi to w niekontrolowany sposób po stronie klienta środowisko, które może być komputerem, telefonem lub tosterem. MUSI być wydajny, aby skutecznie działać w tych warunkach.

Python i Ruby są uruchamiane w środowisku kontrolowanym przez programistę / wdrażającego. Potężny serwer lub komputer stacjonarny, gdzie czynnikiem ograniczającym będą takie rzeczy, jak pamięć lub dyskowe operacje we / wy, a nie czas wykonania. Lub tam, gdzie można zastosować optymalizacje inne niż silnik, takie jak buforowanie. W przypadku tych języków prawdopodobnie bardziej sensowne jest skupienie się na zestawie funkcji językowych i bibliotecznych zamiast na optymalizacji prędkości.

Zaletą tego jest to, że mamy dwa świetne, wysoce wydajne silniki JavaScript typu open source, które mogą i są ponownie przeznaczone do wszelkiego rodzaju aplikacji, takich jak Node.js.


43

Znaczna część ma to związek ze społecznością. W większości Python i Ruby nie mają wsparcia korporacyjnego. Nikt nie otrzymuje wynagrodzenia za pracę w Pythonie i Ruby w pełnym wymiarze godzin (a zwłaszcza nie dostaje się zapłaty za pracę w CPython lub MRI przez cały czas). Z drugiej strony V8 jest wspierana przez najpotężniejszą firmę informatyczną na świecie.

Co więcej, V8 może być szybszy, ponieważ jedyną rzeczą, która jest ważna dla ludzi V8, jest tłumacz - nie mają oni standardowej biblioteki do pracy, nie mają obaw o projektowanie języka. Po prostu piszą tłumacza. Otóż ​​to.

Nie ma to nic wspólnego z prawem własności intelektualnej. Python nie jest również współtworzony przez facetów Google (jego twórca działa tam wraz z kilkoma innymi osobami odpowiedzialnymi, ale nie zarabiają na pracy w Pythonie).

Kolejną przeszkodą dla szybkości Pythona jest Python 3. Jego przyjęcie wydaje się być główną troską twórców języków - do tego stopnia, że ​​wstrzymali rozwój nowych funkcji języka, dopóki inne implementacje nie nadrobią zaległości.

Jeśli chodzi o szczegóły techniczne, niewiele wiem o Ruby, ale Python ma wiele miejsc, w których można zastosować optymalizacje (a Unladen Swallow, projekt Google, zaczął je wdrażać przed odgryzaniem pyłu). Oto niektóre z zaplanowanych optymalizacji . Widziałem, że Python zyskuje prędkość V8 w przyszłości, jeśli JIT a la PyPy zostanie wdrożony dla CPython, ale nie wydaje się to prawdopodobne w nadchodzących latach (obecnie skupia się na adopcji Python 3, a nie JIT).

Wielu uważa również, że Ruby i Python mogą ogromnie skorzystać na usunięciu odpowiednich globalnych blokad interpretera .

Musisz także zrozumieć, że zarówno Python, jak i Ruby są znacznie cięższymi językami niż JS - zapewniają znacznie więcej w zakresie standardowej biblioteki, funkcji językowych i struktury. Sam klasowy system orientacji obiektowej dodaje ogromnej wagi (myślę, że w dobrym sensie). Prawie myślę o Javascript jako języku zaprojektowanym do osadzania, takim jak Lua (i pod wieloma względami są one podobne). Ruby i Python mają znacznie bogatszy zestaw funkcji, a ekspresja zwykle odbywa się kosztem szybkości.


3
W rzeczywistości moratorium na nowe funkcje zostało zniesione od ostatniej wersji Python 3.2.
jd.

2
+1, ale czy zamrożenie nowych funkcji językowych nie oznaczałoby więcej czasu na optymalizację?
Andrew Grimm,

1
@Andrew, jeśli tylko. Nacisk kładziony jest na przyspieszenie działania Jython, IronPython i PyPy, czekając na konwersję bibliotek do Python 3 i ewangelizując Python 3.
Rafe Kettler

2
„Sam system klas orientacji obiektowej dodaje ogromnej wagi” - Nowoczesne maszyny wirtualne JavaScript, takie jak V8, mają klasy, są po prostu niejawne. Podobnie jak w Pythonie nie musisz jawnie wpisywać zmiennej w JavaScript, nie musisz jawnie wpisywać klasy. Maszyna wirtualna jest wystarczająco sprytna, aby przejść przez kod i wyodrębnić klasy.
Benjamin Gruenbaum

1
Jak rozumiem, V8 to kompilator JIT, a nie interpreter ... Jestem prawie pewien, że istnieje różnica między tymi dwoma. Może nie ... Nie wiem.
Luke

24

Wydajność nie wydaje się być głównym przedmiotem zainteresowania głównych programistów Python, którzy uważają, że „wystarczająco szybki” jest wystarczająco dobry, a funkcje, które pomagają programistom w zwiększeniu produktywności, są ważniejsze niż funkcje, które pomagają komputerom szybciej uruchamiać kod.

Rzeczywiście jednak istniał (obecnie porzucony) projekt Google, bez obciążenia , aby stworzyć szybszy interpreter języka Python zgodny ze standardowym. PyPy to kolejny projekt, który ma na celu stworzenie szybszego Pythona. Istnieje również Psyco , prekursor PyPy, który może zwiększyć wydajność wielu skryptów Pythona bez zmiany całego interpretera, oraz Cython , który pozwala pisać wysokowydajne biblioteki C dla Pythona przy użyciu czegoś bardzo podobnego do składni Pythona.


13

Mylące pytanie. V8 to implementacja JavaScript w JIT (kompilator just in time), aw swojej najpopularniejszej implementacji Node.js innej niż przeglądarka jest zbudowana wokół pętli zdarzeń. CPython nie jest JIT i nie został wydany. Ale istnieją one w Pythonie najczęściej w projekcie PyPy - JIT kompatybilny z CPython 2.7 (a wkrótce będzie 3.0+). I jest mnóstwo zdarzonych bibliotek serwerów, takich jak na przykład Tornado. Istnieją testy w prawdziwym świecie między PyPy z uruchomionym Tornado a Node.js, a różnice w wydajności są niewielkie.


3
+1 za wzmiankę o Tornado . Choć działa z prędkością porównywalną do Node.js, jego gen.enginemoduł wraz z generatorami Pythona i yieldinstrukcją ( od wersji 2.5 !!! może przedefiniować kodowanie asynchroniczne.
Lukas Bünger,

1
Od czasu twojego postu pypy wydało stabilną, obsługiwaną wersję 3.x (i oczywiście poprawia wsparcie): morepypy.blogspot.fr/2014/06/pypy3-231-fulcrum.html
Zeograd

9

Właśnie natknąłem się na to pytanie i jest też duży techniczny powód, dla którego różnica w wydajności nie została wspomniana. Python ma bardzo duży ekosystem potężnych rozszerzeń oprogramowania, ale większość z nich jest napisana w C lub innych językach niskiego poziomu w celu zwiększenia wydajności i jest silnie związana z API CPython.

Istnieje wiele dobrze znanych technik (JIT, nowoczesny śmieciarz itp.), Których można by użyć do przyspieszenia implementacji CPython, ale wszystkie wymagałyby znacznych zmian w interfejsie API, niszcząc większość rozszerzeń w tym procesie. CPython byłby szybszy, ale wiele z tego, co czyni Python tak atrakcyjnym (duży stos oprogramowania), zostałoby utraconych. Przykładowo, istnieje kilka szybszych implementacji Pythona, ale mają one małą przyczepność w porównaniu do CPython.


9

Uważam, że z powodu różnych priorytetów projektowych i celów zastosowania.

Zasadniczo głównym celem skryptów (czyli dynamicznych) języków jest „klejenie” między wywołaniami funkcji natywnych. Te natywne funkcje powinny a) obejmować najbardziej krytyczne / często używane obszary i b) być tak skuteczne, jak to możliwe.

Oto przykład: sortowanie jQuery powodujące zawieszanie się iOS Safari Zamrożenie spowodowane jest nadmiernym użyciem wywołań get-by-selector. Jeśli get-by-selektor zostanie zaimplementowany w kodzie natywnym i faktycznie nie będzie takiego problemu.

Rozważ demo ray-tracer, które jest często używane do demonstracji V8. W świecie Python można go zaimplementować w kodzie natywnym, ponieważ Python zapewnia wszystkie udogodnienia dla rozszerzeń natywnych. Ale w dziedzinie V8 (piaskownica po stronie klienta) nie ma innych opcji, niż uczynić maszynę wirtualną tak skuteczną, jak to możliwe. Tak więc jedyną opcją jest implementacja ray-tracera za pomocą kodu skryptu.

Różne priorytety i motywacje.

W Sciter przeprowadziłem test, implementując natywnie prawie pełny rdzeń jQurey. W przypadku praktycznych zadań, takich jak ScIDE (IDE wykonane z HTML / CSS / Script) uważam, że takie rozwiązanie działa znacznie lepiej niż wszelkie optymalizacje maszyn wirtualnych.


5

Jak wspomnieli inni, Python ma wydajny kompilator JIT w postaci PyPy .

Wykonywanie znaczących testów porównawczych jest zawsze subtelne, ale zdarza się, że mam prosty test porównawczy K-średnich napisany w różnych językach - możesz go znaleźć tutaj . Jednym z ograniczeń było to, że wszystkie języki powinny implementować ten sam algorytm i starać się być proste i idiomatyczne (w przeciwieństwie do zoptymalizowanych pod kątem szybkości). Napisałem wszystkie implementacje, więc wiem, że nie oszukiwałem, chociaż nie mogę twierdzić dla wszystkich języków, że to, co napisałem, jest idiomatyczne (mam tylko pewną znajomość niektórych z nich).

Nie twierdzę, że jakikolwiek ostateczny wniosek, ale PyPy był jedną z najszybszych implementacji, jakie dostałem, znacznie lepszą niż Node. Zamiast tego CPython był na najwolniejszym końcu rankingu.


5

To stwierdzenie nie jest do końca prawdziwe

Podobnie jak V8 jest tylko implementacją dla JS, CPython jest tylko jedną implementacją dla Pythona. Pypy ma występy pasujące do V8 .

Istnieje również problem postrzeganej wydajności: ponieważ V8 natywnie nie blokuje, programista Web prowadzi do bardziej wydajnych projektów, ponieważ oszczędzasz czas oczekiwania na IO. Wersja V8 jest wykorzystywana głównie do tworzenia stron internetowych, w których kluczem jest IO, więc porównują ją do podobnych projektów. Ale możesz używać Pythona w wielu innych obszarach niż web dev. I możesz nawet używać rozszerzeń C do wielu zadań, takich jak obliczenia naukowe lub szyfrowanie, i przebijać dane za pomocą niesamowitych perfów.

Ale w Internecie najpopularniejsze projekty Python i Ruby blokują. Zwłaszcza Python ma spuściznę synchronicznego standardu WSGI i oparte są na nim platformy takie jak słynny Django.

Możesz pisać asynchronicznie w Pythonie (jak w Twisted, Tornado, gevent lub asyncio) lub Ruby. Ale nie jest to często wykonywane. Najlepsze narzędzia wciąż blokują.

Są jednak niektóre powody, dla których domyślne implementacje w Ruby i Pythonie nie są tak szybkie jak V8.

Doświadczenie

Jak zauważył Jörg W Mittag, ludzie pracujący na V8 to geniusze VM. Python jest przez wielu pasjonatem, bardzo dobrym w wielu domenach, ale nie specjalizuje się w tuningu VM.

Zasoby

Fundacja Python Software ma bardzo mało pieniędzy: mniej niż 40 tys. Rocznie na inwestycje w Python. To trochę szalone, gdy myślisz, że duzi gracze, tacy jak Google, Facebook czy Apple, używają Pythona, ale to brzydka prawda: większość pracy odbywa się za darmo. Język, który napędza YouTube i istniał zanim Java została ręcznie opracowana przez wolontariuszy.

Są sprytnymi i oddanymi wolontariuszami, ale kiedy stwierdzą, że potrzebują więcej soku na polu, nie mogą poprosić o 300 tys. Pracowników do zatrudnienia najwyższej klasy specjalisty w tej dziedzinie. Muszą rozejrzeć się za kimś, kto zrobiłby to za darmo.

Chociaż to działa, oznacza to, że musisz bardzo uważać na swoje priorytety. Dlatego teraz musimy spojrzeć na:

Cele

Nawet z najnowszymi nowoczesnymi funkcjami pisanie Javascript jest okropne. Masz problemy z określaniem zakresu, bardzo mało kolekcji, straszne manipulacje ciągami i tablicami, prawie brak standardowej listy oprócz daty, matematyki i wyrażeń regularnych oraz brak cukru syntaktycznego nawet w przypadku bardzo częstych operacji.

Ale w V8 masz szybkość.

Dzieje się tak, ponieważ szybkość była głównym celem Google, ponieważ jest wąskim gardłem w renderowaniu stron w Chrome.

W Pythonie użyteczność jest głównym celem. Ponieważ prawie nigdy nie stanowi to wąskiego gardła w projekcie. Skąpym zasobem tutaj jest czas programisty. Jest zoptymalizowany dla programisty.


1

Ponieważ implementacje JavaScript nie muszą dbać o kompatybilność wsteczną swoich powiązań.

Do niedawna jedynymi użytkownikami implementacji JavaScript były przeglądarki internetowe. Ze względu na wymagania bezpieczeństwa tylko dostawcy przeglądarek internetowych mieli przywilej rozszerzenia funkcjonalności poprzez pisanie powiązań do środowisk wykonawczych. W związku z tym nie było potrzeby utrzymywania kompatybilności wstecznej interfejsu API C, dozwolone było żądanie od twórców przeglądarek internetowych aktualizacji kodu źródłowego w miarę ewolucji środowisk wykonawczych JavaScript; i tak pracowali razem. Nawet V8, która była późną grą, a także prowadzona przez bardzo doświadczonego programistę, zmieniła API, gdy stało się lepsze.

OTOH Ruby jest używany (głównie) po stronie serwera. Wiele popularnych rozszerzeń ruby ​​jest zapisywanych jako powiązania C (rozważ sterownik RDBMS). Innymi słowy, Ruby nigdy by się nie udało bez zachowania zgodności.

Dziś różnica nadal istnieje do pewnego stopnia. Deweloperzy używający node.js narzekają, że trudno jest zachować kompatybilność wsteczną swoich rozszerzeń natywnych, ponieważ V8 zmienia API w miarę upływu czasu (i jest to jeden z powodów, dla których node.js został rozwidlony). Rubin IIRC nadal pod tym względem przyjmuje znacznie bardziej konserwatywne podejście.


1

V8 jest szybki ze względu na JIT, wał korbowy, typ wnioskowania i kod zoptymalizowany pod kątem danych. Oznaczone wskaźniki, znakowanie podwójnych NaN. I oczywiście wykonuje normalne optymalizacje kompilatora w środku.

Zwykłe silniki ruby, python i perl nie wykonują żadnego z nich, a jedynie drobne podstawowe optymalizacje.

Jedynym głównym vm, który się zbliża, jest luajit, który nie robi nawet wnioskowania typu, ciągłego składania, znakowania NaN ani liczb całkowitych, ale używa podobnych małych struktur kodu i danych, nie tak grubych jak złe języki. A moje prototypowe języki dynamiczne, mikstura i p2 mają podobne funkcje jak luajit i przewyższają v8. Dzięki opcjonalnemu systemowi pisania, „stopniowemu pisaniu”, możesz łatwo przewyższyć v8, ponieważ możesz ominąć wał korbowy. Zobacz rzutkę.

Znane zoptymalizowane backendy, takie jak pypy lub jruby, wciąż cierpią z powodu różnych technik nadmiernej inżynierii.


Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.