Was ist ein Compiler?

, ,
programming 942487 640

Ein Computer ist nicht selbständig in der Lage, die Anweisungen, die ein Entwickler in Form von Programmcode schreibt, zu verstehen. Die Codebefehle müssen entweder von einem sogenannten Compiler in Maschinensprache übersetze werden oder von einem sogenannten Interpreter zur Laufzeit interpretiert werden. Im folgenden Artikel gehen wir auf das Thema Compiler im Detail ein und schauen uns die Besonderheiten dieser Technologie im Kontext anderen Techniken an.

Was ist ein Compiler?

Moderne Programmiersprachen wie Java, Python oder JavaScript sind so konzipiert, dass sie von Programmierern ohne größere Probleme gelesen und geschrieben werden können. Damit ein Computer/PC mit den einzelnen Befehlen eines Programms etwas anfangen kann, muss der Quellcode erst in eine für den Computer verständliche Sprache übersetzt werden. Je nach Programmiersprache und Plattform wird das beispielsweise von einem Compiler oder Interpreter realisiert. Bei einem Compiler handelt es sich um eine Software, die Quellcode in Maschinensprache umwandelt. Konkret bedeutet das, dass ein Compiler das gesamte Computerprogramm von einer Programmiersprache in Maschinensprache übersetzt. Dabei wird der Programmcode in seiner Ganzheit übersetzt, bevor das Programm auf dem Computer ausgeführt wird.

In vielen Fällen wird noch ein Zwischenschritt eingeleitet, bevor das Programm in Maschinencode umgewandelt wird. In diesem Schritt wird der Quellcode des Programms zunächst in einen sogenannten „Zwischencode“ übersetzt, wie beispielsweise Objektcode oder Bytecode. Der Zwischencode bietet den entscheidenden Vorteil, dass er in den meisten Fällen auf unterschiedlichen Plattformen ausgeführt werden kann, ohne neu kompiliert werden zu müssen. Außerdem kann er auch von einem Interpreter verarbeitet werden, was beispielsweise bei der Programmiersprache Java der Fall ist. Aus diesem Zwischencode übersetzt der Interpreter dann Maschinencode, der von der jeweiligen Zielplattform verstanden wird. Per Linker wird dann eine ausführbare Datei (EXE-Datei) erstellt. Programmiersprachen höherer Ebenen, wie zum Beispiel Java oder C# arbeiten häufig mit Objekt- bzw. Bytecode, während Programmiersprachen, die nähere an der Hardwareebene sind, ausschließlich mit Maschinencode arbeiten.

c 622435 640

Im Rahmen der Kompilierung leitet der Compiler mehrere Schritte ein, um den jeweiligen Quellcode in ein lauffähiges Computerprogramm umzuwandeln. Je umfangreicher und komplizierter der Quellcode ist, umso mehr Zeit und Ressourcen werden bei der Kompilierung benötigt. Sobald das Programm jedoch lauffähig ist, kann es viel schneller und effizienter ausgeführt werden als interpretierte Programme. Dies ist auf die Tatsache zurückzuführen, da alle Anweisungen und Systemaufrufe bereits vollständig in einer für den Computer verständlichen Maschinensprache vorliegen. Beispiele für reine Compiler-Sprachen sind Pascal, C und C++.

Mehr zum Thema:
Was ist eigentlich... Active Directory - und warum brauchen wir das?

Was ist ein Interpreter?

Bei einem Interpreter, wie beispielswiese bei der BASIC-Programmiersprache, handelt es sich um ein Computerprogramm, das den Quellcode einer Anwendung zur Laufzeit verarbeitet. Der Interpreter geht dabei Zeile für Zeile vor: Ein Befehlt wird erfasst, analysiert und sofort ausgeführt. Danach geht es mit dem nächsten Befehl weiter, bis das Ende des Quellcodes erreicht ist oder alternativ ein Fehler den Vorgang zum Stillstand bringt. Sobald etwas nicht stimmt, unterbricht der Interpreter seine Arbeit. Dies liefert Entwicklern wichtige Informationen zur Fehlerbehebung. Man weiß als Entwickler sofort an welcher Stelle im Quellcode sich der Fehler befindet und man kann das Problem so schneller beseitigen.

Im Gegensatz zum Compiler erzeugt ein Interpreter keine ausführbare Datei, die man verteilen, kopieren oder mehrmals ausführen kann. Außerdem fertigt er auch keine Umwandlung des Quellcodes in Maschinensprache an, sondern er fungiert viel mehr als eine Zwischenschicht zwischen der Programmiersprache und dem Computer. Ein Interpreter wertet zur Laufzeit jeden einzelnen Befehl eines Computerprogramms aus und ruft die entsprechenden Funktionen und Systemaufrufe auf, welche die gewünschten Funktionen auf dem Zielsystem auslösen. Da ein Interpreter in Echtzeit arbeitet, wobei jeder einzelne Befehl bearbeitet werden muss, sind interpretierte Sprachen, wie beispielsweise Python oder JavaScript, langsamer und weniger effizienter als kompilierte Sprachen. So werden beispielsweise auch wiederkehrende Anweisungen immer wieder aufs Neue aufgerufen, was die Effizienz äußerst negativ beeinflusst.

programmer 1653351 640

Das Beste aus beiden Welten: der Just-in-time Compiler

Heutzutage gibt es moderne Ansätze, die Interpreter und Compiler vereinen und so die Nachteile der jeweiligen Systeme eliminieren. Der Just-in-time-Compiler übersetzt den Quellcode erst zur Laufzeit in Maschinensprache. Die Kompilierung wird also nicht bereits vorab realisiert. Nachdem der Quellcode erfolgreich kompiliert wurde, wird er vom Prozessor des Zielsystems verarbeitet. Gegenüber der traditionellen Kompilierung hat diese Vorgehensweise wesentliche Performance-Vorteile. Bei der Just-in-time-Kompilierung werden gesamte Codeblöcke reihenweise bearbeitet. Auch das bringt gegenüber der sonst üblichen zeilenweisen Bearbeitung des Quellcodes eine Leistungssteigerung mit sich.

Moderne JiT-Compiler sind in der Lage, einen für dynamische Sprachen optimierte Code zu generieren. Darüber hinaus bietet die Just-in-time-Kompilierung den entscheidenden Vorteil, dass vor dem Programmstart nur ein geringer Teil kompiliert wird, wodurch das Problem der Verzögerung des Programmstarts so gut wie eliminiert wird. Darüber hinaus wird äußerst effizient mit den System-Ressourcen umgegangen. Codefragmente, die überhaupt nicht durchlaufen werden, werden auch nicht kompiliert. Im Rahmen der JiT-Kompilierung werden einmal fertig kompilierte Codeblöcke in einem Zwischenspeicher aufbewahrt. Bei einer erneuten Kompilierung werden die benötigten Codeblöcke einfach aus dem Zwischenspeicher geladen und müssen nicht neu kompiliert werden.