Jakie cechy semantyczne Pythona (i innych dynamicznych języków) przyczyniają się do jego spowolnienia?
Żaden.
Wydajność implementacji językowych jest funkcją pieniędzy, zasobów i doktoratów, a nie cech językowych. Self jest znacznie bardziej dynamiczny niż Smalltalk i nieco bardziej dynamiczny niż Python, Ruby, ECMAScript lub Lua i miał maszynę wirtualną, która przewyższała wszystkie istniejące maszyny wirtualne Lisp i Smalltalk (w rzeczywistości dystrybucja Self dostarczana z małym interpreterem Smalltalk napisanym w języku Self , a nawet to było szybsze niż większość istniejących maszyn wirtualnych Smalltalk) i było konkurencyjne, a czasem nawet szybsze niż implementacje C ++ w tamtym czasie.
Następnie Sun przestał finansować Self, a IBM, Microsoft, Intel i Co. rozpoczęły finansowanie C ++, a trend się odwrócił. Auto-programiści opuścili Sun, aby założyć własną firmę, w której wykorzystali technologię opracowaną dla Self VM, aby zbudować jedną z najszybszych maszyn wirtualnych Smalltalk w historii (Animorphic VM), a następnie Sun odkupił tę firmę i nieco zmodyfikowaną wersję że Smalltalk VM jest teraz lepiej znany pod nazwą „HotSpot JVM”. Jak na ironię, programiści Java patrzą na dynamiczne języki za to, że są „powolni”, podczas gdy w rzeczywistości Javabyło powolne, dopóki nie przyjęła dynamicznej technologii językowej. (Tak, to prawda: HotSpot JVM jest zasadniczo maszyną wirtualną Smalltalk. Weryfikator kodu bajtowego sprawdza wiele typów, ale gdy kod bajtowy zostanie zaakceptowany przez weryfikator, maszyna wirtualna, a zwłaszcza optymalizator i JIT, tak naprawdę nie duże zainteresowanie typami statycznymi!)
CPython po prostu nie robi wielu rzeczy, które sprawiają, że dynamiczne języki (a raczej dynamiczna wysyłka) są szybkie: dynamiczna kompilacja (JIT), dynamiczna optymalizacja, inkluzje spekulacyjne, optymalizacja adaptacyjna, dynamiczna deoptymalizacja, dynamiczne sprzężenie zwrotne / wnioskowanie. Istnieje również problem polegający na tym, że prawie cała podstawowa i standardowa biblioteka jest napisana w C, co oznacza, że nawet jeśli nagle przyspieszysz Python 100x, to ci to nie pomoże, ponieważ około 95% kodu wykonywanego przez Program w języku Python to C, a nie Python. Gdyby wszystko napisano w Pythonie, nawet umiarkowane przyspieszenia wywołałyby efekt lawinowy, w którym algorytmy stają się szybsze, a podstawowe struktury danych stają się szybsze, ale oczywiście podstawowe struktury danych są również używane w algorytmach, a podstawowe algorytmy i podstawowe dane struktury są używane wszędzie indziej,
Jest kilka rzeczy, które są bardzo złe dla zarządzanych przez pamięć języków OO (dynamicznych lub nie) w dzisiejszych systemach. Pamięć wirtualna i ochrona pamięci mogą być zabójcze w szczególności dla wydajności czyszczenia pamięci, a ogólnie wydajności systemu. I jest to całkowicie niepotrzebne w języku bezpiecznym dla pamięci: po co chronić się przed nielegalnymi dostępami do pamięci, skoro na początku nie ma dostępu do pamięci w języku? Azul doszedł do wniosku, że wykorzystuje nowoczesne potężne MMU (Intel Nehalem i nowsze oraz odpowiednik AMD), aby pomóc w usuwaniu śmieci zamiast utrudniania go, ale mimo że jest on obsługiwany przez procesor, obecne podsystemy pamięci głównych systemów operacyjnych nie są wystarczająco mocne aby na to pozwolić (dlatego właśnie JVM Azul'a faktycznie działa zwirtualizowany poza samym metalem system operacyjny, nie w nim).
W projekcie Singularity OS Microsoft zmierzył wpływ ~ 30% na wydajność systemu przy użyciu ochrony MMU zamiast systemu typu do separacji procesów.
Inną rzeczą, którą Azul zauważył, budując swoje wyspecjalizowane procesory Java, było to, że współczesne procesory głównego nurtu koncentrują się na całkowicie niewłaściwej rzeczy, próbując zmniejszyć koszty braków pamięci podręcznej: próbują zmniejszyć liczbę braków pamięci podręcznej poprzez takie rzeczy, jak przewidywanie gałęzi, pobieranie pamięci, i tak dalej. Ale w mocno polimorficznym programie OO wzorce dostępu są w zasadzie pseudolosowe, po prostu nie ma nic do przewidzenia. Tak więc wszystkie te tranzystory są po prostu zmarnowane, a tym, co należy zrobić, jest zmniejszenie kosztu każdej pojedynczej pamięci podręcznej. (Całkowity koszt to koszt #misses *, główny nurt próbuje obniżyć pierwszy, Azul drugi.) Java Compute Accelerators firmy Azul może mieć 20000 równoczesnych braków pamięci podręcznej w locie i nadal robić postępy.
Kiedy Azul zaczął, ale myślałem , że oni trochę off-the-shelf I / O komponenty i zaprojektować własną specjalistyczną rdzeń procesora, ale to, co rzeczywiście skończyło się na konieczności robić dokładnie odwrotnie: miały one raczej standardowy off-the- półka 3-adresowy rdzeń RISC i zaprojektował własny kontroler pamięci, MMU i podsystem pamięci podręcznej.
tl; dr : „powolność” Pythona nie jest własnością języka, ale a) jego naiwną (podstawową) implementacją oraz b) faktem, że nowoczesne procesory i systemy operacyjne są specjalnie zaprojektowane tak, aby C działał szybko, i funkcje mają dla C albo nie pomagają (pamięć podręczna), a nawet aktywnie szkodzą (pamięć wirtualna) wydajności Pythona.
Możesz tu wstawić praktycznie każdy język zarządzany pamięcią z dynamicznym polimorfizmem ad-hoc… jeśli chodzi o wyzwania związane z wydajną implementacją, nawet Python i Java są w zasadzie „tym samym językiem”.