Dlaczego Python jest wolniejszy niż Java, ale szybszy niż PHP [zamknięty]

17

Wielokrotnie widziałem różne testy porównawcze, które pokazują, jak wiele języków radzi sobie z danym zadaniem.

Te testy porównawcze zawsze ujawniają, że Python jest wolniejszy niż Java i szybszy niż PHP i zastanawiam się, dlaczego tak jest.

  • Java, Python i PHP działają w maszynie wirtualnej
  • Wszystkie trzy języki konwertują swoje programy na niestandardowe kody bajtów działające na systemie operacyjnym - więc żaden z nich nie działa natywnie
  • Zarówno Java, jak i Python można „skompilować” ( .pycdla Pythona), ale __main__moduł dla Pythona nie jest skompilowany

Python i PHP są wpisywane dynamicznie, a Java statycznie - czy to jest powód, dla którego Java jest szybsza, a jeśli tak, proszę wyjaśnić, jak to wpływa na szybkość.

I nawet jeśli argument dynamiczny kontra statyczny jest poprawny, nie wyjaśnia to, dlaczego PHP jest wolniejszy niż Python - ponieważ oba są dynamicznymi językami.

Możesz zobaczyć niektóre testy tutaj i tutaj , i tutaj

treecoder
źródło
Jeśli chodzi o Python vs. PHP: najprawdopodobniej jest to tylko kwestia jakości implementacji.
Charles Salvia
8
@good_computer Większość testów porównawczych jest bardzo źle wykonana. Był jeszcze jeden ostatni (nie sądzę, byś go powiązał), że większość osób, które go przeglądały, skarżyło się, że język, który uważał za „najszybszy”, miał po prostu najlepiej zoptymalizowany kod. Zwykle robi to nieświadomie ktoś, kto nie jest tak obeznany z językami, które w końcu są uważane za „powolne”, więc nie zdają sobie sprawy, że piszą lepszy kod w tych, które okazały się „szybkie”.
Izkata
@good_computer Wydaje mi się, że coś twierdzisz, ponieważ twoje pytanie zawiera tekst „ Zawsze te testy porównawcze pokazują, że Python jest wolniejszy niż Java i szybszy niż PHP ” oraz „ PHP jest wolniejszy niż Python ”. Usunięcie tych cytatów i przeformułowanie pytania, aby było niezależne od języka, może go ponownie otworzyć.
śluby
To pytanie jest naprawdę stronnicze : (1) odnoszące się do nieautorytatywnych testów porównawczych przeprowadzonych na bardzo naiwnie niezoptymalizowanym kodzie napisanym przez początkujących programistów w językach, których nie opanowali (jak opisano w odpowiednich wątkach komentarzy) i (2) zbudowanych na błędnych przekonaniach o językach interpretowanych / kodu bajtowego ( interpretuje się php / python, bajtowe kodowanie java, pliki pamięci podręcznej python są abstrakcyjnymi drzewami składniowymi, a nie kodem bajtowym) oraz stanem trzech języków (istnieją skompilowane wersje zarówno Pythona, jak i php - python jest bardziej dojrzały, skompilowany php działa jednak na Facebooku)
ZJR

Odpowiedzi:

26

Kod JVM może być efektywnie skompilowany w JIT przy użyciu trywialnego (i szybkiego) kompilatora ad hoc. Ale to samo byłoby wyjątkowo trudne dla PHP i Pythona, ze względu na ich dynamicznie wpisywaną naturę. JVM tłumaczy na dość niski poziom i prosty kod natywny, całkiem podobny do tego, co produkowałby kompilator C ++, ale dla języków dynamicznych trzeba by było generować dynamiczne wysyłanie dla dosłownie wszystkich podstawowych operacji i wszystkich wywołań metod. Ta dynamiczna wysyłka jest głównym wąskim gardłem we wszystkich językach tego rodzaju.

