V8 Engine: Wéi funktionnéiert et?

v8 ass a Javascript-Moteur am Google Entwécklungszentrum an Däitschland erstallt. De Motor ass Open Source a geschriwwen an C ++. Et gëtt souwuel op der Client Säit (Google Chrome) an op der Server Säit (node.js), am Ökosystem vun JavaScript Uwendungen benotzt.
Sportler déi lafen: V8 vun js Republik
V8 gouf fir d'éischt konzeptualiséiert fir JavaScript Runtime Performance a Browser ze erhéijen. Fir Geschwindegkeet ze gewannen, iwwersetzt V8 JavaScript Code an héich performant Maschinnsprooch amplaz en Dolmetscher ze benotzen. De Motor kompiléiert Javascript Code an Assemblée beim Runtime andeems en a JIT (Just-In-Time) Compiler wéi déi meescht modern Javascript Motore (wéi SpiderMonkey oder Rhino (Mozilla)) maachen. Den Haaptunterschied mam V8 ass datt et kee Bytecode / Zwëschencode produzéiert.
Den Zweck vun dësem Artikel ass Iech ze weisen an Iech ze verstoen wéi de V8 Motor funktionnéiert fir optimiséiert Code ze produzéieren fir de Client Säit an d'Server Säit vun Ären Uwendungen. Wann Dir Iech jeemools d'Fro stellt "Sollt ech iwwer d'Leeschtung vu JavaScript besuergt sinn", dann äntweren ech Iech mat engem Zitat vum Daniel Clifford (Tech Lead a Manager vum V8 Team):
Op Franséisch:

"Et ass net nëmmen Är aktuell App méi séier ze maachen, et ass Saachen méiglech ze maachen déi virdru net méiglech waren"

Op Englesch:

"Et geet net nëmmen drëm fir Är aktuell Applikatioun méi séier ze laafen, et geet drëm Saachen z'erméiglechen déi Dir an der Vergaangenheet nach ni konnt maachen."

Verstoppt Klass

JavaScript ass Prototyp-baséiert: Et gi keng Klassen an Objete ginn erstallt mat engem Kloneprozess. JS ass och eng dynamesch getippten Sprooch: Typen an hir Informatioun sinn net selbstverständlech, an Eegeschafte kënnen derbäigesat ginn a souguer vun Objete geläscht ginn. Effizient Zougang zu Typen an Eegeschaften ass eng éischt grouss Erausfuerderung fir V8. Amplaz eng Wierderbuch-ähnlech Struktur ze benotzen fir Objekteigenschaften ze halen, an en dynamesche Lookup ze maachen fir de Standort vun enger Immobilie ze fannen (wéi déi meescht JavaScript Motore maachen), erstellt V8 verstoppte Klassen, an der Runtime, fir eng intern Representatioun vun der Typ System a verbesseren Propriétéit Zougang mol.
Huelt als Beispill eng Funktioun Point an d'Schafung vun zwee Objeten Point:

Wann d'Layouten d'selwecht sinn, wat se sinn, p et q sinn Deel vun der selwechter verstoppt Klass geschaf V8. Dëst weist en anere Virdeel fir verstoppte Klassen ze benotzen: Si erlaben V8 Objekter ze gruppéieren déi déiselwecht Eegeschaften hunn. Genau hei; p et q benotzen déi selwecht optimiséiert Code.
Gitt elo un datt mir wëllen eng Immobilie derbäisetzen z zu eisem Objet q, direkt no senger Deklaratioun (wat absolut normal ass mat enger dynamesch getippter Sprooch).
Wéi behandelt V8 dëst Szenario? A Wierklechkeet, V8 erstellt eng nei verstoppte Klass all Kéier wann d'Konstruktorfunktioun eng Eegeschafte erklärt an et kontrolléiert fir Ännerungen an der verstoppt Klass. Firwat ? Well wann zwee Objekter erstallt ginn (p et q) a wann e Member op den zweeten Objet bäigefüügt gëtt (q) no senger Kreatioun muss V8 déi lescht erstallt verstoppte Klass erhalen (fir den éischten Objet p) an de Motor muss eng nei schafen mat (fir den zweeten Objet q) den neie Member.
Beispill wéi V8 erstellt verstoppte Klassen fir d'Konstruktorfunktiounen
All Kéier wann eng nei verstoppte Klass erstallt gëtt, gëtt déi virdrun aktualiséiert mat engem Klasseniwwergang, deen uginn wéi eng verstoppte Klass ze benotzen amplaz vun der viregter.

Code Optimisatioun

