Liigu sisu juurde

Võrdlustestid

Phasis on väljakutsepõhistes JavaScript ülesannetes umbes kaks suurusjärku aeglasem kui V8. See ülempiir tuleneb otseselt PHP keskkonnas töötava interpretaatori kulust võrreldes natiivse JIT-kompilaatoriga. Mootori põimijale pole küsimus „kuidas see V8-ga võrdub?”, vaid „kas see on minu töö jaoks piisavalt kiire?”. Enamiku põimimistööde puhul on vastus jah.

Millal ülempiir tähtsust ei oma

  • Mallide renderdamine – tavalise lehe SSR-laadne renderdus kestab tublisti alla 10 ms.
  • Valideerimisreeglid – kasutaja antud JS-i vormi valideerimiseks käivituvad mikrosekunditega.
  • Andmete teisendamine – sadade üksuste array.map(transform)-i töötlemine võtab kümneid millisekundeid.
  • Liivakastis käitajad – lühikesed kasutaja skriptid, mille hostipoolne ajapiirang on 1 sekund, jätavad piisavalt jõudlusvaru.

Millal ülempiir on oluline

  • Arvutusmahukad sisemised tsüklid – pilditöötlus, suurte massiivide koondamine, simulatsioonid. Teisalda arvutused natiivsesse PHP teeki ja ava see hostifunktsioonina.
  • Reaalajas animatsioon – kõik, mis peab töötama sagedusel 60 kaadrit sekundis. See JS kuulub kliendipoolsesse rakendusse (brauserisse või natiivrakendusse), mitte põimitud mootorisse.
  • Arvutusmahukate algoritmide JS ümberteostused – krüptograafia, pakkimine, parsimine. PHP-l on natiivsed vasted, mis on 1000× kiiremad; kasuta neid.

Sobiv mõttemudel: Phasis on PHP-laadsetesse rakendustesse põimitud JS-laadse loogika liimkiht. PHP host hoolitseb arvutuste eest; JS kiht seadistuse, harude ja väikeste teisenduste eest.

Mis teeb mootori tõhusamaks (võrreldes lihtsa puu läbiva käituriga)

  • Baitkoodi VM – enamik sagedasi väljakutseid käib läbi VM::execute opkoodilüliti, mitte AST.
  • Kohandatud väljakutsepinu – iga JS väljakutse hoiab oleku VM::execute sees ja salvestab kutsuja kaadri kogumisse; iga JS väljakutse jaoks ei looda uut PHP raami. Vt Baitkoodi VM § Kohandatud väljakutsepinu.
  • Inline-vahemälud – PC-põhine monomorfne vahemälu jätab prototüübiahela läbimise vahele, kui loetakse prototüübimeetodit eksemplarilt (c.method() muster).
  • Kaadri hetktõmmise generaatorid – lihtsad generaatorikehad peatatakse, salvestades käituse oleku hunnikuobjekti, selle asemel et läbida PHP Fiberit.
  • JsToPhp transpiiler – arvudest ja lokaalm muutujatest sõltuvad kehad (sh obj.method(), new Ctor() ja this.member lugemised) kompileeritakse PHP sulunditeks, mille PHP 8.5 jälgiv JIT-kompilaator teisendab natiivseks masinkoodiks.
  • JSON.stringify vahemälu – JSON.stringify(o) salvestab tulemuse sisendobjekti külge koos transitiivse versiooni kehtetuks muutmisega, kiirendades süvakloonimise idioomi JSON.parse(JSON.stringify(o)).

Oma töökoormuse mõõtmine

Shell
php bench/run.php

See käivitab mikrojõudlustestide komplekti, mis sisaldub asukohas bench/microbench.js: mõned sünteetilised töökoormused (tsüklite aritmeetika, rekursiivsed funktsioonid, objektide loomine, prototüübimeetodite kutsumine, massiivi lisamine, JSON edasi-tagasi teisendus jne) ning väljastab iga testi mediaanse seinakellaaja. Kasulik mõistlikkuse kontrolliks; praegused tulemused salvestatakse iga CI jõudlustesti käigus asukohta BENCH.md.

Oma koodi mõõtmiseks asenda sinna mis tahes skript:

Shell
php -d xdebug.mode=off bench/run.php path/to/your-script.js

PHP-taseme profiilianalüüsiks töötab Xdebug profiilianalüsaator Phasis-iga täpselt nagu iga teise PHP rakendusega. Käivita skript xdebug.mode=profile all ja uuri cachegrind-väljundit, et näha, millised Phasis\ klassid võtavad enim aega.

Teekaart

Mis vähendaks V8 jõudlusvahet kõige rohkem, alustades hõlpsamini teostatavast:

  • Polümorfsed inline-vahemälud — võimaldavad ühel LOAD_MEMBER kutsekohal hoida 2-4 vahemällu salvestatud kuju, enne kui minnakse üle aeglasele väljakutsele. See aitab koodil, mis töötleb eri tüüpi vastuvõtjaid.
  • yield* ja try-with-yield kaadripildi generaatori teel — nende kujude puhul suunatakse praegu Fiber-põhisesse puupõhisesse interpretaatorisse. Enne kui need on kaadripiltide jaoks ohutud, tuleb neid käsitleda selgesõnalise olekumasinaga (delegeeritud iteraatori edastamine, käitlejate pinu säilitamine peatamise ajal).
  • Asünkroonsed generaatorid ja await kaadripiltidel — spetsifikatsioon ühendab generaatori peatamise mikrotööde järjekorraga. Kui baidikoodi keha toetab nii yield kui ka await, sobivad ka asünkroonsed generaatorid kaadripiltidega.
  • Parameetri tüübi tuletamine JsToPhpis — funktsiooni parameetrite vaiketüüp on numbriline, mistõttu function (obj) { obj.method() } paneb kompilaatori loobuma. Parameetrite objektitüübi tuletamine nende kasutuse põhjal funktsiooni kehas võimaldaks kutsuda meetodeid funktsiooniargumentidel, ilma et vastuvõtja tuleks luua lokaalselt new abil.
  • Otsene opcache-väljundi genereerimine — jätab JsToPhpi eval() sammu vahele, kirjutades opcache-vormingus opkoodid otse. See on kõige keerukam punkt; ülejäänud saab teha olemasoleva arhitektuuri piires.

Ükski neist pole vajalik manustatud rakenduste jaoks, millele Phasis on mõeldud.