Ce browsere codul javascript de optimizare js-motoare ca un exemplu v8

cod de optimizare nu începe atât de mult cu studiul de caracteristicile limbajului de programare, dar cu înțelegerea schemei întregului „lanț de proces“, care este implicat în crearea unei aplicații - algoritmul de program pentru compilator.

În prezent, Viaceslav activ de lucru pe Google peste Dart VM.
În acest interviu, el a vorbit despre ceea ce se întâmplă în interiorul motorului care efectuează dinamic JS-cod și exemple comune de modul de a efectua unele optimizare și de ce este important să se înțeleagă foarte bine activitatea motorului pentru a permite executarea de cod rapid.

- A absolvit mekhmat NSU. Întotdeauna interesat de compilatoare. La început a lucrat în compania Excelsior Novosibirsk în cazul în care oamenii fac propriile lor JVM cu AOT-compilator, apoi m-am dus la Google. În Google primul angajat V8, apoi Dart VM, de ceva timp, chiar și repararea bug-uri diferite și LuaJIT.

- Multi prefera masina V8 pentru capacitatea sa de a optimiza codul. Care este secretul?

- Dificultatea principală în optimizarea limbaje de programare dinamice este că, pentru a obține performanțe de vârf, mașina virtuală trebuie, de fapt, să ghicească intenția de programator și a vedea structura statică, ascunse în codul dinamic. O caracteristică puternică a V8 este că acesta este capabil suficient de bine pentru a observa că însăși structura.

și se pare că este destul de V8 capabil de a compila corpul acestei funcții într-un cod de mașină destul de compact:

Nu este o sarcină banală într-un mediu în care totul este static și dinamic tastat complet neclar ce


- În ceea ce privește punctele slabe ale motorului?

- Uneori, un V8 puternic mana devine slăbiciunea sa. Acest lucru se întâmplă din două motive.
În primul rând, nu în nici un V8 de cod tastat dinamic capabil de a vedea structura statică, care poate să fi fost evident pentru programator care a scris codul. Undeva se întâmplă pentru că V8 ceva nu a fost încă realizat, undeva - pentru că nu este întotdeauna posibil algoritmic.

Una dintre cele mai comune exemple - este codul în stil:

Există V8 este capabil de a ignora faptul că a.f și b.f au același comportament (ajustat pentru valoarea variabilelor capturate), ca Această caracteristică a creat de la una și aceeași funcție literală (funcția literală).

În al doilea rând, compilator, uneori, optimizarea V8, pur și simplu nu acceptă un fel de structură în codul, iar compilatorul refuză să se uite la codul. De exemplu, arbore cotit (aceasta este prima punere în aplicare a conceptului de V8 de compilare adaptive) nu a sprijinit try-catch / în cele din urmă și, prin urmare, a refuzat să optimizeze funcția, în cazul în care a participat. Acum funcție, care utilizează try-catch, compilate de turbopropulsoare (compilator este dezvoltat pentru a înlocui arborele cotit), astfel încât situația se simte mai bine.

În al treilea rând, uneori costul petrecut pe identificarea unei structuri statice, nu plătesc off. V8 petrece mult timp construirea de un copac ascunse clase care optimizează / deoptimiziruet / optimizează codul din nou - și codul nu este tot mai bine, de exemplu, pentru că obiectele sunt folosite mai ales ca dicționare. Acesta este un domeniu foarte interesant de îngrijorare - modul de echilibrare a costurilor de optimizare a codului și îmbunătățiri ale performanței de la această optimizare. Cum să execute cod la o viteză rezonabilă, chiar și în cazul în care codul nu se încadrează pe calea rapidă evidentă.

Lucrările la toate aceste probleme sunt efectuate, și pentru că, în orice caz, atunci când codul se execută lent pe V8, ar trebui să se plâng dezvoltatorii V8 - cel pentru ei să explice de ce codul se execută lent sau poate fi chiar reparate ceva în sine V8 .

- Cum crezi că sensul optimizarea codului pentru un anumit motor are (în cazul nostru - V8)? La urma urmei, se întâmplă că într-un anumit cod de browser-ul incetineste. Ce să faci atunci?

- Există două opțiuni (sau combinații ale acestora):

  • „Bad“ codul. În acest caz, performanta sufera de obicei imediat sub mai multe motoare, precum și optimizarea motorului de sub un singur cod de performanță se îmbunătățește imediat sub mai multe;
  • cod „Bad“ a motorului. În acest caz, după cum am menționat anterior, este necesar să se trimită un motor de raport pentru dezvoltatori, care pot repara fie motorul în sine, sau de multe ori recomanda un mod în jurul acestui bug.

- Poți lista cea mai comună „rake“, care dezvoltatorii vin în cod (adică, de fapt, cele mai frecvente erori în cod, care afectează în mare măsură orientarea de performanță pe V8 - în cadrul situației menționate mai sus, „codul rău „)?

- Există două tipuri de rake. Primul tip - o algoritmică grebla. De exemplu, uneori oamenii iteram on-line, folosind ciclul de stil:

