Für Python wurde ein JIT-Compiler vorgeschlagen, der die Technik copy-and-patch verwendet

Brandt Bucher von Microsoft, der zu den Kernentwicklern von CPython gehört und im Team arbeitet, das sich mit der Leistungssteigerung des CPython-Interpreters beschäftigt, hat eine Implementierung eines JIT-Compilers für Python veröffentlicht, die die Technik Copy-and-Patch verwendet. Die Veröffentlichung des JIT fällt auf Weihnachten, und die Ankündigung ist in Versform geschrieben.

Der vorgeschlagene JIT zeichnet sich durch eine sehr hohe Codegenerierungsgeschwindigkeit, einfache Wartung und vollständige Integration mit dem Interpreter aus. Das vorgeschlagene Verfahren ermöglicht es, den in C geschriebenen Interpreter automatisch in einen JIT-Compiler umzuwandeln, ohne separate Logik für die Codegenerierung zu entwickeln und ohne manuell Assemblerdarstellungen zu erstellen. Bei diesem Ansatz wird das Beheben eines Fehlers im Interpreter automatisch auch das gleiche Problem im JIT beheben, da ein gemeinsamer Codegenerator verwendet wird.

Die Funktionsweise der Methode Copy-and-Patch basiert darauf, dass die Relokation von Code im Speicher beim Laden von Objektdateien durch einen Linker und das Einfügen von Maschineninstruktionen anstelle von Bytecode im JIT ähnliche Aufgaben sind. Während der Ausführung des JIT-Compilers durchläuft das Programm die vom Interpreter erzeugten Bytecode-Anweisungen und kopiert für jede Anweisung den im Voraus kompilierten Maschinenkode in den Bereich des ausführbaren Codes, wobei die Anweisungen zur Laufzeit so verändert werden, dass die bearbeiteten Daten eingefügt werden (der JIT kopiert fertige Vorlagen bereits kompilierter Funktionen und setzt die erforderlichen Werte wie Argumente und Konstanten ein). Beim Laden von Objektdateien wird ebenfalls Maschinenkode in den Speicher kopiert und es erfolgt das Einfügen externer Symbole.

Im Copy-and-Patch JIT wird mit LLVM eine Objektdatei im ELF-Format erstellt, die Informationen über die Bytecode-Anweisungen und die erforderlichen Daten zum Austausch enthält. Der JIT ersetzt die während der Programminterpretation generierten Bytecode-Anweisungen durch Maschinenkode-Darstellungen und fügt gleichzeitig die notwendigen Daten für Berechnungen ein. Die JIT-Implementierung erfordert LLVM als Abhängigkeit während des Build-Prozesses, aber die zur Laufzeit verwendeten Komponenten sind nicht an externe Abhängigkeiten gebunden und belaufen sich auf etwa 300 manuell geschriebene C-Zeilen und 3000 generierte C-Codezeilen.

Im Vergleich zu traditionellen JIT-Tools (LLVM -O0) bietet der vorgeschlagene JIT eine hundertmal schnellere Codegenerierung und einen 15 % schnelleren resultierenden Code. Im Vergleich zur Kompilierung in WebAssembly (Liftoff) generiert der neue JIT Code fünfmal schneller, und der resultierende Code läuft 50 % schneller. Vergleicht man den neuen JIT mit dem optimierenden JIT (LuaJIT), der manuell geschriebenen Assembler-Code verwendet, war die vorgeschlagene Variante in 13 von 44 Tests schneller, während sie im Durchschnitt um 35 % in der Leistung zurückblieb, jedoch mit einer erheblichen Vereinfachung der Wartung und einer Verringerung des Implementierungsaufwands.

Video abspielen


Quelle: opennet.ru
60GB SSD 8Gb DDR4