Was ist PyPy?

09.12.2023
Von 
Serdar Yegulalp schreibt für unsere US-Schwesterpublikation Infoworld.
PyPy kann Python-Programme um ein Vielfaches beschleunigen. Das sollten Sie zum Thema wissen.
PyPy bringt Python in Fahrt.
PyPy bringt Python in Fahrt.
Foto: AS photo family - shutterstock.com

Python steht im Ruf, leistungsfähig, flexibel und einfach anzuwenden zu sein. Deswegen setzen auch immer mehr Applikationen, Workflows und Bereiche auf die Programmiersprache. Designbedingt war Python allerdings schon immer eine Größenordnung langsamer als maschinennative Sprachen wie C oder C++.

Um die Speed-Limitationen von Python zu umgehen, haben Entwickler im Laufe der letzten Jahre eine ganze Reihe von Workarounds entwickelt. Performance-intensive Tasks lassen sich beispielsweise in C erstellen und dann mit Python "wrappen" - ein Ansatz, der bei den meisten Machine-Learning-Bibliotheken zum Einsatz kommt. Eine andere Lösung wäre, Cython zu verwenden.

Workarounds sind zwar praktisch, aber selten eine Ideallösung. Genau das verspricht PyPy: Ein bestehendes Python-Programm so wie es ist auszuführen - nur wesentlich schneller.

PyPy vs CPython

PyPy ist ein Drop-In-Ersatz für den Standard-Python-Interpreter CPython. Letzterer kompiliert Python in Intermediate Bytecode, der anschließend von einer virtuellen Maschine interpretiert wird. Im Gegensatz dazu verwendet PyPy Just-in-Time-Kompilierung (JIT), um Python-Code in maschinennative Assemblersprache zu übersetzen.

Dabei können die Performance-Steigerungen je nach Task signifikant ausfallen. Im (geometrischen) Durchschnitt kann PyPy CPython um das 4,7-Fache (Basis: CPython 3.7) übertreffen - einzelne Tasks sogar um den Faktor 50 oder mehr beschleunigen. Zwar wurden JIT-Optimierungen inzwischen auch zu CPython hinzugefügt, allerdings übertrifft PyPy diese sowohl im Umfang als auch was Performance angeht, deutlich.

PyPy unterstützt derzeit sowohl Python 2.x als auch Python 3.x (aktuell bis 3.9; 3.10 nur experimentell). Welche PyPy-Version Sie brauchen, hängt davon ab, welche Python-Version Sie verwenden. PyPy funktioniert auch mit der überwiegenden Mehrheit der Tools innerhalb des Python-Ökosystems, etwa pip (Paketierung) oder virtualenv (virtuelle Umgebungen). Auch die meisten Python-Packages (auch solche mit C-Modulen) sollten ohne Probleme funktionieren.

Wie PyPy funktioniert

PyPy verwendet Optimierungstechniken anderer Just-in-Time-Compiler für dynamische Sprachen und analysiert laufende Python-Programme, um die Typinformationen von Objekten zu ermitteln, während diese erstellt und verwendet werden. Erstgenannte dienen anschließend als Leitfaden, um die Dinge zu beschleunigen. Arbeitet eine Python-Funktion beispielsweise nur mit einem oder zwei verschiedenen Objekttypen, generiert PyPy Maschinencode, der diese speziellen Fälle adressiert.

Die Optimierungen von PyPy werden automatisch zur Laufzeit ausgeführt, so dass keine weiteren Leistungsoptimierungen nötig sind. Fortgeschrittene Benutzer dürfen darüber hinaus mit den Kommandozeilenoptionen von PyPy experimentieren, um noch schnelleren Python-Code für Spezial-Use-Cases zu generieren.

PyPy weicht in der Praxis von der Art und Weise ab, wie CPython einige interne Funktionen handhabt, versucht aber, die Kompatibilität so weit wie möglich zu wahren. Zum Beispiel behandelt PyPy die Garbage Collection anders als CPython: Nicht alle Objekte werden sofort eingesammelt, wenn sie den Gültigkeitsbereich verlassen. Daher kann ein Python-Programm, das unter PyPy läuft, einen höheren Speicherbedarf aufweisen als eines unter CPython. Dennoch können Sie jedoch immer noch die High-Level-Garbage-Collection-Kontrollen von Python nutzen. Diese sind über das gc-Modul zugänglich (beispielsweise gc.enable(), gc.disable() und gc.collect()).

Wenn Sie Informationen über das JIT-Verhalten von PyPy zur Laufzeit einsehen möchten, enthält PyPy das Modul pypyjit, das viele JIT-Hooks für Ihre Python-App bereitstellt. Sollte eine Funktion oder ein Modul mit dem JIT schlecht performen, gibt pypyjit detaillierte statistische Einblicke darüber.

Ein anderes PyPy-spezifisches Modul ist __pypy__, das weitere PyPy-spezifische Funktionen zur Verfügung stellt. Aufgrund der Laufzeitdynamik von Python ist es möglich, Python-Anwendungen zu erstellen, die diese Funktionen nutzen, wenn PyPy vorhanden ist, und sie ignorieren, wenn nicht.

Die Limitationen von PyPy

PyPy mag aus mancher Perspektive magisch erscheinen, ist jedoch kein vollständig universeller Ersatz für die CPython-Laufzeitumgebung. Einige seiner Limitationen schränken seine Effektivität für bestimmte Programme ein - oder beseitigen sie komplett. Die folgenden drei Einschränkungen sollten Sie dabei insbesondere auf dem Schirm haben:

1. PyPy funktioniert am besten mit purem Python

Anwendungen, die ausschließlich in Python geschrieben sind, holen das Maximum aus PyPy heraus. Python-Pakete, die eine Schnittstelle zu C-Bibliotheken aufweisen, etwa NumPy, schneiden aufgrund der Art und Weise, wie PyPy die nativen Binärschnittstellen von CPython emuliert, nicht so gut ab.

Die PyPy-Entwickler haben an diesem Problem gefeilt und PyPy mit den meisten Python-Paketen, die von C-Erweiterungen abhängen, kompatibel gemacht. NumPy funktioniert inzwischen beispielsweise sehr gut mit PyPy. Wenn Sie auf maximale Kompatibilität mit C-Erweiterungen angewiesen sind, ist CPython zu empfehlen.

2. PyPy funktioniert am besten mit langfristig angelegten Apps

Ein Nebeneffekt, wenn man Python-Programme mit PyPy optimiert: Länger laufende Programme profitieren davon am meisten. Denn je länger das Programm läuft, desto mehr Laufzeittypinformationen kann PyPy sammeln und Optimierungen kann es vornehmen. Applikationen, die davon profitieren, haben typischerweise Loops, die über lange Zeiträume laufen oder laufen kontinuierlich im Hintergrund - wie zum Beispiel Web-Frameworks.

3. PyPy beherrscht Ahead-of-Time Compilation nicht

PyPy kompiliert zwar Python-Code, ist aber kein Compiler für Python-Code. Aufgrund der Art und Weise, wie PyPy seine Optimierungen durchführt sowie der Dynamik, die Python inhärent ist, gibt es keine Möglichkeit, den resultierenden JIT-kompilierten Code als eigenständige Binärdatei auszugeben und wiederzuverwenden. Jedes Programm muss für jeden Lauf kompiliert werden - wie auch in der Dokumentation beschrieben.

Wenn Sie Python in schnellen Code kompilieren wollen, der als eigenständige Anwendung läuft, sollten Sie auf

Dieser Beitrag basiert auf einem Artikel unserer US-Schwesterpublikation Infoworld.