Effizienz von Programmiersprachen


[ Gliederung ] [ Einführung ] [ Effizienz ] [ Regelmäßigkeit ] [ Einfachheit ] [ Ausdruckskraft ] [ Erweiterbarkeit ]
[ Einschränkbarkeit ] [ Präzision ] [ Sicherheit ] [ Fazit ] [ Literatur und Internetquellen ]

Effizienz


Effizienz des kompilierten Codes

Die Effizienz von Programmiersprachen ist ein breit gefächertes Feld. In den Anfängen der Entwicklung von Programmiersprachen ging es ausschließlich um Effizienz des generierten Objektcodes. Die Maschinen waren äußerst langsam und somit war es wichtig, dass die Ressourcen bestmöglich ausgenutzt wurden. Im Laufe der Entwicklung von Computern und Programmiersprachen kamen andere Kriterien zum Tragen, die die Ansicht zum Teil verdrängten, dass man heutzutage keinen überaus effizienten Programmcode mehr benötigt. Durch die rapide Entwicklung in Geschwindigkeit und Kapazität von Computern, sollten Programmierer auch einen Vorteil dadurch haben und eine einfachere und vielleicht auch mächtigere Programmiersprache zu Hand bekommen. Dieses Argument ist sogar vertretbar, wenn der Effizenzverlust vielleicht nur bei 10-20% oder sogar bei 30-40% liegt. Liegt der Verlust jedoch um den Faktor 2, 10 oder noch höher, dann ist dies nicht hinnehmbar. Dabei gilt es nicht nur den Overhead an Zeit zur Programmausführung zu beachten, sondern auch das Mehr an Platz, dass das Programm einnimmt. Es gibt somit mehrere Gründe eine Sprache effizient zu gestalten. Die Anforderungen an die Aufgaben, die ein Computer bewältigen muss, steigen stärker, als der Computer durch den Geschwindigkeitsgewinn ausgleichen kann. D.h. der Computer muss immer größere und schwierigere Aufgaben bewältigen, die zumeist nicht durch die Schnelligkeitsentwicklung der Hardware aufgefangen wird. Somit kann die Effizienz des Programmcodes nicht vernachlässigt werden.
Es ist egal wie schnell und billig Computer geworden sind, sie werden noch billiger und schneller, wenn man sie noch effizienter benutzen kann. Vielmehr sollte es der Programmierer und nicht der Sprachentwickler sein, der uneffizienten Code schreibt oder schreiben kann. Der Programmierer sollte die Freiheit haben alle Vorteile zu nutzen um ein gut strukturiertes, klares Programm zu schreiben. Der Programmierer sollte also nicht dazu gezwungen werden ein schlecht strukturiertes Programm zu schreiben nur um ein Effizienzgewinn zu erhalten.


Effizienz in der Übersetzung zu ausführbaren Code

Ein weiterer Bereich in der Effizienz von Programmiersprachen liegt in der Übersetzung zu ausführbaren Code. Hier taucht die Fragestellung auf, wie schnell ein Compiler den Code übersetzt und ob der Compiler eine angemessene Größe hat. D.h. der Compiler sollte ebenfalls nicht unnötig viel Speicher belegen.
Am Anfang der Entwicklung der Programmiersprachen ging man davon aus, dass der Code nur einmal kompiliert werden müsse. Doch es stellte sich heraus, dass das Gegenteil eher zutrifft. Der Programmcode wird äußerst oft kompiliert und dann debugged. Es besteht hier also eine Effizienzthematik im Design der Programmiersprache.
So besteht beispielsweise in den Sprachen C und Pascal die Möglichkeit einen "one-pass" Compiler zu schreiben d.h. der Compiler ließt den Quelltext nur einmal ein und compiliert ihn sofort. Dies ist deshalb möglich, da die Variablen in den Sprachen erst deklariert bevor sie benutzt werden müssen. In C++ ist dies nicht der Fall. Dort muss der Compiler (mindestens) noch ein zweites Mal den Code durchlaufen um den Type der Variable zu ermitteln, was zu einem Effizienzverlust führt. Somit gibt es einen Effizienzgewinn im Bereich der Entwicklung von Programmen, wenn die Programmiersprache auch einen "one-pass" Compiler unterstützt.


Effizienzproblem bei der Suche nach Programmierfehlern

