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


190

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

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

これは非効率ですが、完全に理解できますが、最近のブラウザーはサイト内の解析手順を回避するのに十分なほど賢いのでしょうか。サイトがExtJSやjQueryなどのJavaScriptライブラリを使用している場合を考えています。


4
私の2c:解析されたJavascriptファイルをキャッシュすることのパフォーマンス上の利点は、意味のある最適化には小さすぎると感じています。
Itay Maman

2
私のベンチマークから、それは実際に重要かもしれません。たとえば、jQueryの読み込み時間は約30ミリ秒(高速デスクトップマシン上)で、そのうち20%はコードを実行可能な表現に解析するだけで、残りはコードを実行します。つまり、この場合はjQueryオブジェクトを初期化します。モバイルを使用していて、2つまたは3つのライブラリを使用している場合、JavaScriptの実行がブロックされ、すべてのJSスクリプトがメモリに読み込まれるまでページは基本的に空白になるため、この遅延が関係する可能性があります。
djjeck

回答:


338

これらは私が掘り起こすことができた詳細です。JavaScriptは通常VMで解釈および実行されると見なされますが、ソースを直接マシンコードにコンパイルする傾向がある最近のインタープリターでは、これは実際には当てはまりません(IEを除く)。


Chrome:V8エンジン

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

ソース


更新-2015年3月19日

Chromeチームは、JavaScriptのストリーミングとキャッシングに関する新しい手法の詳細をリリースしました。

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

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

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

  1. コードキャッシング

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

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


Opera:キャラカンエンジン

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

したがって、JavaScriptはページの再読み込み時にキャッシュされます。同じスクリプトに対する2つの要求は、再コンパイルにつながりません。

ソース


Firefox:SpiderMonkeyエンジン

SpiderMonkeyはNanojit、JITコンパイラをネイティブバックエンドとして使用します。マシンコードをコンパイルするプロセスはここにあります。要するに、ロードされたスクリプトを再コンパイルするように見えます。しかし、私たちはよく見とるの内部でNanojit我々をより高いレベルの監視ことがわかりjstracerコンパイルを追跡するために使用され、に利益を提供し、コンパイル時に3つの段階を経て移行することができますNanojit

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

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

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

編集:Mozilla開発者のBoris Zbarskyが、Geckoはまだコンパイル済みスクリプトをキャッシュしないと述べていることが指摘されてます。このSOの答えから取られた。


Safari:JavaScriptCore / SquirelFishエンジン

この実装の最良の答えはすでに他の誰かによって与えられていると思います

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

これは、Safariの主要開発者であるMaciej Stachowiakによって書かれました。だから私たちはそれが真実であると考えることができると思います。

私は他の情報を見つけることができませんでしたが、あなたは、最新の速度の向上について詳しく読むことができるSquirrelFish Extremeエンジンここでは、あるいはソースコードを閲覧し、ここであなたは冒険を感じている場合。


IE:チャクラエンジン

この分野のIE9のJavaScriptエンジン(チャクラ)に関する現在の情報はありません。誰か知っていることがあればコメントしてください。

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

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

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


10
+1、優れた記事。ただし、Firefoxについては、このStackOverflowの質問を参照しください。Mozilla開発者のBoris Zbarskyが、Geckoは現在これを実行していないと説明しています。
cha0site

ありがとう、私は旅行でそれを見ましたが、他の裏付けとなる証拠を見つけることができませんでした。それで答えを編集します。
Jivings

1
IEについて言われたことが2003年に言われたことに注意してください:IE9のJSエンジンの最初のリリースは2011
。– gsnedders

また、Operaは単なるリロード以上の方法でJSバイトコードをキャッシュします。(ただし、生成されたマシンコードはキャッシュされません)。
gsnedders 2012

2
@Jivings上記をソースとして使用します。(私はカラカンチームのメンバーの1人です。)
gsnedders '15

12

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

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

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

IE [6/7/8]かV8(Chrome)かはわかりません。IEがキャッシュを実行しているのに対して、V8は実行していないと思います。IEはクローズドソースであるため、よくわかりませんが、V8では、「コンパイルされた」コードをキャッシュすることは、マシンコードに直接コンパイルされるため、意味がありません。


1
IE6–8はほとんど間違いなくそうしません。IE9はそうかもしれませんが、どちらの方法でも証拠がありません。コンパイルされたJSはかなり大きいことが多いため、どこにもキャッシュされない可能性があります。
gsnedders 2012

@gsnedders:IE8が技術的にそれを実行できないかどうかはわかりませんが、あまりにもコンパイルしてバイトコード(公式ではありませんが閉じる)にコンパイルされているようです。そのため、それをキャッシュしない技術的な理由はありません。IE9はネイティブコードにコンパイルするJITを追加するようです。
cha0site

2
バイトコードは、IEで…ずっと使用されてきました。IE8の新機能はありません。インタプリタが与えられた場合、インタプリタのパフォーマンスが解析時間よりも非常に遅いということは、それだけではまったく関係ありません。IE9には完全に新しい(ゼロから)JSエンジンが搭載されているため、2つの間に何も従いません。
gsnedders

3

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


おかげで、他のブラウザファミリの詳細もわかりますか?
ajreal


0

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

そのため、ほとんどの場合、JavaScriptファイル自体はキャッシュされますが、ページが読み込まれるたびに動的に再解釈されると思います。


0

ブラウザーは間違いなくキャッシュを利用しますが、ページが更新されるたびにブラウザーはJavaScriptを解析します。ブラウザがページをロードするたびに、2つのツリー1.コンテンツツリーと2.レンダリングツリーが作成されるためです。

このレンダーツリーは、dom要素の視覚的なレイアウトに関する情報で構成されています。そのため、ページが読み込まれるたびにJavaScriptが解析され、JavaScriptによる動的な変更により、dom要素、show / hide要素、add / remove要素の配置がブラウザでレンダーツリーが再作成されます。しかし、FFやクロームのような最近のブロワーは少し異なる方法で処理し、インクリメンタルレンダリングの概念を持っているため、前述のようにjsによって動的な変更があった場合は常に、これらの要素をレンダリングして再描画するだけです。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.