web-dev-qa-db-ja.com

JavaScriptがネットワーク経由で送信する前にバイトコードにコンパイルされないのはなぜですか?

JavaScriptが実際にWeb経由で転送され、そこにある必要のないすべての不要なものが含まれていることがよくあります-コメント、特にライセンスを含むもの、インデント '\ t' '\ n')など。十分な時間が与えられると、テラバイト単位のデータが世界中で無駄になる可能性があります。 JavaScriptバイトコードは別の大きな問題を引き起こすのでしょうか、それともまだ誰もこれについて考えていませんか?

155
Vivek Yadav

JavaScriptがネットワーク経由で送信する前にバイトコードにコンパイルされないのはなぜですか?

背景:1990年代後半にECMAScript技術委員会に所属し、MicrosoftのJScriptエンジンの実装者の1人でした。

まず、「どうして?」と直面したときにいつも言うことから始めましょう。質問:言語デザイナーは、誰かがたまたま気に入った機能に何億ドルもの人のお金を費やさなかった理由を示す必要はありません。むしろ、その機能を売り込む人は、それがその時間、労力、お金を費やす最善の方法である理由を説明する必要があります。数字を付けずに、バイトコードは帯域幅の面でコスト削減になるという議論をしました。実際の数値を調べて、さらに別の言語を作成するコストと比較することをお勧めします。これらのコストは重要です。分析では、「実装」は最小のコストの1つであることを忘れないでください。また、分析には誰がお金を節約するかとだれを使うかを含める、そしてあなたはお金を使う人々がそれを節約する人ではないことがわかるでしょう。インセンティブが重要です。

とはいえ、これはより合理的な「理由」の1つです。これは、私たちが検討し、理由により拒否した機能であるためです。

マイクロソフト内とTCレベルの両方で、このようなスキームを検討しました。 JScriptは、適切に設計された原則的なバイトコード言語にコンパイルするように既に実装されているため、標準として提案するのは簡単で、そうすることを検討しました。

私たちは、次のようなさまざまな理由から、そうしないことにしました。

  • JavaScriptを標準化するのは十分に困難でした。みんなと彼らの犬は、バイトコード言語の理想的な特性が何であるかについて意見を持っているでしょう、そしてそれは何年ものバイクシェディングであるでしょう。誰もそこに行きたくなかった。
  • これは、関連するコストのかかる問題のない高価なソリューションでした。サイズや速度のいずれかでバイトコード言語がより効率的であると仮定する理由はありません。 JavaScriptは既にかなり適切に圧縮されており、非常に圧縮可能です。
  • それは、効率的で準拠したJS実装を作成する費用にすでに悩まされていたブラウザープロバイダーにとって、膨大な量の作業を生み出していたでしょう。
  • 悪意のある人物による攻撃に抵抗する安全なJS実装を作成することは十分に困難です。攻撃に利用できる表面積を2倍にする必要がありますか?おそらく違います。
  • 標準はイノベーションの障害です。バイトコード言語に小さな変更を加えると、以前には予期していなかった、または以前には重要でなかったいくつかの点で大きな違いが生じることがわかった場合ユーザーシナリオでは、自由に変更できます。それが標準だったとしたら、私たちはそのユーザーの利益を自由に生み出すことはできません。

しかし、その分析は、機能を実行する理由がパフォーマンスであることを前提としています。興味深いことに、1990年代にこの機能を検討する動機となった顧客の要求は、主にパフォーマンスに関するものではありませんでした。

何故なの? 1990年代は、JSにとって今日とは非常に異なる時期でした。スクリプトはほとんどが小さなものでした。いつの日か何十万ものラインを持つフレームワークが存在するという考えは、私たちのレーダーにいることすらありませんでした。 JSのダウンロードと解析は、HTMLのダウンロードと解析に費やした時間のごく一部でした。

他の言語への拡張の動機もありませんでしたが、非常によく似たバイトコード言語を使用するブラウザーでVBScriptを実行していたので、Microsoftにとっても興味がありました。 (同じチームによって開発され、同じソースおよびすべてからコンパイルされています。)

むしろ、ブラウザでバイトコードを動機付ける主な顧客シナリオは、コードを読みにくくし、理解し、逆コンパイルし、リバースエンジニアリングし、改ざんすることを難しくすることでした。 バイトコード言語は、合理的なリソースを持つ攻撃者が理解する必要のある追加の作業ではないということは、この作業を行うことに対する主要なポイントでした。私たちは誤った安心感を作りたくありませんでした。

基本的には費用が多くてメリットが少ないので、うまくいきませんでした。 1998年から2015年の間に、WebAssemblyに妥当な価格対効果をもたらした変更があったに違いありません。それらの要因が何であるか、私は知りません。 WebAssemblyの専門家に依頼する必要があります。

381
Eric Lippert

ソースを表示

「ソースの表示」は最初にありましたが、それでもある程度は、Webの重要な機能であると考えられています。これは、何世代にもわたるWeb開発者がWeb開発を学び、関連する標準化団体(ECMA TC39、W3C、WHATWG)がそれを非常に真剣に受け止めている方法です。

縮小

ECMAScriptファイルは通常、展開前に「縮小」されます。これには、すべてのコメントの削除、すべての空白、およびすべての識別子の名前を可能な限り短くするための名前変更に加えて、デッドコードの削除などのいくつかの高レベルの最適化が含まれます。

圧縮

