Ich vergleiche zwei Technologien, um eine Empfehlung zu erhalten, für die eine von einem Unternehmen verwendet werden sollte. Der Code von Technologie A wird interpretiert, während der Code von Technologie B zu Maschinencode kompiliert wird. In meinem Vergleich stelle ich fest, dass Tech B im Allgemeinen eine bessere Leistung hätte, da es nicht den zusätzlichen Overhead des Interpretationsprozesses hat. Ich stelle auch fest, dass ein Programm, das in Tech A geschrieben wurde, ein in Tech B geschriebenes Programm übertreffen kann, da es auf viele Arten geschrieben werden kann.
Als ich diesen Bericht zur Überprüfung einreichte, gab der Prüfer an, dass ich keinen eindeutigen Grund angegeben habe, warum der Aufwand für den Interpretationsprozess im Allgemeinen groß genug wäre, um zu dem Schluss zu gelangen, dass die Leistung von Tech B besser wäre.
Meine Frage ist also, können wir jemals etwas über die Leistung kompilierter / interpretierter Technologien sagen? Wenn wir sagen können, kompiliert ist im Allgemeinen schneller als interpretiert, wie könnte ich den Prüfer von meinem Standpunkt überzeugen?
Antworten:
Nein.
Im Allgemeinen hängt die Leistung einer Sprachimplementierung in erster Linie von der Menge an Geld, Ressourcen, Arbeitskräften, Forschung, Technik und Entwicklung ab, die dafür ausgegeben werden.
Insbesondere hängt die Leistung eines bestimmten Programms in erster Linie von der Menge an Gedanken ab, die in seine Algorithmen gesteckt werden.
Es gibt einige sehr schnelle Interpreter und einige Compiler, die sehr langsamen Code generieren .
Einer der Gründe, warum Forth nach wie vor beliebt ist, ist, dass ein interpretiertes Forth-Programm in vielen Fällen schneller ist als das entsprechende kompilierte C-Programm, während gleichzeitig das in Forth geschriebene Anwenderprogramm plus der Forth-Interpreter geschrieben werden in C ist kleiner als das in C geschriebene Anwenderprogramm
quelle
Verallgemeinerungen und spezifische Szenarien sind buchstäblich gegensätzlich.
Sie scheinen sich selbst zu widersprechen. Einerseits möchten Sie eine allgemeine Aussage über interpretierte und kompilierte Sprachen treffen. Andererseits möchten Sie diese allgemeine Aussage auf ein konkretes Szenario anwenden, das Technologie A und Technologie B umfasst.
Sobald Sie etwas auf ein konkretes Szenario angewendet haben, wird es nicht mehr verallgemeinert . Selbst wenn Sie feststellen können, dass interpretierte Sprachen im Allgemeinen langsamer sind , sind Sie dennoch nicht richtig. Verallgemeinerungen interessieren Ihren Rezensenten nicht. Sie analysieren zwei sehr spezifische Technologien. Das ist buchstäblich das Gegenteil von Generalisierung.
quelle
Als Faustregel gilt, dass ein interpretiertes Programm etwa 2x – 10x langsamer ist als das Schreiben des Programms in der Hostsprache des Interpreters, wobei Interpreter für dynamischere Sprachen langsamer sind. Dies liegt daran, dass das interpretierte Programm die gesamte eigentliche Arbeit erledigen muss, aber zusätzlich den Interpretationsaufwand hat.
Abhängig von der Struktur des Interpreters kann es zu sehr signifikanten Unterschieden kommen. Es gibt zwei widersprüchliche Konstruktionsmethoden für Interpreter: Die eine besagt, dass Opcodes so klein wie möglich sein sollten, damit sie einfacher optimiert werden können, die andere besagt, dass Opcodes so groß wie möglich sein sollten, damit wir mehr im Interpreter arbeiten. Wenn die Struktur Ihres Programms mit der Philosophie des Interpreters übereinstimmt, wird der Overhead vernachlässigbar.
ZB Perl ist eine interpretierte Sprache, die sich an Textmanipulationen orientiert. Ein idiomatisches Perl-Programm, das Textmanipulation ausführt, ist nicht viel langsamer als ein C-Programm und kann in einigen Fällen sogar die Leistung des C-Programms übertreffen (möglich, weil Perl eine andere Zeichenfolgendarstellung verwendet und verschiedene text- und E / A-bezogene Optimierungen eingebaut hat). Allerdings wird es in Perl unerträglich langsam, Zahlen zu knacken. Ein Inkrement
++x
ist eine einzelne Assemblierungsanweisung, umfasst jedoch mehrere Zeigerdurchläufe und Verzweigungen für den Perl-Interpreter. Ich habe kürzlich ein CPU-gebundenes Perl-Skript nach C ++ portiert und je nach Optimierungsstufe des Compilers eine 7x – 20x höhere Geschwindigkeit erzielt.Das Sprechen über Optimierungen ist hier wichtig, da ein polierter, optimierter Interpreter einen nicht optimierenden naiven Compiler vernünftigerweise übertreffen kann. Da das Erstellen eines optimierenden Compilers schwierig ist und viel Aufwand erfordert, ist es unwahrscheinlich, dass Ihre „Technologie B“ diesen Reifegrad aufweist.
(Hinweis: Die Computersprachen-Benchmarks-Spieleseite hat eine verwirrende Struktur, aber sobald Sie die Tabelle mit den Zeitangaben für ein Problem erreicht haben, werden Sie feststellen, dass die Leistung verschiedener Sprachen überall vorhanden ist - häufig gibt es keine klare Leistungsgrenze zwischen kompilierten und interpretierten Lösungen. Der wichtigste Teil der Website sind nicht die Benchmark-Ergebnisse, sondern die Diskussionen darüber, wie schwierig aussagekräftige Benchmarks sind.)
Bei der Auswahl einer Technologie spielt die Leistung einer Sprachlaufzeit für sich genommen keine Rolle. Es ist wahrscheinlicher, dass die Technologie einige grundlegende Einschränkungen erfüllt (unser Budget ist $ x, wir müssen in der Lage sein, vor dem JJJJ-MM-TT zu liefern, wir müssen verschiedene nicht-funktionale Anforderungen erfüllen) und dass es einen niedrigeren Wert hat Gesamtbetriebskosten (Berücksichtigung der Entwicklerproduktivität, der Hardwarekosten, der Kosten für Geschäftsmöglichkeiten, des Risikos von Fehlern und unerwarteten technischen Einschränkungen, der Wartungskosten, der Schulungs- und Einstellungskosten usw.). ZB in einer Branche, in der Time-to-Market der wichtigste Faktor ist, passt die Technologie mit der besten Entwicklerproduktivität am besten. Für eine große Organisation sind Wartbarkeit und langfristige Kosten möglicherweise interessanter.
quelle
Sie können absolut etwas über die Leistung kompilierter / interpretierter Technologien sagen. Aber zuerst müssen Sie "Leistung" definieren. Wenn Sie ein rechnerisch einfaches eingebettetes System erstellen, würde sich die "Leistung" wahrscheinlich nach der Seite der Speichernutzung richten. Während ein rechenintensives System, das mit großen Datenmengen arbeitet, "Leistung" in der Anzahl der Berechnungen pro Zeiteinheit definiert, da der Speicheraufwand von JVM oder .NET vernachlässigbar wäre.
Wenn Sie sich für die "Leistung" entschieden haben, können Sie sagen: "Wir haben zu jedem Zeitpunkt 50 Milliarden Objekte im Speicher. Die interpretierte TechA fügt jedem Objekt zusätzliche 8 Bytes für die interne Verwaltung hinzu, was einem Speicheraufwand von 400 GB entspricht im vergleich zu techB das diese daten nicht hinzufügt "
quelle
Dies ist eine technische Frage, und Sie haben bereits viele gute technische Antworten erhalten. Ich möchte jedoch auf einen etwas anderen Aspekt Ihrer Situation hinweisen: Die Tatsache, dass Sie eine Entscheidung wie "Technologie A oder Technologie B" nicht einfach nur begründen können aus technischen und / oder Leistungsgründen.
Die technischen Aspekte von so etwas sind nur ein kleiner Teil der Entscheidung zwischen A und B. Dutzende weiterer Faktoren sind zu berücksichtigen:
Wie Sie sehen, gibt es eine Menge Dinge zu beachten, wenn Sie eine solche Entscheidung treffen.
Ich weiß, dass dies Ihre Frage nicht spezifisch beantwortet, aber ich denke, dass es eine umfassendere Sicht auf Ihre Situation und die Einzelheiten einer solchen Entscheidung bietet.
quelle
Die Teilevaluierung ist ein konzeptioneller Rahmen, der für die Beziehung zwischen Dolmetschern und Compilern relevant ist.
Programmiersprachen sind Spezifikationen (in einigen Berichten, z. B. R5RS oder n1570 ). Da es sich nicht um Software handelt, ist es nicht einmal sinnvoll, von Leistung zu sprechen . Einige Programmiersprachen können jedoch mehrere Implementierungen aufweisen, einschließlich Interpreter und Compiler .
Selbst in traditionell kompilierten Sprachen (dh Sprachen, deren Implementierungen häufig Compiler sind) wie C werden einige Teile häufig interpretiert. Beispielsweise wird die Formatsteuerzeichenfolge von printf (definiert im C-Standard) häufig "interpretiert" (von der C-Standardbibliothek , die eine
printf
Funktion unter Verwendung von Techniken mit variablen Argumenten hat), aber einige Compiler (einschließlich GCC ) sind in der Lage, in bestimmten Grenzen zu arbeiten Fälle - um es zu optimieren und in untergeordnete Aufrufe zu "kompilieren".Einige Implementierungen, auch innerhalb von "Interpretern", verwenden JIT-Kompilierungstechniken (generieren Sie also Maschinencode zur Laufzeit ). Ein gutes Beispiel ist Luajit . Andere Implementierungen (z. B. Python, Ocaml, Java, Parrot, Lua) übersetzen den Quellcode in einen Bytecode, der dann interpretiert wird.
SBCL ist ein Common-Lisp-Compiler, der jede REPL- Interaktion (und Aufrufe von
eval
etc ...) dynamisch in Maschinencode übersetzt. Sie fühlen sich als Dolmetscher. Die meisten JavaScript-Implementierungen in Browsern (z. B. v8 ) verwenden JIT-Kompilierungstechniken.Mit anderen Worten, ist der Unterschied zwischen Interpreter und Compiler sehr unscharf (es ist eigentlich ein Kontinuum zwischen den beiden), und praktisch gesehen, die meisten Programmiersprache Implementierungen hat oft sowohl einen Dolmetscher und einen Compiler (zumindest auf Byte - Code) Facette.
Eine Implementierung kann schnell oder langsam sein, unabhängig davon, ob die meisten "Compiler" - oder "Interpreter" -Techniken verwendet werden.
Einige Sprachmerkmale bevorzugen einen Dolmetschansatz (und können nur durch Analyse des gesamten Programms effizient zusammengestellt werden).
Bei einigen Arten von Problemen lohnt es sich , die Software mit Metaprogrammierungsansätzen zu entwerfen, und dies führt zu wichtigen Beschleunigungen. Sie können sich vorstellen, dass Ihr Programm bei bestimmten Eingaben dynamisch speziellen Code generiert, um ihn zu verarbeiten. Dies ist auch möglich , mit C oder C ++ (entweder einer JIT - Bibliothek, oder einen C - Code zu erzeugen, ist es als Plugin kompiliert , die dynamisch geladen werden).
Siehe auch diese verwandte Frage zu Python und das
quelle
Für Code wie
A = A + B
diesen können bis zu ein oder zwei Maschinenbefehle kompiliert werden, die jeweils eine bestimmte Anzahl von Zyklen benötigen. Kein Dolmetscher kann aus einem einfachen Grund in dieser Anzahl von Zyklen dasselbe tun.Der Interpreter führt auch einen eigenen Befehlssatz aus (nennt sie Byte-Codes, p-Codes, Zwischensprache, was auch immer). Jedes Mal, wenn es einen Byte-Code wie ADD sieht, muss es ihn irgendwie nachschlagen und zu dem Code verzweigen, der den Zusatz ausführt.
Wenn es das nächste Mal angezeigt wird, muss es diese Suche wiederholen , es sei denn, es kann sich an die vorherige Suche erinnern. Wenn es eine Möglichkeit gibt, sich an die vorherige Suche zu erinnern, handelt es sich nicht mehr um einen "Interpreter", sondern um einen Just-in-Time-Compiler oder JITter.
Auf der anderen Seite...
Für Code wie
callSomeFunction( ... some args ...)
, wie viele Zyklen werden zwischen der Eingabe und dem Verlassen des Codes verbracht? Es hängt alles davon ab, was im Inneren passiertcallSomeFunction
. Es könnten ein paar sein, und es könnten Billionen sein, selbst wenn siecallSomeFunction
selbst zusammengestellt sind. Wenn es viel ist, hat es keinen Sinn, die Interpretationskosten dieser Codezeile zu diskutieren - das Geld ist woanders.Denken Sie daran, dass interpretierte Sprachen einen eigenen Wert haben, z. B. dass sie nicht kompiliert werden müssen. (Die "Kompilierung" der Oberflächensyntax in Byte-Codes nimmt triviale Zeit in Anspruch. Nehmen Sie beispielsweise R oder MATLAB.)
Auch für intelligente Programmierebenen ist Flexibilität erforderlich. In Minskys Society of Mind , Kapitel 6.4 B- Brains, gibt es A-Programme, die sich mit der Welt befassen, und es gibt B-Programme, die sich mit A-Programmen befassen, und es kann weitere Ebenen geben. Programme, die andere Programme schreiben und verwalten, können in interpretierenden Systemen einfacher ausgeführt werden.
In Lisp können Sie schreiben
(+ A B)
, um A und B hinzuzufügen, aber sobald es geschrieben ist, haben Sie nur die Wahl, ob Sie es ausführen möchten oder nicht. Sie können auch schreiben,(eval (list '+ 'A 'B))
was das Programm erstellt und dann ausführt. Es könnte etwas anderes konstruieren.Das Thema des Programms ist ein anderes Programm . Dies ist einfacher in einer interpretierten Sprache zu schreiben (Jörg weist jedoch darauf hin, dass neuere Versionen von Lisp zwar im
eval
Handumdrehen kompiliert werden können, sie also nicht die Geschwindigkeitsstrafe eines Dolmetschers haben).quelle
eval
undapply
Funktionen, die Dolmetscher sind.eval
nicht interpretiert wird. Und das ist auch nichtapply
. Es gibt sicherlich Implementierungen, die Interpreter enthalten, SBCL jedoch nicht.eval
nicht interpretieren ed . Es ist eine Interpretation sich .Art, Art, es hängt davon ab, aber in der Regel ist die kompilierte Umgebung - sei es durch JIT oder statisch kompiliert - für viele rechenintensive Aufgaben schneller - aus Gründen der Einfachheit wird dieselbe Sprache vorausgesetzt.
Ein Grund dafür ist, dass für interpretierte Sprachen eine Interpreter-Schleife erforderlich ist. Diese Schleife liest eine Anweisung, wählt die entsprechende Aktion aus und führt sie aus. Im besten Fall wie bei der Interpretation von Python oder Java-Bytecode (wie es die alte JVM getan hat) hat es einen Overhead von wenigen Befehlen und hat mit Branch Predictor Chaos angerichtet. Sogar ein sehr dummer JIT sollte dies erheblich beschleunigen.
Das heißt, die interpretierte Sprache kann schummeln. Zum Beispiel hat Matlab optimierte Routinen für die Matrixmultiplikation und mit wenigen Änderungen können Sie Code auf der GPU zum Laufen bringen (Haftungsausschluss: Ich arbeite für nVidia - jede hier geäußerte Meinung ist meine und repräsentiert nicht die Ansicht meines Arbeitgebers). Auf diese Weise können Sie kurzen und leistungsfähigen Code auf höherer Ebene schreiben, ohne sich um Details zu kümmern. Jemand hat sich darum gekümmert und Zeit und Ressourcen in die Optimierung der Sprache auf niedriger Ebene gesteckt. Daran ist nichts vererbt und es verhindert beispielsweise nicht, dass Matlab den Code JIT, aber oft gibt es keinen Grund, da der Aufwand für das Aufrufen von Routinen auf hoher Ebene im Vergleich zu Zeiten auf niedriger Ebene minimal ist.
TL; DR - Die kompilierten Programme haben gegenüber den interpretierten enorme Leistungsvorteile (für den Vergleich von Äpfeln zu Äpfeln siehe PyPy Speed ). Die Geschwindigkeit der ausführbaren Datei ist jedoch nur ein Teil des Problems und trägt möglicherweise nicht wesentlich zur Gesamtgeschwindigkeit bei (wenn die meiste Zeit in Bibliotheken verbracht wird). Auch die Umsetzung ist wichtig.
quelle
Ihre Annahme ist begründet, obwohl es sich um eine Annahme handelt.
Ich werde nicht gehen die Gründe , warum über kompilierten Code sollte schneller als interpretted Code sein: wenn Sie wissen , wie Computer funktionieren, die offensichtlich sein wird. Die Differenz kann für bestimmte Arten von Problemen Größenordnungen betragen. Wenn Ihr Prüfer diesen allgemeinen Fall ernsthaft bestreitet, weiß er nicht, wovon er spricht.
Inwieweit sie einen Punkt haben, ist, ob der Unterschied in der Art der Anwendung, die Sie entwickeln, signifikant ist. Wenn es sich hauptsächlich um E / A-Vorgänge oder vorwiegend um den Aufruf kompilierter Bibliotheken handelt und nicht viel Rechenaufwand anfällt, kann der Aufwand für den Interpretationsprozess in der Tat unbedeutend sein.
Mein Beitrag lautet jedoch: Als IT-Experte werden Sie häufig aufgefordert, wichtige Entscheidungen zu treffen, die auf dem allgemeinen Wissen darüber beruhen, wie die Dinge funktionieren sollten. Wenn Sie einen bestimmten Test durchführen, erhalten Sie möglicherweise eine genauere Antwort. Dies kostet jedoch viel mehr und führt Sie nicht zuerst dorthin.
Aber von Zeit zu Zeit wird man erwischt. Es ist mir passiert. Sie treffen eine gute Annahme und stellen dann fest, dass Sie die Dummheit der Welt nicht berücksichtigt haben.
Aber ich kann meinen Lieblings-Dilbert-Cartoon aller Zeiten nicht so gut erklären. Nichts zeigt besser als dieses die Gefahren eines klugen Esels.
TL; DR: Sie sollten Recht haben, aber überprüfen Sie die reale Welt für alle Fälle.
quelle
Wenn Sie nicht etwas Exotisches verwenden, geht es bei Ihrem Problem nicht um die Leistung einer interpretierten Sprache A und einer kompilierten Sprache B.
Denn wenn Sie / Ihr Team A und nicht B kennen und so einen besseren Code in A als B schreiben, können Sie eine viel bessere Leistung in A als B erzielen Job, den Sie brauchen, bleiben Sie dabei.
Hier ist ein Link zu Regex in verschiedenen Sprachen. Sie werden feststellen, dass reguläre Ausdrücke in einigen Sprachen besser implementiert sind, auch wenn sie kompiliert wurden oder nicht: http://benchmarksgame.alioth.debian.org/u64q/performance.php?test=regexdna
quelle
Ich denke, es ist einfach keine gute Idee, über die Leistung von zwei Technologien zu sprechen, nur weil eine kompiliert und die andere interpretiert wird. Wie in anderen Antworten angegeben, kann dies vom Anwendungsbereich (einige Sprachen können optimiert werden, um bestimmte Vorgänge sehr schnell und andere langsamer auszuführen) sowie von der Erfahrung der Personen abhängen, die diese Technologie verwenden werden.
Ich glaube nicht, dass es vernünftig ist, zu erwarten, dass Sie eine Leistungssteigerung erzielen, wenn Sie einige hervorragend interpretierte Sprachcodierer verwenden und ihnen eine Technologie geben, mit der sie nicht vertraut sind - theoretisch kann letztere zu einer besseren Leistung führen, in der Realität jedoch. Ohne die erforderlichen Fähigkeiten und Erfahrungen werden Sie nicht alle Optimierungsmöglichkeiten nutzen.
Von einem der bekannten Mitarbeiter des Silicon Valley-Unternehmens habe ich auch gehört, dass sie die Sprache bevorzugen, die einfacher zu verwenden ist, da es teurer und mühsamer ist, einige erfahrene Entwickler zu bezahlen, um einen komplizierten, aber hoch optimierten Code zu warten, als nur zu kaufe mehr rig um mit der weniger effizienten umsetzung umzugehen, damit auch bei der auswahl der technik berücksichtigt werden sollte.
quelle
Einmal musste ich eine ähnliche pauschale Aussage machen, um eine große Entscheidung zu rechtfertigen.
Erstens möchten sie vielleicht keinem bescheidenen Ingenieur glauben, also habe ich einige vergleichbare Benchmark-Tests gefunden und zitiert. Es gibt viele von ihnen, von Menschen wie Microsoft oder renommierten Universitäten. Und sie werden Dinge sagen wie: Methode A ist zwischen 3 und 10 mal schneller als Methode B, abhängig von den Variablen X und Y.
Zweitens möchten Sie vielleicht einen eigenen Benchmark durchführen, vielleicht einen repräsentativen Teil des fraglichen Codes oder etwas Ähnliches, das Sie bereits haben. Führen Sie es 1000 Mal über Nacht aus, damit es wirklich einen messbaren Unterschied gibt.
An diesem Punkt sollte der Unterschied (oder das Fehlen davon) zwischen A und B so klar sein, dass Sie ihn nur präsentieren müssen. Formatieren Sie daher die Ergebnisse klar und möglichst mit Diagrammen, geben Sie alle Annahmen an und definieren Sie alle verwendeten Daten.
quelle
Ich würde argumentieren, dass jede dynamische Sprache einen Vorteil gegenüber statisch kompilierten hat: "Laufzeitoptimierungen"
Dies ist einer der Gründe, warum Java schneller sein kann als C ++
Ja, das Laden einer dynamisch getippten Sprache ist immer mit Übersetzungskosten verbunden und mit Nachteilen verbunden. Sobald es ausgeführt wird, kann der Interpreter häufige Codepfade mit Laufzeitinformationen profilieren und erweitern, die statische Sprachen niemals haben werden
HINWEIS: Nun, Java ist eine interpretierte Sprache, keine dynamische. Aber es ist ein großartiges Beispiel dafür, was Sie mit Laufzeitinformationen beschleunigen können
quelle
Das wäre mein Ansatz:
Im Allgemeinen werden Dolmetscher kompiliert, sodass jede interpretierte Technologie nichts anderes als eine kompilierte Technologie ist, wenn sie auf einer niedrigen Ebene betrachtet wird. Daher sind kompilierte Technologien einfach mehr und mit mehr Möglichkeiten kann man nie schlechter werden, wenn man schlau ist (was man im Allgemeinen ist). Es hängt davon ab, wie viele Informationen zur Kompilierungszeit verfügbar sind und wie viele Informationen nur zur Laufzeit verfügbar sind und wie gut die Compiler und Interpreter sind. Theoretisch sollte es jedoch immer möglich sein, die Leistung eines Interpreters mit einem geeigneten Compiler mindestens gleichzusetzen. nur weil Dolmetscher von Compilern hergestellt werden. Das ist möglich, heißt aber nicht, dass es bei Ihren Technikern A und B der Fall ist.
In der Praxis teilen Sie dem Prüfer einfach alle verfügbaren Benchmarks mit, bei denen kompilierte und interpretierte Systeme verglichen werden. Bitten Sie ihn dann, einen Interpreter vorzuschlagen, der Ihren optimierten Assembly-codierten spezifischen Algorithmus übertrifft.
Man sollte vielleicht hinzufügen, dass eine solche allgemeine Aussage beim Vergleich zweier spezifischer Techniken A und B überhaupt nicht hilft. Dort ist die Wahl von A und B viel wichtiger, als wenn sie interpretiert oder kompiliert werden.
quelle