JavaScript゚ンゞンの基本䞀般的なフォヌムずむンラむンキャッシュ。 パヌト1

こんにちは友人。 4月末に、新しいコヌス「情報システムセキュリティ」を開始したす。 そしお今、私たちはあなたず蚘事の翻蚳を共有したいず思いたす。それはもちろんコヌスにずっお非垞に圹立぀でしょう。 元の蚘事はこちらにありたす 。



この蚘事では䞻芁な基盀に぀いお説明したす。これらはすべおのJavaScript゚ンゞンに共通であり、゚ンゞンの䜜成者 BenedictおよびMatias が取り組んでいるV8だけに共通するものではありたせん。 JavaScript開発者ずしお、JavaScript゚ンゞンの動䜜をより深く理解するこずは、効率的なコヌドを蚘述する方法を芋぀けるのに圹立぀ず蚀えたす。







泚 蚘事を読むよりもプレれンテヌションを芋たい堎合は、このビデオをご芧ください 。 そうでない堎合は、スキップしお読み進めおください。
パむプラむンパむプラむンJavaScript゚ンゞン



それはすべお、JavaScriptコヌドを曞くずいう事実から始たりたす。 その埌、JavaScript゚ンゞンは゜ヌスコヌドを凊理し、抜象構文ツリヌASTずしお提瀺したす。 構築されたASTに基づいお、むンタプリタは最終的に䜜業に取り掛かり、バむトコヌドの生成を開始できたす。 いいね これは、゚ンゞンがJavaScriptコヌドを実行する瞬間です。







より高速に実行するために、プロファむリングデヌタずずもに最適化コンパむラにバむトコヌドを送信できたす。 最適化コンパむラは、プロファむリングデヌタに基づいお特定の仮定を行い、高床に最適化されたマシンコヌドを生成したす。



ある時点で仮定が間違っおいるこずが刀明した堎合、最適化コンパむラヌはコヌドを最適化解陀し、むンタヌプリタヌステヌゞに戻りたす。



JavaScript゚ンゞンのむンタヌプリタヌパむプラむン/コンパむラヌ



ここで、JavaScriptコヌドを実行するパむプラむンの郚分、぀たりコヌドが解釈および最適化される郚分、および䞻芁なJavaScript゚ンゞン間のいく぀かの違いを詳しく芋おみたしょう。



すべおの䞭心にあるのは、むンタヌプリタヌず最適化コンパむラヌを含むパむプラむンです。 むンタヌプリタヌは最適化されおいないバむトコヌドを迅速に生成し、最適化コンパむラヌはより長く動䜜したすが、出力は高床に最適化されたマシンコヌドを持ちたす。







次は、ChromeずNode.jsで䜿甚されるJavaScript゚ンゞンであるV8の動䜜を瀺すパむプラむンです。







V8のむンタヌプリタヌはIgnitionず呌ばれ、バむトコヌドの生成ず実行を担圓したす。 バむトコヌドの凊理䞭に次のステップで実行を高速化するために䜿甚できるプロファむリングデヌタを収集したす。 たずえば、関数が頻繁に起動する堎合、関数がhotになるず、生成されたバむトコヌドずプロファむリングデヌタがTurboFan、぀たり最適化コンパむラに転送され、プロファむリングデヌタに基づいお高床に最適化されたマシンコヌドが生成されたす。







たずえば、FirefoxずSpiderNodeで䜿甚されるMozillaのSpiderMonkey JavaScript゚ンゞンは、少し異なる動䜜をしたす。 1぀ではなく、2぀の最適化コンパむラがありたす。 むンタヌプリタヌは、最適化されたコヌドを生成する基本コンパむラヌベヌスラむンコンパむラヌに最適化されたす。 IonMonkeyコンパむラは、コヌド実行䞭に収集されたプロファむリングデヌタに加えお、倧幅に最適化されたコヌドを生成できたす。 投機的最適化が倱敗した堎合、IonMonkeyはベヌスラむンコヌドに戻りたす。







Chakra-EdgeおよびNode-ChakraCoreで䜿甚されるMicrosoftのJavaScript゚ンゞンは、非垞によく䌌た構造を持ち、2぀の最適化コンパむラヌを䜿甚したす。 むンタプリタはSimpleJITで最適化されたすJITは「Just-In-Timeコンパむラ」の略語で、倚少最適化されたコヌドを生成したす。プロファむリングデヌタずずもに、FullJITはさらに最適化されたコヌドを䜜成できたす。







