web-dev-qa-db-ja.com

ブラウザはページを読み込むたびにJavaScriptを解析しますか?

ブラウザ(IEおよびFirefox)は、ページが更新されるたびに、リンクされたJavaScriptファイルを解析しますか?

彼らはファイルをキャッシュすることができるので、毎回それらをダウンロードしようとはしないと思いますが、各ページは本質的に別個なので、古いコードを破棄して再解析することを期待しています。

これは非効率的ですが、完全に理解できますが、最新のブラウザはサイト内の解析ステップを回避するのに十分賢いのではないかと思います。サイトでExtJSやjQueryなどのjavascriptライブラリを使用する場合を考えています。

185
Steve Jones

これらは私が掘り下げた詳細です。 JavaScriptは通常、VMで解釈され実行されると考えられていますが、ソースをマシンコードに直接コンパイルする傾向のある最新のインタープリター(IEを除く)には当てはまらないことに注意してください。


Chrome:V8 Engine

V8にはコンパイルキャッシュがあります。これは、最大5つのガベージコレクションのソースのハッシュを使用して、コンパイルされたJavaScriptを保存します。これは、2つの同一のソースコードが、どのように含まれているかに関係なく、メモリ内のキャッシュエントリを共有することを意味します。このキャッシュは、ページがリロードされてもクリアされません。

ソース


更新-2015年3月19日

Chromeチームはリリースしました JavaScriptストリーミングとキャッシングのための新しいテクニックの詳細

  1. スクリプトストリーミング

スクリプトストリーミングは、JavaScriptファイルの解析を最適化します。 [...]

バージョン41以降、Chromeは、ダウンロードが開始されるとすぐに、非同期スクリプトと遅延スクリプトを別のスレッドで解析します。これは、ダウンロードが完了してから数ミリ秒で解析が完了し、ページが表示されることを意味します読み込みが最大10%速くなります。

  1. コードキャッシング

通常、V8エンジンは訪問のたびにページのJavaScriptをコンパイルし、プロセッサーが理解できる命令に変換します。コンパイルされたコードはコンパイル時のマシンの状態とコンテキストに大きく依存するため、ユーザーがページから離れると、このコンパイルされたコードは破棄されます。

Chrome 42では、コンパイルされたコードのローカルコピーを保存する高度な技術が導入されているため、ユーザーがページに戻ったときに、ダウンロード、解析、コンパイルのステップをすべてスキップできます。すべてのページの読み込みで、これによりChromeがコンパイル時間の約40%を回避し、モバイルデバイスの貴重なバッテリーを節約できます。


オペラ:カラカンエンジン

実際には、これは、ソースコードが最近コンパイルされた他のプログラムのソースコードと同じであるスクリプトプログラムがコンパイルされる直前に、コンパイラからの以前の出力を再利用し、コンパイル手順を完全にスキップすることを意味します。このキャッシュは、各ページが同じ(場合によっては非常に大きい)スクリプトライブラリをロードすることが多いため、ニュースサービスの異なるニュース記事など、同じサイトからページごとにページをロードする一般的なブラウジングシナリオで非常に効果的です。

そのため、JavaScriptはページのリロード時にキャッシュされるため、同じスクリプトに対する2つのリクエストは再コンパイルされません。

ソース


Firefox:SpiderMonkey Engine

SpiderMonkeyはNanojitをネイティブバックエンド、JITコンパイラとして使用します。マシンコードをコンパイルするプロセスは here で見ることができます。要するに、スクリプトがロードされたときに再コンパイルするためにが表示されます。ただし、 詳細に調べますNanojitの内部を見ると、コンパイルの追跡に使用される高レベルのモニターjstracerが3つのステージを遷移できることがわかります。コンパイル中に、Nanojitに利点を提供します。

トレースモニターの初期状態は監視です。これは、spidermonkeyがバイトコードを解釈していることを意味します。 spidermonkeyが逆方向ジャンプバイトコードを解釈するたびに、モニターは、ジャンプ先のプログラムカウンター(PC)値がジャンプした回数を記録します。この数は、PCのヒットカウントと呼ばれます。特定のPCのヒットカウントがしきい値に達すると、ターゲットはホットと見なされます。

モニターは、ターゲットPCがホットであると判断すると、フラグメントのハッシュテーブルを調べて、そのターゲットPCのネイティブコードを保持しているフラグメントがあるかどうかを確認します。そのようなフラグメントが見つかると、実行モードに移行します。それ以外の場合は、記録モードに移行します。