Mulți kompilyatorschiki începe să sări ușor în scaun și frecându-și mâinile sale atunci când văd un astfel de cod pentru a pune în aplicare optimizări care ar fi un astfel de ciclu ar fi transformat în ceva sănătos - este teribil de interesantă provocare. Cu toate acestea, din punct de vedere al dezvoltator este mult mai eficient pentru a realiza cât de mult s.substring în cele mai bune și mai rău, iar acest cod nu scrie. Deoarece nici o optimizare dificil, în cadrul ciclului motorului are o complexitate timp de O (n 2).

Celălalt tip de arme Tine - o grebla asociată cu optimizarea limbilor dinamice (deja am atins de mai sus). De exemplu, un cod de polimorfă, și anume, cod care funcționează cu diferite tipuri de obiecte. . O astfel de cod pentru V8 de multe ori ca Krypton (material radioactiv cristalin care apare în DC Comics universul kryptonita este faimos pentru că este singura slăbiciune non-magic de Superman și alte kriptontsev - el este capabil să le influențeze, care variază în funcție de culorile minerale -. Ca. Ed..) pentru Superman. Tema este suficient de adânc, și am pe acest subiect există un post cu imagini.

- Cum să se ocupe de aceste probleme? Caută „reguli de codificare a mărfurilor sub anumite motor“ și să verifice codul de respectarea acestora?

- Și dacă te duci înapoi la spus probleme de cod compilator (situația „cod de motor rău“)? Putem da unele probleme cel mai frecvent raportate V8?

- Bug-uri nu apar, de obicei, „de multe ori“ sau „nu de multe ori“. De obicei, se întâmplă ca un bug observat orice dezvoltator, reparat rapid, și că a fost. Bug-uri în acest caz se referă doar o mică populație de dezvoltatori, pentru că există într-un loc foarte special cu dreptul set de circumstanțe.

Ca un exemplu practic: Am o dată a fost rugat să se uite la codul, care, pentru un motiv sau altul, uneori, a început să curgă foarte încet. Sa dovedit toate expresiile Math.floor (x * y). în care, uneori, x a devenit egal cu 1, și y egal cu 0. Este nimic special, dar Math.floor (x y *), în acest caz este egal cu numărul magic „la zero negativ“ (care este aproape în întregime ca 0, dar dacă divizat, spune 1 la zero, se dovedește infinit pozitiv, iar dacă decalajul 1 de minus la zero, se obține infinit negativ). Arbore cotit-se presupune întotdeauna că rezultatul operațiunilor de podea - este un număr întreg, și, prin urmare, -0 - numărul nu poate fi reprezentat ca un întreg a rezultat deoptimization. Soluția în acest caz a fost înlocuită Math.floor (x * y) la (x * y) | 0 (în general, acest lucru nu este echivalent cu conversie, dar codul de care au nevoie pentru a dispersa, nu a jucat un rol). Apropo, recent, această problemă arbore cotit reparat o dată pentru totdeauna.

Am ales în mod specific acest bug-ul ca un exemplu, deoarece este destul de ciudat ( „ceea ce un minus zero?“, „ce pentru deoptimization?“), în speranța de a convinge cititorul că cunoștințele despre bug-uri specifice complet inutil. Am constatat că codul, mă uitam la el vine la acest bug, nu pentru că am știut Math.floor detestă -0. și înarmați cu această cunoaștere a mers înlocui toate Math.floor la | 0. până când bug-ul nu a rezolvat problema ... Nu, am găsit acest bug, pentru că el a știut cum să profilul V8, cu unele chei trebuie să-l rulați la V8 mi-a arătat o listă de deoptimization. Prin urmare, cel mai important lucru pentru a înțelege modul în care V8 (și alte JS VM), care rulează.
Cu aceste cunoștințe, puteți găsi întotdeauna „ce a mers prost undeva in temnite adânci,“ și apoi se plâng autorităților superioare.
Sunt despre acest lucru destul de multe de scris în blog-ul meu și chiar a făcut Instrumente, care vă permite să urmăriți datele de ieșire V8 (compilator IR, deopts, etc), într-o formă mai mult sau mai puțin convenabil.

- Tu faci Dart acum? Atunci când această nouă limbă va înlocui JS? Am nevoie acum dezvoltator pentru a trece la o nouă limbă? Care este poziția sa în industrie?

Unul dintre cele mai interesante lucruri care se întâmplă cu limba în afara Web-ului, puteți selecta flutter.io - este un cadru pentru dezvoltarea cross-platform (Android iOS) aplicațiile mobile și dartino - Dart sisteme mici integrate.

Vă mulțumesc pentru interviu!

Exemplele de mai sus în mod clar ilustrează faptul că simpla lista de „recomandări simple pentru un motor specific“ pentru optimizarea codului nu este de ajuns - este important să înțelegem cum funcționează, și, în același timp, să fie clar despre ce rezultate doriți să obțineți din program.