Python har fått rykte om sig att vara kraftfull, flexibel och lätt att arbeta med. Dessa dygder har lett till att den används i ett stort och växande antal tillämpningar, arbetsflöden och områden. Men språkets utformning – dess tolkade natur, dess dynamik vid körning – innebär att Python alltid har varit en storleksordning långsammare än maskinella språk som C eller C++.

Under årens lopp har utvecklare kommit på en rad olika lösningar på Pythons hastighetsbegränsningar. Du kan till exempel skriva prestandaintensiva uppgifter i C och paketera dem med Python; många bibliotek för maskininlärning gör exakt detta. Eller så kan du använda Cython, ett projekt som låter dig strö Pythonkoden med information om körtidstyp som gör att den kan kompileras till C.

Men lösningar är aldrig idealiska. Skulle det inte vara fantastiskt om vi bara kunde ta ett befintligt Pythonprogram som det är och köra det dramatiskt mycket snabbare? Det är precis vad PyPy låter dig göra.

PyPyPy vs. CPython

PyPyPy är en drop-in ersättare för den vanliga Python-tolken CPython. Medan CPython kompilerar Python till mellanliggande bytekod som sedan tolkas av en virtuell maskin, använder PyPy just-in-time-kompilering (JIT) för att översätta Python-kod till maskinnära assemblerspråk.

Avhängigt av den uppgift som utförs kan prestandavinsterna vara dramatiska. I genomsnitt snabbar PyPy upp Python med ungefär 7,6 gånger, och vissa uppgifter accelereras 50 gånger eller mer. CPython-tolken utför helt enkelt inte samma typer av optimeringar som PyPy, och kommer förmodligen aldrig att göra det eftersom det inte är ett av dess designmål.

Det bästa är att det krävs liten eller ingen ansträngning från utvecklarens sida för att låsa upp de vinster som PyPy ger. Det är bara att byta ut CPython mot PyPy och för det mesta är du klar. Det finns några få undantag, som diskuteras nedan, men PyPys uttalade mål är att köra befintlig, oförändrad Pythonkod och ge den en automatisk hastighetsökning.

PyPyPy stöder för närvarande både Python 2 och Python 3, genom olika inkarnationer av projektet. Med andra ord måste du ladda ner olika versioner av PyPy beroende på vilken version av Python du kommer att köra. Python 2-grenen av PyPy har funnits mycket längre, men Python 3-versionen har nyligen uppdaterats. Den stöder för närvarande både Python 3.5 (produktionskvalitet) och Python 3.6 (betakvalitet).

Förutom stöd för hela kärnspråket Python fungerar PyPy med den stora majoriteten av verktygen i Python-ekosystemet, till exempel pip för paketering eller virtualenv för virtuella miljöer. De flesta Pythonpaket, även de med C-moduler, bör fungera som de är, även om det finns begränsningar som vi går in på nedan.

Hur PyPy fungerar

PyPyPy använder optimeringstekniker som finns i andra just-in-time-kompilatorer för dynamiska språk. Den analyserar pågående Pythonprogram för att bestämma typinformationen för objekt när de skapas och används i programmen, och använder sedan denna typinformation som en vägledning för att snabba upp saker och ting. Om en Pythonfunktion till exempel bara arbetar med en eller två olika objekttyper genererar PyPy maskinkod för att hantera dessa specifika fall.

PyPys optimeringar hanteras automatiskt vid körning, så du behöver i allmänhet inte justera dess prestanda. En avancerad användare kan experimentera med PyPys kommandoradsalternativ för att generera snabbare kod för specialfall, men det är bara sällan det är nödvändigt.

PyPyPy avviker också från hur CPython hanterar vissa interna funktioner, men försöker bevara kompatibla beteenden. PyPy hanterar till exempel garbage collection på ett annat sätt än CPython. Alla objekt samlas inte omedelbart in när de går utanför räckvidden, så ett Pythonprogram som körs under PyPy kan visa ett större minnesavtryck än när det körs under CPython. Men du kan fortfarande använda Pythons kontroller för sophämtning på hög nivå som exponeras via modulen gc, till exempel gc.enable(), gc.disable() och gc.collect().

Om du vill ha information om PyPys JIT-beteende vid körning innehåller PyPy en modul, pypyjit, som exponerar många JIT-krokar för ditt Pythonprogram. Om du har en funktion eller modul som verkar prestera dåligt med JIT kan du med pypyjit få detaljerad statistik om den.

En annan PyPy-specifik modul, __pypy__, exponerar andra funktioner som är specifika för PyPy, så den kan vara användbar för att skriva program som utnyttjar dessa funktioner. På grund av Pythons körtidsdynamik är det möjligt att konstruera Python-appar som använder dessa funktioner när PyPy är närvarande och ignorerar dem när det inte är det.

PyPyPy-begränsningar

Magisk som PyPy kan tyckas vara, är det inte magi. PyPy har vissa begränsningar som minskar eller omöjliggör dess effektivitet för vissa typer av program. Tyvärr är PyPy inte en helt universell ersättning för CPythons standardkörningstid.

PyPyPy fungerar bäst med rena Pythonprogram

PyPyPy har alltid fungerat bäst med ”rena” Pythonprogram – det vill säga program som är skrivna i Python och inget annat. Pythonpaket som har ett gränssnitt mot C-bibliotek, t.ex. NumPy, har inte klarat sig lika bra på grund av det sätt på vilket PyPy emulerar CPythons ursprungliga binära gränssnitt.

PyPys utvecklare har gjort sig av med detta problem och gjort PyPy mer kompatibel med majoriteten av de Pythonpaket som är beroende av C-förlängningar. Numpy, till exempel, fungerar mycket bra med PyPy nu. Men om du vill ha maximal kompatibilitet med C-tillägg ska du använda CPython.

PyPyPy fungerar bäst med längre löpande program

En av bieffekterna av hur PyPy optimerar Pythonprogram är att längre löpande program gynnas mest av dess optimeringar. Ju längre programmet körs, desto mer information om körtidstyper kan PyPy samla in och desto fler optimeringar kan den göra. Python-skript som bara är en gång till kommer inte att gynnas av den här typen av saker. De program som gynnas har vanligtvis slingor som körs under långa perioder eller körs kontinuerligt i bakgrunden – till exempel webbramverk.

PyPyPy gör ingen kompilering i förväg

PyPyPy kompilerar Python-kod, men det är inte en kompilator för Python-kod. På grund av hur PyPy utför sina optimeringar och den inneboende dynamiken i Python finns det inget sätt att emittera den resulterande JITt-behandlade koden som en fristående binär kod och återanvända den. Varje program måste kompileras för varje körning. Om du vill kompilera Python till snabbare kod som kan köras som en fristående app, använd Cython, Numba eller det för närvarande experimentella Nuitka-projektet.

Lämna ett svar

Din e-postadress kommer inte publiceras.