it-swarm-eu.dev

Warum wird JavaScript vor dem Senden über das Netzwerk nicht zu Bytecode kompiliert?

Man würde oft sehen, dass JavaScript tatsächlich mit all den nutzlosen Dingen, die nicht vorhanden sein müssen, über das Web transportiert wird - Kommentare, insbesondere solche, die Lizenzen enthalten, Einrückungen ( '\ t' , '\ n' ) usw. Bei genügend Zeit kann es sein, dass weltweit Terabyte an Daten verschwendet werden! Würde ein JavaScript-Bytecode ein weiteres größeres Problem verursachen, oder hat noch niemand daran gedacht?

155
Vivek Yadav

Warum wird JavaScript vor dem Senden über das Netzwerk nicht zu Bytecode kompiliert?

Hintergrund: Ich war Ende der neunziger Jahre Mitglied des technischen Komitees von ECMAScript und einer der Implementierer der JScript-Engine von Microsoft.

Lassen Sie mich zunächst sagen, was ich immer sage, wenn ich mit einem "Warum nicht?" Frage: Sprachdesigner müssen keine guten Gründe angeben, warum sie nicht Hunderte Millionen Dollar anderer Leute für eine Funktion ausgegeben haben, die zufällig jemandem gefällt. Vielmehr muss die Person, die die Funktion aufstellt, gute Gründe angeben, warum dies der beste Weg ist, um diese Zeit, Mühe und Geld zu verbringen. Sie haben ein Argument ohne Zahlen angeführt, dass Bytecode eine Kostenersparnis in Bezug auf die Bandbreite bedeuten würde. Ich möchte Sie ermutigen, einige tatsächliche Zahlen zu ermitteln und diese mit den Kosten für die Erstellung einer weiteren Sprache zu vergleichen. Diese Kosten sind erheblich. Denken Sie in Ihrer Analyse daran, dass "Implementierung" einer der geringsten Kosten ist. Zu Ihrer Analyse gehört auch, wer spart das Geld gegen wen ausgibt das Geld, und Sie werden feststellen, dass die Leute, die das Geld ausgeben, nicht diejenigen sind, die es sparen; Anreize sind wichtig.

Das heißt, dies ist eines der vernünftigeren "warum nicht?" Fragen, weil es eine Funktion ist, die wir aus Gründen in Betracht gezogen und abgelehnt haben.

Wir haben ein solches Schema sowohl innerhalb von Microsoft als auch auf TC-Ebene in Betracht gezogen. Da JScript bereits als Kompilierung in eine gut gestaltete, prinzipielle Bytecode-Sprache implementiert wurde, wäre es für uns unkompliziert gewesen, es als Standard vorzuschlagen, und wir haben dies in Erwägung gezogen.

Wir haben uns aus verschiedenen Gründen dagegen entschieden, darunter:

  • Heilige Güte, es war schwer genug, JavaScript zu standardisieren. Jeder und sein Hund würden eine Meinung darüber haben, was die idealen Eigenschaften einer Bytecode-Sprache sind, und es würde mehrere Jahre Bikeshedding geben. Niemand wollte wirklich dorthin gehen.
  • Es war eine teure Lösung ohne damit verbundene kostspielige Probleme. Es gibt keinen Grund anzunehmen, dass eine Bytecode-Sprache in Bezug auf Größe oder Geschwindigkeit effizienter ist. JavaScript minimiert bereits einigermaßen gut und ist stark komprimierbar.
  • Dies hätte eine enorme Menge an Arbeit für Browser-Anbieter verursacht, die bereits über die Kosten für die Erstellung einer effizienten, konformen JS-Implementierung geärgert waren.
  • Es ist schwierig genug, eine sichere JS-Implementierung zu erstellen, die Angriffen durch schlechte Akteure widersteht. sollten wir die für Angriffe verfügbare Fläche verdoppeln? Wahrscheinlich nicht.
  • Standards sind ein Hindernis für Innovationen. Wenn wir feststellen würden, dass eine kleine Änderung unserer Bytecode-Sprache in einem zuvor unvorhergesehenen oder zuvor unwichtigen Benutzerszenario einen großen Unterschied bewirken würde, konnten wir dies tun Veränderung. Wenn es ein Standard wäre, wäre es uns nicht frei, diesen Nutzervorteil zu schaffen.

Diese Analyse setzt jedoch voraus, dass der Grund für die Ausführung der Funktion überhaupt die Leistung ist. Interessanterweise ging es bei den Kundenanfragen, die in den neunziger Jahren zu dieser Funktion motiviert waren, nicht in erster Linie um Leistung.