Ein weiteres Problem bei der Entwicklung von Programmiersprachen besteht im Überprüfen des Programmcodes nach Fehlern. So ist es sehr schwer bzw. zumeist unmöglich einige Fehler im Programmcode zur Übersetzungs- bzw. Ausführungszeit zu erkennen. Dies führt zu einem weiteren Problem in der Entwicklung des Compilers. Zum einen soll er, wie vorher schon angemerkt, schnell und effizient arbeiten, aber auf der anderen Seite entsteht auch ein uneffizienter Programmcode, wenn eine Fehlerüberprüfung erst zur Ausführungszeit erfolgt. Andererseits kann man es auch nicht verantworten keine Fehlerüberprüfung zu machen, da es gegen ein genauso wichtiges Designkriterium verstößt und zwar der Zuverlässigkeit von Programmcode. Das Programm sollte sich möglichst nicht unerwartet während der Ausführungszeit verhalten.


Effizienz contra Flexibilität bei der Wahl des Bindungszeitpunktes

Effizienz spielt auch in der Wahl der Bindungszeiträume eine Rolle. Bindung bedeutet in dem Fall die Bindung eines Programmelements mit einem bestimmten Merkmal oder der Eigenschaft, die Auswahl eines Elements aus einer Menge möglicher Merkmale. So wird beispielsweise zu einer Variablen im Programm auch der Typ mitgebunden. Eine Bindung kann während der Übersetzungs- oder Ausführungszeit erfolgen. Die Vor- und Nachteile kann man an Hand eines Beispiels verdeutlichen.
Hierzu dient das Einrichten und Manipulieren von Zahlenarrays in den Sprachen Fortran und ML als Beispiel. So ist Fortran weitaus effizienter große Arrays und weitläufige arithmetische Operationen auszuführen. Wenn man sich die Bindungszeiträume anschaut, liegt der Grund auf der Hand. In ML finden die Bindungen vorwiegend zur Ausführungszeitzeit statt. D.h. die ML-Version von einem gleichen Programm wäre größtenteils mit dem Erstellen und Auflösen von Bindungen verbringen. Die Bindung der Fortran Version dieses Programmes müsste nur einmal zur Übersetzungszeit eingerichtet werden. Dadurch entsteht ein Effizienzgewinn in der Ausführungszeit.
Nachteil dieser Variante ist es, dass die Flexibilität von Fortran im Gegensatz zu ML leidet. Es zeigt sich hier schon wieder, dass unterschiedliche Designkriterium nicht immer miteinander vereinbar sind.


Effizienter Einsatz einer Programmiersprache

Ein weiterer Faktor von Effizienz ist die Möglichkeit einen geeigneten Compiler für eine Programmiersprache zu schreiben. Dies kann als Grund haben, dass es entweder zu schwierig ist einen geeigneten Compiler zu schreiben, weil die gesamte Grammatik nicht richtig verstanden wird oder eben auch einzelne Algorithmen die zur Sprachübersetzung benötigt werden, werden nicht verstanden. Es gibt ein paar Beispiele, wo dies zu Problemen oder auch Misserfolg von einigen Sprachen führte. So war bei Algol60 der Stack basierte Struktur des Systems weitläufig nicht bekannt. Auch war z.B. die Größe und Komplexität von Ada ein Hindernis und führte dazu, dass der Compiler schwerlich weiterentwickelt wurde und damit die Sprache wenig gebraucht wurde. Wenn die Sprache nicht verstanden wird oder werden kann, dann wird sie schlicht und ergreifend unübersetzbar und dadurch irgendwann irrelevant.


Schnelle und effiziente Programmierung in einer Programmiersprache

Eine andere Sichtweise für Effektivität lautet wie gut, strukturiert und schnell kann der Programmierer seine Vorstellung von einem Programm mit der Programmiersprache implementieren. Dieses Kriterium spielt auch in weitere Bereiche für Prinzipien zur Entwicklung von Programmiersprachen mit ein. So beinhaltet es zum Beispiel Les- und Schreibbarkeit einer Programmiersprache, das ebenfalls ein wichtiges Kriterium ist. Aber zurück zum Thema Effizienz, wo es darum geht dem Programmierer möglichst klare und einfach Strukturen zu geben, die sich nicht widersprechen. So wird den Programmierer das Schreiben eines Programms vereinfacht, wenn beispielsweise die Variablendeklarationen innerhalb eines Programms durch die Programmiersprache wegfallen. Dies verletzt zwar andere Designkriterien wie Lesbarkeit, aber für den Programmierer ist dies trotzdem erstmal ein Effizienzgewinn.
[ Gliederung ] [ Einführung ] [ Effizienz ] [ Regelmäßigkeit ] [ Einfachheit ] [ Ausdruckskraft ] [ Erweiterbarkeit ]
[ Einschränkbarkeit ] [ Präzision ] [ Sicherheit ] [ Fazit ] [ Literatur und Internetquellen ]