Wéi V8 eng nei verstoppte Klass fir all Immobilie erstellt, sollten hir Kreatiounen miniméiert ginn. Dofir musse mir probéieren keng Eegeschafte no der Schafung vum Objet ze addéieren an ëmmer d'Membere vum Objet an der selwechter Uerdnung initialiséieren (fir verschidde verstoppte Klassebam ze vermeiden).
En aneren Tipp: Monomorphesch Operatiounen sinn déi, déi op Objeten funktionnéieren, déi déiselwecht verstoppt Klass deelen. V8 erstellt eng verstoppt Klass wann Dir eng Funktioun rufft. Wa mir déiselwecht Funktioun nennen awer mat Parameteren vun verschiddenen Typen, muss V8 eng aner verstoppte Klass erstellen: Preferenz monomorphic Code zu polymorphic Code.

Méi Beispiller vu wéi V8 JavaScript Code optiméiert

Tagged Wäerter

Fir eng efficace Representatioun vu JavaScript Zuelen an Objeten ze hunn, representéiert V8 se mat engem Wäert vun 32 Bit. Et benotzt e bësse fir ze wëssen ob et en Objet ass (Fändel = 1) oder en Ganzt (Fändel = 0) genannt aus SMall Integer oder SMI wéinst deenen 31 Bits. Also wann en numeresche Wäert méi grouss ass wéi 31 Bits, wäert V8 d'Zuel encapsuléieren, entweder mécht et duebel oder erstellt en neien Objet fir se ze kapselen.
Code Optimisatioun: Benotzt 31-Bit ënnerschriwwen Zuelen sou vill wéi méiglech, fir déi deier Operatioun vun der Encapsuléierung an engem JavaScript Objet ze vermeiden.

Biller

V8 benotzt zwou verschidde Methoden fir Arrays ze veraarbecht:

  • Fast Elementer: Entworf fir Brieder wou all d'Schlësselen ganz kompakt sinn. Si hunn eng linear Stockage Puffer sou datt den Zougang ganz effizient ass.

  • Wierderbuch Artikelen: Designt fir Brieder wou Elementer verspreet sinn. Si sinn tatsächlech hash Dëscher, wat méi deier ass wéi "Fast Elements".

Code Optimisatioun: Vergewëssert Iech datt V8 d'Methode "Fast Element" benotzt fir mat Arrays ze këmmeren, an anere Wierder, Arrays mat verspreeten Elementer vermeiden wou d'Schlësselen net inkrementell bestallt sinn. Vermeit och Pre-allokéieren grouss Arrays. Et ass besser datt se wuessen wéi se goen. Endlech, läscht keng Elementer an den Arrays: all d'Schlësselen wieren dann verspreet.

Wéi kompiléiert V8 JavaScript Code?

V8 huet zwee Compiler!

  • Un "Voll" Compiler wat e gudde Code fir all JavaScript generéiere kann: gudde Code awer, et ass kee super JIT Code. Den Zweck vun dësem Compiler ass Code séier ze generéieren. Fir dëst Zil z'erreechen, mécht de Compiler keng Typanalyse a weess näischt iwwer Typen. Amplaz benotzt de Compiler eng Strategie vun inline Cache oder "IC" fir Wëssen iwwer Typen ze verfeineren wärend de Programm leeft. IC ass ganz effizient an erhéicht d'Geschwindegkeet (duerch eng Bestellung x20).

  • Un optimiséieren Compiler déi fantastesch Code fir déi meescht vun der JavaScript Sprooch produzéiert. Dëse Compiler kënnt méi spéit a kompiléiert Funktiounen nei, déi e puer Mol benotzt ginn (waarm Funktiounen). Dëse Compiler hëlt d'Typen aus dem Inline Cache an entscheet wéi am Beschten de Code optiméiert. Wéi och ëmmer, e puer Deeler vun der Sprooch ginn nach net ënnerstëtzt, zum Beispill Try/catch Blocks. (Den Trick fir Versuch-/Fangblocken ass den "onstabile" Code an enger Funktioun ze schreiwen an et am Versuchblock ze nennen).

Code Optimisatioun: V8 ënnerstëtzt och de-optimization: Optimisatiounscompiler mécht optimistesch Viraussetzungen aus Inline Cache iwwer verschidden Aarten, Deoptimiséierung geschitt wann dës Viraussetzungen ongëlteg sinn. Zum Beispill, wann eng verstoppte Klass erstallt gouf déi net virgesi war, verwerft V8 den optimiséierte Code a geet zréck op de "Full" Compiler fir d'Typen aus dem Inline Cache zréckzekommen. Dëse Prozess ass lues a sollt vermeit ginn, wat méiglech ass andeems d'Funktioune geännert ginn nodeems se optimiséiert goufen.

Ressourcen

Zousätzlech Ressourcen: monomorphesch vs polymorphesch
Source: Wéi funktionnéiert de V8 Motor?, Thibault Laurens
Iwwersetzung vum Yoan Ribeiro