Warum nicht? Die neunziger Jahre waren für JS eine ganz andere Zeit als heute; Skripte waren meistens winzig. Die Vorstellung, dass es eines Tages Frameworks mit Hunderttausenden von Linien geben würde, war nicht einmal annähernd auf unserem Radar. Das Herunterladen und Parsen von JS war ein winziger Bruchteil der Zeit, die zum Herunterladen und Parsen von HTML aufgewendet wurde.

Die Motivation war auch nicht die Erweiterung auf andere Sprachen, obwohl dies für Microsoft von Interesse war, da VBScript auch im Browser ausgeführt wurde, der eine sehr ähnliche Bytecode-Sprache verwendete. (Wird von demselben Team entwickelt und aus denselben Quellen und allen zusammengestellt.)

Das primäre Kundenszenario für die Motivierung von Bytecode im Browser bestand vielmehr darin, das Lesen, Verstehen, Dekompilieren, Reverse Engineering und Manipulieren des Codes zu erschweren. Dass eine Bytecode-Sprache für einen Angreifer mit angemessenen Ressourcen kaum zusätzliche Arbeit zu verstehen ist, war ein wichtiger Punkt gegen diese Arbeit; wir wollten kein falsches Sicherheitsgefühl schaffen.

Grundsätzlich gab es viele Ausgaben und nur wenige Vorteile, so dass es nicht erledigt wurde. Zwischen 1998 und 2015 muss sich etwas geändert haben, das WebAssembly zu einem angemessenen Preis-Leistungs-Verhältnis geführt hat. Was diese Faktoren sind, weiß ich nicht. Sie müssten einen Experten für WebAssembly fragen.

381
Eric Lippert

Quelltext anzeigen

"View Source" war am Anfang und wird bis zu einem gewissen Grad immer noch als wichtiges Merkmal des Webs angesehen. Auf diese Weise haben Generationen von Webentwicklern die Webentwicklung gelernt, und die zuständigen Normungsgremien (ECMA TC39, W3C, WHATWG) nehmen dies immer noch sehr ernst.

Minimierung

ECMAScript-Dateien werden normalerweise vor der Bereitstellung "minimiert". Dies umfasst das Entfernen aller Kommentare, aller Leerzeichen und das Umbenennen aller Bezeichner, um sie so kurz wie möglich zu halten, sowie einige übergeordnete Optimierungen wie das Entfernen von totem Code.

Kompression

Die Komprimierung wird in HTTP seit HTTP/1.0 (Anfang 1996) unterstützt. ECMAScript ist Text und Text wird sehr gut komprimiert. In der Tat ist ECMAScript Text mit vielen Redundanzen (viele Erscheinungen von ;, {, }, (, ), ,, ., function, var, if, for usw.) und Komprimierungsalgorithmen leben von Redundanz. Die übertragene Datenmenge ist also viel geringer, als Sie sich vorstellen. Versuchen Sie als Experiment, eine ECMAScript-Quelldatei mit einem der typischen im Web verwendeten Komprimierungsalgorithmen (z. B. gzip oder deflate) zu komprimieren, und vergleichen Sie diese mit der Größe des kompilierten Bytecodes derselben Datei.

Bytecode-Format

Damit kommen wir zum nächsten Problem: Es gibt kein standardisiertes Bytecode-Format für ECMAscript. Tatsächlich verwenden einige Implementierungen möglicherweise überhaupt keinen Bytecode! In den ersten Jahren hat V8 beispielsweise ECMAScript direkt in nativen Maschinencode kompiliert, ohne dazwischen einen Bytecode-Schritt. Chakra, SquirrelFish Extreme und SpiderMonkey verwenden alle Bytecode, aber sie verwenden unterschiedliche Bytecodes. dyn.js, TruffleJS, Nashorn und Rhine verwenden keinen ECMAScript-spezifischen Bytecode, sondern kompilieren zu JVML-Bytecode. Ebenso kompiliert IronJS zum CLI CIL-Bytecode.

Nun könnte man sagen: Warum nicht define ein standardisiertes Bytecode-Format für ECMAScript? Die Probleme dabei sind zweifach:

  1. Ein Bytecode-Format schränkt das Design der Ausführungs-Engine ein. Schauen Sie sich zum Beispiel JVMs an: JVMs sind einander viel ähnlicher als ECMAScript-Engines. Persönlich glaube ich, dass das "Performance Race" der späten 2000er/frühen 2010er Jahre ohne das breite Spektrum an Experimenten, das das Fehlen eines standardisierten Bytecode-Formats ermöglichte, nicht möglich gewesen wäre.

  2. Es ist nicht nur schwierig, alle Anbieter von ECMAScript-Engines dazu zu bringen, sich auf ein gemeinsames standardisiertes Bytecode-Format zu einigen, sondern auch Folgendes: Es ist nicht sinnvoll, dem Browser ein Bytecode-Format für nur ECMAScript hinzuzufügen . Wenn Sie ein allgemeines Bytecode-Format verwenden, wäre es schön, wenn es auch ActionScript, VBScript, Python, Ruby, Perl, Lua, PHP usw. unterstützen würde. Aber jetzt haben Sie das gleiche Problem wie in # 1, außer dass es exponentiell zugenommen hat: Nicht nur alle Anbieter von ECMAScript-Engines müssen sich auf ein gemeinsames Bytecode-Format einigen, sondern Sie müssen auch PHP, Perl, Ruby, Python, Lua usw. erwerben. Gemeinschaften auch zuzustimmen!