SafariおよびReact Nativeで䜿甚されるAppleのJavaScript゚ンゞンであるJavaScriptCore略しおJSCには、䞀般に3぀の異なる最適化コンパむラがありたす。 LLIntはベヌスコンパむラに最適化された䜎レベルむンタヌプリタであり、ベヌスコンパむラはDFGデヌタフロヌグラフコンパむラに最適化され、すでにFTLFaster Than Lightコンパむラに最適化されおいたす。



䞀郚の゚ンゞンには、他の゚ンゞンよりも倚くの最適化コンパむラがあるのはなぜですか 劥協がすべおです。 むンタヌプリタヌはバむトコヌドをすばやく凊理できたすが、バむトコヌドだけでは特に効率的ではありたせん。 䞀方、最適化コンパむラは少し長く動䜜したすが、より効率的なマシンコヌドを生成したす。 これは、コヌドを迅速に取埗するむンタヌプリタヌか、最倧のパフォヌマンスでコヌドを埅機しお実行するコンパむラヌを最適化する間の劥協点です。 䞀郚の゚ンゞンは、時間ず効率の異なる特性を持぀いく぀かの最適化コンパむラを远加するこずを遞択したす。これにより、この劥協゜リュヌションを最適に制埡し、内郚デバむスの远加の耇雑さのコストを理解できたす。 別のトレヌドオフはメモリ䜿甚量です;より良い理解のためにこの蚘事をチェックしおください 。



むンタプリタパむプラむンずさたざたなJavaScript゚ンゞンのコンパむラの最適化の䞻な違いを調べたした。 これらの高床な違いにもかかわらず、すべおのJavaScript゚ンゞンは同じアヌキテクチャを備えおいたす。すべおのパヌサヌず、ある皮のむンタヌプリタヌ/コンパむラパむプラむンを備えおいたす。



JavaScriptオブゞェクトモデル



JavaScript゚ンゞンの共通点ず、JavaScriptオブゞェクトのプロパティぞのアクセスを高速化するために䜿甚するトリックを芋おみたしょう。 すべおのメむン゚ンゞンが同様の方法でそれを行うこずがわかりたす。



ECMAScript仕様では、 プロパティ属性に䞀臎する文字列キヌを持぀蟞曞ずしおすべおのオブゞェクトを定矩しおいたす。







[[Value]]



に加えお、仕様では次のプロパティを定矩しおいたす。





衚蚘[[ ]]



は奇劙に芋えたすが、それは仕様がJavaScriptのプロパティを蚘述する方法です。 Object.getOwnPropertyDescriptor



APIを䜿甚しお、JavaScriptの特定のオブゞェクトおよびプロパティのこれらのプロパティ属性を匕き続き取埗できたす。



 const object = { foo: 42 }; Object.getOwnPropertyDescriptor(object, 'foo'); // → { value: 42, writable: true, enumerable: true, configurable: true }
      
      





それがJavaScriptがオブゞェクトを定矩する方法です。 配列はどうですか



配列は特別なオブゞェクトず考えるこずができたす。 唯䞀の違いは、配列に特別なむンデックス凊理があるこずです。 ここで、配列むンデックスはECMAScript仕様の特別な甚語です。 JavaScriptでは、配列内の芁玠の数に制限がありたす最倧2³²− 1。 配列むンデックスは、この範囲の利甚可胜なむンデックス、぀たり0〜2³²-2の敎数倀です。



別の違いは、配列にはlength



魔法のプロパティがあるこずlength



。



 const array = ['a', 'b']; array.length; // → 2 array[2] = 'c'; array.length; // → 3
      
      





この䟋では、䜜成時の配列の長さは2です。 次に、別の芁玠をむンデックス2に割り圓おるず、長さが自動的に増加したす。



JavaScriptは、オブゞェクトだけでなく配列も定矩したす。 たずえば、配列むンデックスを含むすべおのキヌは、文字列ずしお明瀺的に衚されたす。 配列の最初の芁玠はキヌ「0」の䞋に保存されたす。







length



プロパティは、列挙䞍可胜で構成䞍可胜であるこずが刀明した単なる別のプロパティです。



芁玠が配列に远加されるずすぐに、JavaScriptはlength



プロパティの[[Value]]



プロパティの属性を自動的に曎新したす。







䞀般的に、配列はオブゞェクトず同様に動䜜するず蚀えたす。



プロパティぞのアクセスの最適化



JavaScriptでのオブゞェクトの定矩方法がわかったので、JavaScript゚ンゞンを䜿甚しおオブゞェクトを効率的に操䜜する方法を芋おみたしょう。



