web-dev-qa-db-ja.com

Javascriptエンジンの利点

私は今、JavaScriptエンジンについて混乱しています。 JavaScriptをネイティブコードにコンパイルしたため、 V8 が大したことを知っています。

それから Mozilla SpiderMonkey について読み始めました。これは私が理解していることからCで書かれており、JavaScriptをコンパイルできます。では、これはV8とどのように違うのですか?これが本当なら、なぜFirefoxはこれをしないのですか?

最後に、 Rhino JavaScriptを文字通りJavaバイトコードにコンパイルするので、Javaの速度の利点をすべて得ることができますか?デスクトップ上のスクリプト?

57
Jan

JITを実行する場合でも、JavaScript実行にはさまざまなアプローチがあります。 V8とNitro(以前はSquirrelFish Extremeとして知られていました)は、メソッド全体のJITを実行することを選択しました。つまり、スクリプトに遭遇したときにすべてのJavaScriptコードをネイティブ命令にコンパイルし、それを単にCコードがコンパイルされたように実行します。 SpiderMonkeyは代わりに「トレース」JITを使用します。最初にスクリプトをバイトコードにコンパイルして解釈しますが、実行を監視し、ループなどの「ホットスポット」を探します。それを検出すると、そのホットパスだけをマシンコードにコンパイルし、将来的に実行します。

どちらのアプローチにも長所と短所があります。メソッド全体のJITは、実行されるすべてのJavaScriptがコンパイルされ、マシンコードとして実行され、解釈されないことを保証します。これは一般に高速です。ただし、実装によっては、エンジンが実行されることのないコードのコンパイルに時間を費やすことを意味する場合があります。さらに、このコンパイルされたコードはメモリに保存する必要があるため、メモリ使用量が増加する可能性があります。

SpiderMonkeyに実装されているトレースJITは、メソッド全体のJITと比較して非常に特殊なコードを生成できます。これは、コードを既に実行し、変数の種類を推測できるためです(forループのインデックス変数をネイティブ整数として扱うなど) )では、JavaScriptが型指定されていないため型が変更される可能性があるため、メソッド全体のJITは変数をオブジェクトとして扱う必要があります(SpiderMonkeyは、仮定が失敗した場合にトレースを「フォールオフ」し、バイトコードの解釈に戻ります)。ただし、SpiderMonkeyのトレースJITは、現在、トレースが単一の実行パスに対して最適化されているため、多くのブランチを持つコードでは効率的に機能しません。さらに、トレースをコンパイルすることを決定し、実行をそのトレースに切り替える前に、実行の監視に伴うオーバーヘッドがあります。また、トレーサーが後で違反する仮定(変数の変更タイプなど)を行う場合、トレースから落ちて解釈に戻るコストは、メソッド全体のJITよりも高くなる可能性があります。

79
Ted Mielczarek

V8は、すべてのJSをマシンコードにコンパイルするため、最速です。

SpiderMonkey(FFが使用するもの)も高速ですが、マシンコードではなく、中間バイトコードにコンパイルされます。これがV8との大きな違いです。編集-新しいFirefoxリリースには、SpideMonkeyの新しいバリアントが付属しています。 TraceMonkey。 TraceMonkeyは、重要な部分のJITコンパイル、およびその他のスマートな最適化を行います。

RhinoはJavascriptをJavaクラスにコンパイルします。したがって、基本的にJavascriptで「Java」アプリケーションを作成できます。Rhinoは、バックエンドでJSを解釈し、それを操作し、完全なコードを作成する方法としても使用されますリフレクションなどの理解これは、たとえばYUI Compressorによって使用されます。

至る所でV8の代わりにRhinoが使用される理由は、おそらくV8が比較的新しいためです。そのため、多くのプロジェクトがすでにYahooウィジェットなどのJSエンジンとしてRhino/Spidermonkeyを使用しています。 (私はそれが「デスクトップ上のスクリプト」であなたが言及しているものだと思います)

edit-このリンクは、SpiderMonkeyが広く採用されている理由についての洞察を与えるかもしれません。 アプリケーションに埋め込むJavascriptエンジンはどれですか?

12
adamJLev