Caching

Bekannte, weit verbreitete Bibliotheken werden an kanonischen URIs gehostet, auf die von mehreren Sites aus verwiesen werden kann. Daher müssen sie nur einmal heruntergeladen werden und können clientseitig zwischengespeichert werden.

CDN

Viele Bibliotheken verwenden CDNs, sodass sie tatsächlich von einem Ort in der Nähe des Benutzers aus bedient werden.

Wasm/asm.js.

WebAssembly (Wasm) ist ein kompaktes binäres Befehlsformat, das derzeit vom W3C standardisiert und bereits in Firefox, Chrome, Safari und Edge ausgeliefert wird. Es ist jedoch nicht als Bytecode-Format für ECMAScript konzipiert, sondern als tragbares Maschinencode- und Kompilierungsziel auf niedriger Ebene für Sprachen wie C, C++ und Rust.

Vor Wasm gab es bereits asm.js, die ähnliche Ziele hatten, aber als syntaktische und semantische Teilmenge von ECMAScript konzipiert wurden, sodass Sie es unverändert in einer nicht asm.js-fähigen Engine ausführen konnten und es einfach funktionieren würde viel langsamer.

114
Jörg W Mittag

JavaScript wurde von Netscape erfunden. Das Designziel war es, Webseiten durch eine eingebettete Skriptsprache interaktiv zu gestalten. Es war ursprünglich nicht für komplexe Anwendungen gedacht - komplexe Inhalte sollten als Java Applets oder Plug-Ins) geschrieben werden, und JavaScript wurde als einfacher "Kleber" -Code positioniert, der HTML-Elemente mit = verbinden konnte Java Applets und andere skriptfähige Plug-Ins.

JavaScript wurde so konzipiert, dass es direkt in HTML eingebettet wird, wie z. B. <input type="button" onclick="alert('hello world')">. Heutzutage ist es verpönt, JavaScript in HTML einzubetten, aber in jenen Tagen war dies die Standardmethode, um Ereignishandler anzuschließen. In diesem Anwendungsfall musste JavaScript grundsätzlich textbasiert sein.

Es gab auch Möglichkeiten zum Generieren von HTML in JavaScript, wie zum Beispiel:

<script>
  document.write("<input type=\"button\" onclick=\"alert('hello world')\">"
</script>

Dies setzt wiederum voraus, dass JavaScript im Textformat vorliegt, um nützlich zu sein.

Darüber hinaus ist ein Textformat für Gelegenheitsentwickler viel einfacher, da Sie keine Entwicklungsumgebung benötigen, um es in Bytecode zu kompilieren. Geben Sie einfach den Text ein und laden Sie den Browser neu, damit er ausgeführt wird. Zum Zeitpunkt der Einführung von JavaScript gab es kaum dedizierte HTML-Editoren. Die Leute haben Webseiten im Notizblock geschrieben. Es gab keine Pipelines für Webseiten.

Die Nachteile, die Sie erwähnen, waren zu dieser Zeit nicht wirklich eine Überlegung. Da es für kleine Skripte konzipiert wurde, war der Aufwand für ein Textformat völlig unbedeutend.

18
JacquesB

Die Datennutzung ist wahrscheinlich kein Problem.

Um auf die Annahme im Körper zu antworten (seit dem wunderbaren Antwort von Eric Lippert scheinen die eigentlichen Fragen ziemlich gut abgedeckt zu sein):

Unabhängig davon, ob es sich um Datenbeschränkungen oder Bandbreite handelt, konnte mein Google-Fu keine Untersuchungen aufdecken, die darauf hindeuten, dass Javascript tatsächlich "Terabyte an Daten verschwendet" (was auch immer das bedeutet).

Was den Rest Ihrer Fragen betrifft, ist es in vielen Dingen weniger nützlich zu fragen: "Welche Probleme wird dies verursachen?" als zuerst zu fragen "welche Vorteile wird dies schaffen?".

1
sp88