HTTP/1.0(1996年初頭)以降、圧縮のサポートはHTTPに存在します。 ECMAScriptはテキストであり、テキストは非常によく圧縮されます。実際、ECMAScriptは多くの冗長性(たくさんの;{}(),.functionvarifforなど)、および圧縮アルゴリズムは冗長性で成功します。そのため、転送されるデータの量は、実際よりもはるかに少なくなります。実験として、Webで使用されている一般的な圧縮アルゴリズム(gzipやdeflateなど)の1つでECMAScriptソースファイルを圧縮し、それを同じファイルのコンパイル済みバイトコードのサイズと比較してみてください。

バイトコード形式

これが次の問題につながります。ECMAscriptには標準化されたバイトコード形式がありません。実際、実装によってはバイトコードをまったく使用しない場合もあります。たとえば、最初の数年間、V8はECMAScriptをネイティブマシンコードに直接コンパイルしましたが、間にバイトコードのステップはありませんでした。 Chakra、SquirrelFish Extreme、SpiderMonkeyはすべてバイトコードを使用しますが、使用するバイトコードは異なります。 dyn.js、TruffleJS、Nashorn、およびRhineはECMAScript固有のバイトコードを使用せず、JVMLバイトコードにコンパイルします。同様に、IronJSはCLI CILバイトコードにコンパイルされます。

さて、あなたは言うかもしれません:なぜECMAScriptの標準化されたバイトコード形式をdefineしないのですか?これに関する問題は2つあります。

  1. バイトコード形式は、実行エンジンの設計を制約します。たとえば、JVMを見てください。JVMはECMAScriptエンジンよりもはるかに似ています。個人的には、2000年代後半/ 2010年代初頭の「パフォーマンスレース」は、標準化されたバイトコード形式の欠如によってもたらされた幅広い実験なしには不可能だったと思います。

  2. すべてのECMAScriptエンジンベンダーが共通の標準化されたバイトコード形式に同意するのを困難にするだけでなく、これを考慮してください。onlyECMAScriptにバイトコード形式を追加することは意味がありませんブラウザに。 もし一般的なバイトコード形式を使用する場合、ActionScript、VBScript、Python、Ruby、Perl、Lua、PHPなどもサポートしているといいでしょう。しかし、指数関数的に増加することを除いて、#1と同じ問題があります。すべてのECMAScriptエンジンベンダーが共通のバイトコード形式に同意する必要があるだけでなく、PHP、Perl、Ruby、Python、Luaなども取得する必要があります。コミュニティも同意する!

キャッシング

広く使用されている有名なライブラリは、正規のURIでホストされており、複数のサイトから参照できます。したがって、それらは一度ダウンロードするだけでよく、クライアント側にキャッシュできます。

CDN

多くのライブラリはCDNを使用しているため、実際にはユーザーの近くの場所から提供されます。

Wasm/asm.js

WebAssembly(Wasm) は、現在W3Cによって標準化されており、Firefox、Chrome、Safari、およびEdgeですでに出荷されているコンパクトなバイナリ命令フォーマットです。ただし、ECMAScriptのバイトコード形式としては設計されておらず、低レベルのポータブルマシンコードおよびC、C++、Rustなどの言語のコンパイルターゲットとして設計されています。

Wasmの前には、同じような目標を持つasm.jsがすでにありましたが、それはECMAScriptの構文的および意味的なサブセットとして設計されたので、asm.jsに対応していないエンジンで変更せずに実行でき、動作しました。はるかに遅い。

114
Jörg W Mittag

JavaScriptはNetscapeによって発明されました。設計目標は、埋め込みスクリプト言語を使用してWebページをインタラクティブにすることでした。最初は複雑なアプリケーションを対象としていませんでした-複雑なものはJavaアプレットまたはプラグインとして記述されることになっており、JavaScriptはHTML要素を=で接続できる単純な「接着」コードとして配置されていましたJavaアプレットおよびその他のスクリプト可能なプラグイン。

JavaScriptは、<input type="button" onclick="alert('hello world')">のように、HTMLに直接埋め込まれるように設計されています。最近ではJavaScriptをHTMLに埋め込むことはお勧めできませんが、当時はこれがイベントハンドラーをフックする標準的な方法でした。この使用例では、JavaScriptは基本的にテキストベースである必要がありました。

JavaScriptでHTMLを生成するための機能もありました。

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

繰り返しますが、これは基本的にJavaScriptがテキスト形式であることが有用であることを必要とします。

さらに、テキスト形式は、それをバイトコードにコンパイルするための開発環境を必要としないため、カジュアルな開発者にとってmuchより簡単です。テキストを入力してブラウザをリロードするだけで実行されます。 JavaScriptが導入された当時、専用のHTMLエディターはほとんど存在していませんでした。人々はメモ帳でウェブページを書いた。 Webページのパイプラインを構築するようなものはありませんでした。

あなたが言及する不利な点は、当時は本当に考慮事項ではありませんでした。小さなスクリプト用に設計されているため、テキスト形式のオーバーヘッドはまったく取るに足りません。

18
JacquesB

データの使用はおそらく実際には問題ではありません。

本文の仮定に応答するには(すばらしい Eric Lippertによる応答 が実際の質問をかなりカバーしているように見えるため):

データの上限と帯域幅のどちらを話しているにせよ、私のGoogle-Fuは、Javascriptが実際に「テラバイトのデータを浪費している」ことを示唆する研究を発掘できませんでした(それが何であれ)。

残りの質問については、多くの場合、「これによりどのような問題が発生するのですか?」最初に「これによりどのようなメリットがもたらされるのか」と尋ねるよりも。

1
sp88