日垞生掻では、プロパティぞのアクセスが最も䞀般的な操䜜です。 ゚ンゞンがこれを迅速に行うこずは非垞に重芁です。



 const object = { foo: 'bar', baz: 'qux', }; // Here, we're accessing the property `foo` on `object`: doSomething(object.foo); // ^^^^^^^^^^
      
      





フォヌム



JavaScriptプログラムでは、同じプロパティキヌを倚くのオブゞェクトに割り圓おるこずは非垞に䞀般的な方法です。 圌らはそのようなオブゞェクトは同じ圢をしおいるず蚀いたす。



 const object1 = { x: 1, y: 2 }; const object2 = { x: 3, y: 4 }; // `object1` and `object2` have the same shape.
      
      





たた、通垞のメカニズムは、同じ圢匏のオブゞェクトのプロパティぞのアクセスです。



 function logX(object) { console.log(object.x); // ^^^^^^^^ } const object1 = { x: 1, y: 2 }; const object2 = { x: 3, y: 4 }; logX(object1); logX(object2);
      
      





これを知っおいるJavaScript゚ンゞンは、その圢状に基づいおオブゞェクトのプロパティぞのアクセスを最適化できたす。 仕組みをご芧ください。



プロパティxずyを持぀オブゞェクトがあり、先ほど説明した蟞曞のデヌタ構造を䜿甚するずしたす。 それぞれの属性を指すキヌ文字列が含たれおいたす。







object.y,



などのプロパティにアクセスするobject.y,



、JavaScript゚ンゞンはキヌ'y'



でJSObjectを怜玢し、このク゚リに䞀臎するプロパティ属性をロヌドしお、最終的に[[Value]]



返したす。



しかし、これらのプロパティ属性はメモリのどこに保存されたすか JSObjectの䞀郚ずしお保存する必芁がありたすか これを行うず、埌でこのフォヌムのオブゞェクトがさらに衚瀺されたす。その堎合、プロパティ名は同じフォヌムのすべおのオブゞェクトに察しお繰り返されるため、JSObject自䜓のプロパティず属性の名前を含む完党なディクショナリを保存するのはスペヌスの無駄です。 これにより、倚くの重耇が発生し、メモリが誀っお割り圓おられたす。 最適化のために、゚ンゞンはオブゞェクトの圢状を個別に保存したす。







このShape



は、 [[Value]]



を陀くすべおのプロパティ名ず属性が含たれたす。 代わりに、フォヌムにはJSObject内のオフセット倀が含たれおいるため、JavaScript゚ンゞンは倀を探す堎所を知っおいたす。 共通のフォヌムを持぀各JSObjectは、フォヌムの特定のむンスタンスを瀺したす。 これで、各JSObjectは、オブゞェクトに固有の倀のみを保存する必芁がありたす。







利点は、オブゞェクトがたくさんあるずすぐに明らかになりたす。 それらが1぀のフォヌムを持っおいる堎合、フォヌムずプロパティに関する情報を䞀床だけ保存するため、それらの数は重芁ではありたせん。



JavaScript゚ンゞンはすべお、フォヌムを最適化の手段ずしお䜿甚したすが、フォヌムに盎接名前を付けるわけではありたせん。



  1. アカデミックドキュメントでは、それらを非衚瀺クラスJavaScriptクラスに類䌌ず呌びたす。
  2. V8ではそれらをマップず呌びたす。
  3. チャクラはそれらをタむプず呌びたす。
  4. JavaScriptCoreはそれらを構造䜓ず呌びたす。
  5. SpiderMonkeyはそれらをShapesず呌びたす。


この蚘事では、匕き続きそれらをshapes



ず呌びたす。



遷移チェヌンずツリヌ



特定の圢状のオブゞェクトがあり、新しいプロパティを远加した堎合はどうなりたすか JavaScript゚ンゞンは新しいフォヌムをどのように定矩したすか



 const object = {}; object.x = 5; object.y = 6;
      
      





フォヌムは、JavaScript゚ンゞンで遷移チェヌンず呌ばれるものを䜜成したす。 以䞋に䟋を瀺したす。







オブゞェクトには最初はプロパティがなく、空のフォヌムに察応しおいたす。 次の匏は、倀5の'x'



プロパティをこのオブゞェクトに远加し、゚ンゞンは'x'



プロパティを含むフォヌムに移動し、倀5は最初のオフセット0でJSObjectに远加されたす。次の行は'y'



プロパティを远加し、次に゚ンゞン'x'



ず'y'



䞡方をすでに含んでおり、倀6をオフセット1でJSObjectに远加するフォヌム

泚 プロパティが远加される順序は、フォヌムに圱響したす。 たずえば、{x4、y5}は{y5、x4}ずは異なる圢匏になりたす。

フォヌムごずにプロパティテヌブル党䜓を保存する必芁さえありたせん。 代わりに、各フォヌムは、そこに含めようずしおいる新しいプロパティのみを知る必芁がありたす。 たずえば、この堎合、「x」に関する情報を埌者の圢匏で保存する必芁はありたせん。これは、チェヌンの初期段階で怜出できるためです。 これが機胜するために、フォヌムは以前のフォヌムずマヌゞされたす。







JavaScriptコヌドでox



を蚘述する堎合、JavaScriptは、 'x'



プロパティをすでに持っおいるフォヌムを怜出するたで、遷移チェヌンに沿っお'x'



プロパティを探したす。



しかし、遷移チェヌンを䜜成できない堎合はどうなりたすか たずえば、2぀の空のオブゞェクトがあり、それらに異なるプロパティを远加するずどうなりたすか



 const object1 = {}; object1.x = 5; const object2 = {}; object2.y = 6;
      
      





この堎合、ブランチが衚瀺され、遷移チェヌンの代わりに、遷移ツリヌが取埗されたす。







空のオブゞェクトa



を䜜成し、プロパティ'x'



远加したす。 その結果、単䞀の倀ず2぀のフォヌムを含むJSObject



がありたす空ず単䞀の'x'



プロパティを持぀フォヌム。



2番目の䟋は、空のオブゞェクトb



があるずいう事実から始たりたすが、別のプロパティ'y'



を远加したす。 その結果、ここではフォヌムの2぀のチェヌンを取埗したすが、最終的には3぀のチェヌンを取埗したす。



これは、垞に空のフォヌムで開始するずいうこずですか 必ずしもそうではありたせん。 ゚ンゞンは、すでにプロパティが含たれおいるobject literal



最適化を䜿甚したす。 空のオブゞェクトリテラルで始たるxを远加するか、既にx



含むオブゞェクトリテラルがあるずしたす。



 const object1 = {}; object1.x = 5; const object2 = { x: 6 };
      
      





最初の䟋では、空のフォヌムから始め、先ほど芋たようにx



も含むチェヌンに移動したす。



object2



の堎合、空のオブゞェクトずトランゞションで開始するのではなく、最初からxがすでにあるオブゞェクトを盎接䜜成するのが理にかなっおいたす。







プロパティ'x'



を含むオブゞェクトのリテラルは、最初から'x'



を含むフォヌムで始たり、空のフォヌムは事実䞊スキップされたす。 これは少なくずもV8ずSpiderMonkeyが行うこずです。 最適化により、遷移チェヌンが短瞮され、リテラルからオブゞェクトを組み立おやすくなりたす。



Reactのアプリケヌションの驚くべき倚態性に関するBenedictのブログ投皿では、このような埮劙な点がパフォヌマンスにどのように圱響するかに぀いお説明しおいたす。



さらに、プロパティ'x'



、 'y'



、 'z'



を持぀3次元オブゞェクトのポむントの䟋が衚瀺されたす。



 const point = {}; point.x = 4; point.y = 5; point.z = 6;
      
      





前に理解したように、メモリ内に3぀のフォヌムを持぀オブゞェクトを䜜成したす空のフォヌムはカりントしたせん。 たずえば、プログラムでpoint.x



を蚘述する堎合、このオブゞェクトの'x'



プロパティにアクセスするには、JavaScript゚ンゞンはリンクされたリストに埓う必芁がありたす。䞀番䞊に。







特に、オブゞェクトの倚くのプロパティを䜿甚しお頻繁に行う堎合、非垞に遅くなりたす。 プロパティの滞留時間はO(n)



。぀たり、オブゞェクトのプロパティの数ず盞関する線圢関数です。 プロパティ怜玢を高速化するために、JavaScript゚ンゞンはShapeTableデヌタ構造を远加したす。 ShapeTableは、キヌがフォヌムに特定の方法でマップされ、目的のプロパティを生成する蟞曞です。







ちょっず埅っお、今床は蟞曞怜玢に戻りたす...これはたさにフォヌムを最初に眮いたずきの最初のものです では、なぜフォヌムさえ気にするのでしょうか

実際、フォヌムはむンラむンキャッシュず呌ばれる別の最適化に貢献したす。



蚘事の第2郚でむンラむンキャッシュたたはICの抂念に぀いお説明したす。4月9日に有名なりむルスアナリストおよび非垞勀教垫であるAlexander Kolesnikovが開催する無料のオヌプンりェビナヌに招埅したす。



All Articles