W niektórych przypadkach możliwe jest wyeliminowanie dynamicznej wysyłki (jak również wirtualnych wywołań w Javie) przy użyciu znacznie bardziej skomplikowanego kompilatora śledzenia JIT. To podejście jest jeszcze w powijakach, nie robi zbyt wiele abstrakcyjnej interpretacji, a taki kompilator prawdopodobnie dusi się podczas evalpołączeń (które są bardzo typowe dla języków dynamicznych).

Jeśli chodzi o różnicę między Pythonem a PHP, ta ostatnia ma tylko znacznie niższą jakość. Teoretycznie może działać szybciej, ale nigdy nie będzie.

Logika SK
źródło
1
Dlaczego JIT jest „wyjątkowo” trudny dla języków dynamicznych? Spójrz na v8 lub TraceMonkey w świecie JavaScript - tam JIT działa dobrze.
treekoder
6
@good_computer, śledzenie JIT jest znacznie bardziej złożone niż normalne JIT ad hoc i nadal działają znacznie wolniej niż JIT dla języków o typie statycznym. Prawidłowe śledzenie JIT wymagałoby pełnej interpretacji abstrakcyjnej i dusiłoby się przy każdym evalwywołaniu.
SK-logic
2
Prawdopodobnie w zespole kompilatorów Oracle HotSpot jest około stu inżynierów, którzy nie zgadzają się co do „trywialnej” części :-)
Jörg W Mittag
1
@ JörgWMittag, oczywiście, HotSpot nie jest tak prosty, robi trochę analizy statycznej, wykorzystuje wyniki profilowania środowiska wykonawczego, ale nadal jest o wiele prostszy niż prawidłowe śledzenie JIT. I, powiedziałbym, HotSpot jest nadmiernie skomplikowany, a jego implementacja jest, mówiąc grzecznie, trochę zbyt gadatliwa.
SK-logic
1
@Frank Shearar, ad hoc JIT dla języka dynamicznego jest tak samo trywialny jak dla języka o typie statycznym (patrz na przykład LuaJIT). OTOH, wydajny JIT to zupełnie inna sprawa.
SK-logic
21

Istnieje ogólny problem z tym pytaniem, ponieważ jest ono zbyt absolutne. Nie ma sensu mówić, że „język X jest szybszy niż język Y”. Sam język komputera nie jest „szybki” ani „wolny”, ponieważ jest jedynie sposobem wyrażenia algorytmu. Rzeczywiste pytanie powinno brzmieć w kolejności „dlaczego implementacja X1 języka X jest szybsza niż implementacja Y1 języka Y dla tej konkretnej dziedziny problemowej?”

Niektóre różnice prędkości z pewnością wypadną z samego języka, ponieważ niektóre języki są łatwiejsze do wdrożenia w niektórych domenach niż inne. Ale większość tego, co sprawia, że ​​wdrożenie jest szybkie, nie jest językiem. Na przykład tak naprawdę nie można powiedzieć „Python jest wolniejszy niż Java” bez zastanowienia się, czy mówimy o CPython, IronPython czy PyPy. Jest to szczególnie prawdziwe w przypadku języków korzystających z maszyny wirtualnej, ponieważ na jej szybkość bezpośrednio wpłynie jakość maszyny wirtualnej.

Nawiasem mówiąc, pracuję z systemem, który z różnych powodów nie może używać JIT na naszym urządzeniu z bardzo popularną maszyną wirtualną JavaScript, która normalnie go obsługuje. Oznacza to, że nasz JavaScript działa znacznie, znacznie wolniej niż na komputerze PC z podobnym procesorem. Ta jedna zmiana, która nie jest bezpośrednio związana z samym językiem, powoduje, że JavaScript staje się „kilka razy wolniejszy niż C ++” do bycia „rzędami wielkości wolniejszymi niż C ++” w przypadku zadań, na których nam zależy.

