Programmering

Hvad er PyPy? Hurtigere Python uden smerter

Python har opnået et ry for at være stærk, fleksibel og nem at arbejde med. Disse dyder har ført til dets anvendelse i et stort og voksende udvalg af applikationer, arbejdsgange og felter. Men designet af sproget - dets fortolkede natur, dets runtime-dynamik - betyder, at Python altid har været en størrelsesorden langsommere end maskinindfødte sprog som C eller C ++.

I årenes løb har udviklere kommet med en række løsninger til Pythons hastighedsbegrænsninger. For eksempel kan du skrive præstationsintensive opgaver i C og pakke det med Python; mange maskinlæringsbiblioteker gør netop dette. Eller du kan bruge Cython, et projekt, der lader dig drysse Python-kode med runtime-information, der gør det muligt at kompilere den til C.

Men løsninger er aldrig ideelle. Ville det ikke være godt, hvis vi bare kunne tage et eksisterende Python-programsom det er, og køre det dramatisk hurtigere? Det er præcis, hvad PyPy giver dig mulighed for at gøre.

Relateret video: Brug af PyPy-runtime til Python

PyPy vs. CPython

PyPy er en drop-in erstatning for lager Python tolk, CPython. Mens CPython kompilerer Python til mellemliggende bytecode, der derefter fortolkes af en virtuel maskine, bruger PyPy just-in-time (JIT) -kompilering til at oversætte Python-kode til maskinindfødt samlingssprog.

Afhængigt af den opgave, der udføres, kan præstationsgevinsterne være dramatiske. I gennemsnit fremskynder PyPy Python ca. 7,6 gange, hvor nogle opgaver accelereres 50 gange eller mere. CPython-tolk udfører simpelthen ikke de samme slags optimeringer som PyPy og vil sandsynligvis aldrig, da det ikke er et af dens designmål.

Den bedste del er, at der kræves lidt eller ingen indsats fra udviklerens side for at låse op for de gevinster, PyPy giver. Du skal blot bytte CPython ud for PyPy, og for det meste er du færdig. Der er et par undtagelser, der diskuteres nedenfor, men PyPys erklærede mål er at køre eksisterende, umodificeret Python-kode og give den en automatisk hastighedsforøgelse.

PyPy understøtter i øjeblikket både Python 2 og Python 3 ved forskellige inkarnationer af projektet. Med andre ord skal du downloade forskellige versioner af PyPy afhængigt af den version af Python, du kører. Python 2-grenen af ​​PyPy har eksisteret meget længere, men Python 3-versionen er blevet bragt op til hastighed sent. Den understøtter i øjeblikket både Python 3.5 (produktionskvalitet) og Python 3.6 (beta-kvalitet).

Ud over at understøtte hele det centrale Python-sprog fungerer PyPy med langt størstedelen af ​​værktøjerne i Python-økosystemet, såsompip til emballering ellervirtualenv til virtuelle miljøer. De fleste Python-pakker, selv dem med C-moduler, skal fungere som de er, selvom der er begrænsninger, vi går ind på nedenfor.

Sådan fungerer PyPy

PyPy bruger optimeringsteknikker, der findes i andre just-in-time kompilatorer til dynamiske sprog. Den analyserer kørende Python-programmer for at bestemme typeoplysningerne for objekter, når de oprettes og bruges i programmer, og bruger derefter den type information som en guide til at fremskynde tingene. For eksempel, hvis en Python-funktion kun fungerer med en eller to forskellige objekttyper, genererer PyPy maskinkode til at håndtere disse specifikke tilfælde.

PyPys optimeringer håndteres automatisk ved kørsel, så du behøver generelt ikke at tilpasse dens ydeevne. En avanceret bruger kan eksperimentere med PyPys kommandolinjemuligheder for at generere hurtigere kode til specielle tilfælde, men kun sjældent er dette nødvendigt.

PyPy afviger også fra den måde, CPython håndterer nogle interne funktioner på, men forsøger at bevare kompatibel adfærd. For eksempel håndterer PyPy affaldssamling anderledes end CPython. Ikke alle objekter indsamles straks, når de er uden for anvendelsesområdet, så et Python-program, der kører under PyPy, viser muligvis et større hukommelsesfodaftryk, end når det kører under CPython. Men du kan stadig bruge Pythons kontrolniveauer til skraldopsamling på højt niveau, der er eksponeret gennem gc modul, f.eks gc.enable (), gc.disable ()og gc.collect ().

Hvis du vil have oplysninger om PyPys JIT-opførsel under kørsel, inkluderer PyPy et modul, pypyjit, der udsætter mange JIT-kroge til din Python-applikation. Hvis du har en funktion eller et modul, der ser ud til at fungere dårligt med JIT, pypyjit giver dig mulighed for at få detaljerede statistikker om det.

Et andet PyPy-specifikt modul, __pypy__, udsætter andre funktioner, der er specifikke for PyPy, så det kan være nyttigt til at skrive apps, der udnytter disse funktioner. På grund af Pythons dynamik i runtime er det muligt at konstruere Python-apps, der bruger disse funktioner, når PyPy er til stede, og ignorerer dem, når det ikke er tilfældet.

PyPy-begrænsninger

Magisk som PyPy måske ser ud, er det ikke magisk. PyPy har visse begrænsninger, der reducerer eller undgår dens effektivitet for visse former for programmer. Ak, PyPy er ikke en helt universel erstatning for lager-CPython-runtime.

PyPy fungerer bedst med rene Python-apps

PyPy har altid fungeret bedst med "rene" Python-applikationer - dvs. applikationer skrevet i Python og intet andet. Python-pakker, der grænseflader med C-biblioteker, såsom NumPy, har ikke haft det så godt på grund af den måde, PyPy emulerer CPythons native binære grænseflader på.

PyPys udviklere har fjernet dette problem og gjort PyPy mere kompatibel med de fleste Python-pakker, der afhænger af C-udvidelser. Numpy fungerer for eksempel meget godt med PyPy nu. Men hvis du vil have maksimal kompatibilitet med C-udvidelser, skal du bruge CPython.

PyPy fungerer bedst med programmer, der kører længere

En af bivirkningerne ved, hvordan PyPy optimerer Python-programmer, er at programmer, der kører længere, har mest gavn af dens optimeringer. Jo længere programmet kører, jo mere information om kørselstiden kan PyPy indsamle, og jo flere optimeringer kan det foretage. One-and-done Python-scripts drager ikke fordel af denne slags ting. De applikationer, der nyder godt af, har typisk sløjfer, der kører i lange perioder eller kører kontinuerligt i baggrunden - f.eks. Webrammer.

PyPy foretager ikke kompilering på forhånd

PyPykompilerer Python-kode, men det er det ikkeen kompilator til Python-kode. På grund af den måde, PyPy udfører sine optimeringer på og den iboende dynamik i Python, er der ingen måde at udsende den resulterende JITted-kode som en enkeltstående binær og genbruge den. Hvert program skal udarbejdes for hver kørsel. Hvis du vil kompilere Python til hurtigere kode, der kan køre som en enkeltstående app, skal du bruge Cython, Numba eller det nuværende eksperimentelle Nuitka-projekt.