ブラウザ内のさまざまなJavascriptエンジンがどのように積み重なっているかを確認するには、Safari 4をインストールします(Windowsでも実行されます!)、Chrome V8、Firefox 3.5、およびIE 8(Windowsを使用している場合)およびベンチマークを実行します。

http://www2.webkit.org/perf/sunspider-0.9/sunspider.html

先ほどPointyが言ったように、新しいFirefox 3.5はTraceMonkeyを使用しています。TraceMonkeyは、何らかの形のJITを使用してオンザフライでコードを編集します。そのため、V8と比較していくぶん有利になります。少なくとも、Firefox 3 SpiderMonkey(JITなし)のようにV8よりも10倍遅くなることはありません。

私にとって... safari 4.0.3は、Win XP上のFirefox 3.5.3のTracemonkyよりも2.5倍高速でした。 IE8ははるかに低速でした。現時点ではChromeをインストールしていません。

RhinoのJavaバイトコードへのコンパイルについては知りません。実行時にオブジェクトインスタンスに属性を追加できるなど、Javascriptの動的機能をまだ解釈している場合(例obj.someNewAttribute = "someValue" Javascriptで許可されています)...それがバイトコードに完全に「コンパイル」されているかどうかはわかりませんが、JavascriptソースコードテキストからJavascriptをコンパイルする必要がない限り、パフォーマンスが向上しない可能性がありますJavascriptはeval( "x = 10; y = 20; z = x * y");などの非常に動的な構文を許可することを忘れないでください。これは、実行時にコンパイルされるコードの文字列を構築できることを意味します。 JVMバイトコードにコンパイルした場合でも、Rhinoは混合モードで解釈/コンパイルされると思います。

JVMは、JITサポートを備えた非常に優れたものではありますが、依然としてインタープリターです。だから、Rhino-on-JVMを2つのインタープリターレイヤー(インタープリターオンインタープリター)またはインタープリター^ 2と考えるのが好きです。他のJavascriptエンジンのほとんどはCで記述されているため、インタープリター^ 1のように動作するはずです。各インタープリターレイヤーは、CまたはC++と比較して5〜10倍のパフォーマンスの低下を追加できます(PerlまたはPythonまたはRubyなど)を参照)。ヒットは2〜4倍のオーダーではるかに低く、JVMはこれまでで最も堅牢で成熟したJITエンジンの1つを備えています。

したがって、マイレージは間違いなく異なります。自分のハードウェアとOSで目的のアプリケーションに本当の答えが必要な場合は、いくつかの深刻なベンチマークを行うことで利益を得られるでしょう。

多くの人がRhinoを使用していることを知っているので、Rhinoはそれほど遅くなることはありません。私はそれが主な魅力はその速度ではないが、Javaライブラリへのフックを備えた、コーディングが簡単/軽量/埋め込み可能/インタープリタであり、スクリプト作成に最適であるという事実ソフトウェアプロジェクトの/configuration/extensibility。UltraEditのような一部のテキストエディターは、Javascriptを代替マクロスクリプトエンジンとして埋め込みさえしています。すべてのプログラマーは、javascriptを簡単につまずくことができるため、簡単に手に入れることができます。

Rhinoの利点の1つは、JVMが実行されるほとんどどこでも実行できることです。私の経験では、スタンドアロンのTraceMonkeyまたはSpiderMonkeyを取得してコマンドラインからビルドおよび実行しようとすると、Windowsなどのシステムで少し苦痛になることがあります。また、独自のアプリケーションへの埋め込みにはさらに時間がかかる場合があります。しかし、埋め込み可能な言語を使用することに対する見返りは、大きなプロジェクトにとっては価値があります。それがあなたが望んでいるのであれば、「独自の」ミニスクリプティングソリューションを作成する必要があるのと比較して。

Javaとrhino jarがあれば、javascriptを作成してコマンドラインから実行するだけで、Rhinoでのスクリプト作成は非常に簡単です。単純なタスクには常に使用しています。

6
linguanerd

質問に答えるために、なぜネイティブコード対バイトコード...

ネイティブコードはより高速であり、Googleにとっては少なくとも1つがChromeOSであるJSを計画しているため、戦略的な選択です。

この質問に関する優れたビデオがChannel9に投稿されており、V8の背後にいる男性を見つけることができるLars Bakのインタビューが掲載されています here

3
Zied