Należy również wziąć pod uwagę fakt, że języki różnią się cechami wydajności w sposób, który nie jest bezpośrednio porównywalny. Zbyt wiele testów porównawczych po prostu tłumaczy program z języka A ​​na język B i nie bierze pod uwagę, że języki różnią się tym, które funkcje są szybkie. (Możesz to zobaczyć w każdym rozsądnym porównaniu porównawczym, takim jak te, do których prowadzisz link, ponieważ często zawierają notatki typu „dzięki tak-a-tak za pokazanie mi, jak zaimplementować to w języku Foo.)

Na przykład weź ten kod Java:

for(int i=0;i<10;i++) {
    Object o = new Object;
    doSomething(o);
}

Kuszące byłoby „przepisanie” tego w C ++ i porównanie czasów wykonywania:

for(int i=0;i<10;i++) {
    Object *o = new Object;
    doSomething(o);
    delete(o);
}

Chodzi o to, że każdy kompetentny programista C ++ od razu zobaczy, że w C ++ nie jest to najszybszy sposób na zrobienie czegoś. Możesz łatwo przyspieszyć, zmieniając go, aby był bardziej odpowiedni dla C ++:

for(int i=0;i<10;i++) {
    Object o;
    doSomething(&o);
}

Nie chodzi o to, że C ++ może być szybki, ale pisanie testów porównawczych w językach jest naprawdę bardzo trudne. Aby zrobić to odpowiednio, musisz być ekspertem w obu językach i pisać od zera w obu językach. Nawet wtedy możesz łatwo natknąć się na obszary, w których jeden język wyróżnia się w określonym zadaniu. Na przykład mogę napisać wersję Towers of Hanoi w C ++, która będzie działać szybciej niż Java na dowolnym rozsądnym kompilatorze. Mogę to zrobić, zasadniczo oszukując, używając szablonów C ++, ocenianych w czasie kompilacji (http://forums.devshed.com/c-programming-42/c-towers-of-hanoi-using-templates-424148.html)

Nie chodzi o to, że mógłbym powiedzieć, że „C ++ jest szybszy niż Java”, ponieważ mój program powrócił natychmiast, podczas gdy wersja Java działała przez kilka minut (i mam nadzieję, że nikt nie zauważył, że budowa mojego programu zajęła pół godziny.) Chodzi o to, że różnią się wąskimi literami, C ++ jest szybszy. W innych wąskich przypadkach może być na odwrót. Nie jest to więc „C ++ jest szybszy”, to „C ++ jest szybszy w przypadkach, w których można ocenić wyrażenie w czasie kompilacji za pomocą szablonów”. Mniej satysfakcjonujące, ale prawdziwe.

Różnice prędkości w językach dotyczą głównie implementacji. Języki skompilowane będą szybsze niż języki interpretowane. Kompilacja do kodu natywnego będzie szybsza niż kompilacja do kodu bajtowego. Będzie to miało o wiele większy efekt niż pytania, czy język jest wpisywany statycznie, czy nie. I oczywiście dobre wdrożenia będą szybsze niż złe.

I nie zapominaj, że dobrzy programiści będą produkować szybszy kod niż źli programiści, często w stopniu znacznie przewyższającym różnice językowe.

Gort the Robot
źródło
6

Ma to związek z jakością kompilatora, kompilator Java jest ciągle optymalizowany o wiele dłużej, a optymalizacja jest ważniejsza, ponieważ cały kod jest kompilowany dla Javy. Nie jestem pewien dokładnego powodu, dla którego Python jest szybszy niż PHP, ale postawiłbym się na to z powodu wpływu Google na Python.

Ryathal
źródło
8
Dlaczego zostało to zanegowane? To jest dokładnie odpowiedź: wydajność jest wyłącznie kwestią badań i wysiłków inżynieryjnych, a tym samym ostatecznie pieniędzy. Firmy produkujące implementacje Java są po prostu bogatsze niż firmy produkujące implementacje Python lub PHP. To wszystko.
Jörg W Mittag
1
Co więcej, jestem prawie pewien, że optymalizacje CPython nie są akceptowane, jeśli powodują, że kod jest zbyt trudny do odczytania i tylko nieznacznie zwiększają wydajność.
cgt
2
+ Jörg W Mittag: Nie zgadzam się. Niektóre funkcje językowe mogą być bardzo trudne do zaimplementowania w sposób wydajny, dlatego też sprawiają, że tworzenie wydajnej implementacji jest bardzo trudne lub prawie niemożliwe. Z drugiej strony niezwykle łatwo jest stworzyć „wydajną” implementację języka „asemblera”.
user281377
@ammoQ Podejrzewam, że wiele z nich sprowadza się do systemów typów, a w szczególności do umiejętności dokładnego określenia, jaki masz typ i jaka jest dokładna semantyka dozwolonych operacji. Języki dynamiczne zyskują elastyczność ze względu na swoją naturę, ale utrudniają wykonanie proofów tekstowych (a tym samym kompilacji do bezpiecznego, hiperszybkiego kodu).
Donal Fellows
1
@DonalFellows Dokładnie moja myśl. Im mniej wiadomo w czasie kompilacji, tym więcej trzeba dowiedzieć się podczas uruchamiania.
user281377
4

Dlaczego Java jest najszybsza:

Statycznie wpisana flaga + Kompilacja JIT + --server do agresywnej rekompilacji działającego kodu.

Dlaczego Python jest szybszy niż PHP:

Python może być językiem dynamicznym, ale nadal jest mocno napisany. Oznacza to, że struktury, które kodujesz, są w stanie zoptymalizować środowisko wykonawcze.

Dlaczego PHP jest do bani:

Jest to w zasadzie javascript na serwerze (brak obsługi wielowątkowości, całkowicie dynamiczny, luźno wpisany).

Zasadniczo, im więcej kompilator wie o twoim kodzie, tym bardziej może go zoptymalizować. Java jest w pełni optymalizowana przed uruchomieniem i podczas działania. Python można optymalizować podczas działania, a PHP jest, no cóż, okropny. Facebook faktycznie przenosi ich PHP do C, zanim trafi na serwer.
https://developers.facebook.com/blog/post/2010/02/02/hiphop-for-php--move-fast/

Ajax
źródło
W rzeczywistości javascript na serwerze to Node.JS iz tego, co rozumiem (choć tego nie potwierdzę), silnik V8 ogólnie przewyższa PHP (choć prawdopodobnie nie o tonę). Co więcej, powinieneś wspomnieć, że Python można skompilować do natywnego (jak wtedy działa w porównaniu z Javą?)
Jimmy Hoffa
Nie użyłem wystarczająco dużo Pythona, aby ci pomóc, ale mogę powiedzieć, że nodejs z systemem V8 obsługuje natywne rozszerzenia C (chociaż przekraczanie granicy JS / C jest podobno powolne), a ponadto może korzystać z kompilatora JIT Google. .. Nie zdziwiłbym się, gdyby węzeł był szybszy niż Python i php. Oto punkt odniesienia (jak większość jest wadliwy) blog.famzah.net/2010/07/01/… Zauważ, że java wyglądała wolniej niż JS, dopóki komentator nie wskazał naszych wad w teście ... Więc weź to z odrobiną Sól. :)
Ajax,
To powiedziawszy, zarówno węzły, jak i php są również jednokierunkowe, a jeśli nie lubisz konfigurować serwerów proxy klastrowych (takich jak haproxy), nie dotknąłbym żadnego z nich w poważnym środowisku produkcyjnym.
Ajax,
1

Testy porównawcze są raczej wypaczone na korzyść ciężkiego programowania matematycznego.

Nic dziwnego, że Python jest całkiem dobry w złożonej matematyce, jeśli wziąć pod uwagę, gdzie i dlaczego został napisany po raz pierwszy .

Z drugiej strony PHP zostało napisane, by obsługiwać strony internetowe, może robić inne rzeczy, ale strony internetowe są najlepsze w tym zadaniu i lepsze niż Java.

James Anderson
źródło