これは、コードのhotフラグメントに対して、ネイティブコードがキャッシュされることを意味します。再コンパイルする必要のない意味。これらのハッシュされたネイティブセクションがページの更新間で保持されるかどうかは明確になっていません。しかし、そうだと思います。 誰もがこれを裏付ける証拠を見つけることができれば、素晴らしい。

[〜#〜] edit [〜#〜]:Mozilla開発者のBoris ZbarskyがGeckoはコンパイルされたスクリプトをキャッシュしないと述べていることが指摘されていますyetthis SO answer


Safari:JavaScriptCore/SquirelFish Engine

この実装のベストアンサーはすでに 他の誰かから与えられている であると思います。

現在、バイトコード(またはネイティブコード)をキャッシュしていません。それは
検討したオプションですが、現在、コード生成は
JS実行時間のごく一部(<2%)、したがって私たちは追求していません
これは現時点では。

これは Maciej Stachowiak 、Safariのリード開発者によって書かれました。だから私たちはそれを真実だと思うことができると思います。

他の情報は見つかりませんでしたが、最新のSquirrelFish Extreme engine here 、またはソースコードを参照します here 冒険的な気分であれば。


IE:チャクラエンジン

このフィールドには、IE9のJavaScriptエンジン(Chakra)に関する現在の情報はありません。 誰かが何かを知っているなら、コメントしてください。

これは非常に非公式ですが、IEの古いエンジンの実装では、Eric Lippert( JScriptのMS開発者 )はブログの返信で here と述べています:

JScript Classicは、JScript Classicプログラムを実行する前に、コードを完全に構文チェックし、完全な解析ツリーを生成し、バイトコードを生成するという意味で、コンパイルされた言語のように機能します。次に、バイトコードインタープリターを介してバイトコードを実行します。その意味で、JScriptはJavaと同じくらい「コンパイル」されています。 違いは、JScriptでは、独自のバイトコードを永続化または検査できないことです。また、バイトコードはJVMバイトコードよりもはるかに高レベルです。JScriptClassicバイトコード言語は、解析ツリーの線形化に過ぎませんが、JVMバイトコードは明らかに低レベルのスタックマシンで動作することを目的としています。

これは、バイトコードが決して持続しないため、バイトコードがキャッシュされないことを示唆しています。

333
Jivings

他の回答で述べたように、Operaはそれを行います。 ( ソース

Firefox(SpiderMonkeyエンジン)は、バイトコードをキャッシュしませんnot。 ( ソース

WebKit(Safari、Konqueror)は、バイトコードをキャッシュnotします。 ( ソース

IE [6/7/8]またはV8(Chrome)についてはわかりません。IEは何らかのキャッシングを行うかもしれませんが、V8はそうではないかもしれません。IEはソースが閉じているのでわかりませんが、V8では、マシンコードに直接コンパイルされるため、「コンパイル済み」コードをキャッシュしても意味がありません。

12
cha0site

私の知る限り、Operaは解析されたJavaScriptをキャッシュします。「キャッシュされたコンパイル済みプログラム」セクションを参照してください here

3
gsnedders

Google Dart が「スナップショット」を介してこの問題に明示的に取り組むことは価値がありません-目標は、コードの事前解析バージョンをロードすることにより、初期化とロード時間を短縮することです。

InfoQには優れた記事があります@ http://www.infoq.com/articles/google-Dart

2
igrigorik

ブラウザは間違いなくキャッシュを使用しますが、はい、ブラウザはページが更新されるたびにJavaScriptを解析します。ブラウザーによってページが読み込まれるたびに、2つのツリー1.Contentツリーと2.renderツリーが作成されるためです。

このレンダーツリーは、dom要素の視覚的なレイアウトに関する情報で構成されています。そのため、ページが読み込まれるたびに、javascriptが解析され、javascriptによる動的な変更により、dom要素、show/hide要素、add/remove要素の配置がブラウザによってレンダリングツリーが再作成されます。しかし、FFやchromeのような現代のブラウザは、少し異なる方法で処理し、インクリメンタルレンダリングの概念を持っているため、上記のjsによる動的な変更があるときはいつでも、これらの要素はレンダリングして再描画します。

0
Abhidev

正解は「常にではない」と思います。私が理解していることから、ブラウザとサーバーの両方が、キャッシュされるものを決定する役割を果たす。毎回ファイルをリロードする必要がある場合は、Apache内から設定する必要があると思います(たとえば)。もちろん、ユーザーのブラウザーがその設定を無視するように構成できると思いますが、それはおそらくありそうもないことです。

だから、ほとんどの実際的なケースでは、javascriptファイル自体はキャッシュされますが、ページがロードされるたびに動的に再解釈されると想像します。

0
Zachary Murray