Veiktspējas testi
Phasis ir aptuveni divas lieluma kārtas lēnāks par V8 izsaukumu apstrādē ierobežotām JavaScript slodzēm. Tā ir interpretētāja, ko darbina PHP, nevis vietējā JIT kompilatora, raksturīgā maksa. Iegultā risinājuma izstrādātājam jautājums nav “kā tas salīdzināms ar V8”, bet gan “vai tas ir pietiekami ātrs maniem uzdevumiem”. Lielākajai daļai iegulto risinājumu slodžu atbilde ir jā.
Kad šis ierobežojums nav svarīgs
- Veidņu apstrāde — tipiskas lapas renderēšana SSR stilā aizņem krietni mazāk par 10 ms.
- Validācijas noteikumi — lietotāja nodrošināts JS veidlapu validācijai tiek izpildīts dažu mikrosekundžu laikā.
- Datu pārveidošana —
array.map(transform)ar simtiem elementu tiek pabeigts dažu desmitu milisekunžu laikā. - Skriptu smilškastes — īsi lietotāja nodrošināti skripti ar resursdatora noteiktu 1 sekundes ierobežojumu atstāj lielu laika rezervi.
Kad šis ierobežojums ir svarīgs
- Skaitļošanas ziņā intensīvi iekšējie cikli — attēlu apstrāde, lielu masīvu reducēšana, simulācijas. Pārvietojiet aprēķinus uz vietējo PHP bibliotēku un pievienojiet to kā resursdatora funkciju.
- Animācija reāllaikā — viss, kas darbina 60 kadrus sekundē. Šai JS jādarbojas klientā (pārlūkprogrammā vai vietējā lietotnē), nevis iegultajā dzinējā.
- JS algoritmu atkārtotas realizācijas, kas prasa daudz aprēķinu — kriptogrāfija, saspiešana, parsēšana. PHP ir vietējās alternatīvas, kas ir 1000× ātrākas; izmantojiet tās.
Pareizais domāšanas modelis: Phasis ir līmēšanas slānis JS veida loģikai, kas iegulta PHP veida lietotnēs. Resursdatora PHP apstrādā aprēķinus; JS slānis — konfigurāciju, sazarošanos un nelielas pārveides.
Kas padara dzinēju ātru (salīdzinājumā ar vienkāršu koka apstaigātāju)
- Baitu koda virtuālā mašīna — lielākā daļa bieži izsaukto darbību notiek
VM::executeopkodu izvēles konstrukcijā, nevis AST. - Pielāgots izsaukumu steks — katrs JS izsaukums saglabā stāvokli
VM::executeiekšienē un noglabā izsaucēja kadru pūlā; katram JS izsaukumam netiek izveidots jauns PHP kadrs. Skatiet Baitu koda virtuālā mašīna § Pielāgots izsaukumu steks. - Iekļautās kešatmiņas — monomorfa kešatmiņa katram PC ļauj nolasīt instances prototipa metodi (
c.method()formu), izlaižot prototipu ķēdes apstaigāšanu. - Ģeneratori ar kadru momentuzņēmumiem — vienkāršu ģeneratoru pamatkodi aptur darbību, tverot izpildes stāvokli kaudzē glabātā objektā, nevis pārejot uz PHP Fiber.
- JsToPhp transpilers — skaitliski un lokālo mainīgo ziņā intensīvi pamatkodi (tostarp
obj.method(),new Ctor()unthis.membernolasīšana) tiek kompilēti PHP slēgumos, ko PHP 8.5 trasējošais JIT pārveido par mašīnkodu. - JSON.stringify kešatmiņa —
JSON.stringify(o)saglabā izvadi ievades objektā ar pārejošu versiju anulēšanu, paātrinot dziļās klonēšanas idiomuJSON.parse(JSON.stringify(o)).
Savas slodzes mērīšana
php bench/run.php
Šī komanda palaiž mikromērījumu kopu, kas iekļauta bench/microbench.js — dažas sintētiskas slodzes (aritmētika ciklos, rekursīvas funkcijas, objektu izveide, prototipa metožu izsaukumi, elementu pievienošana masīvam, JSON turp un atpakaļ u. c.) — un izvada katra testa vidējo laiku. Noderīga ātrai pārbaudei; pašreizējie skaitļi pēc katras CI veiktspējas pārbaudes tiek pievienoti BENCH.md.
Lai pārbaudītu savu kodu, aizstājiet to ar jebkuru skriptu:
php -d xdebug.mode=off bench/run.php path/to/your-script.js
Lai profilētu PHP līmenī, Xdebug profilētājs darbojas ar Phasis tāpat kā ar jebkuru citu PHP lietotni. Palaidiet skriptu ar xdebug.mode=profile un pārskatiet cachegrind izvadi, lai noskaidrotu, kuras Phasis\ klases rada lielāko slodzi.
Ceļvedis
Kas aptuveni šādā īstenošanas sarežģītības secībā vēl samazinātu veiktspējas atšķirību līdz V8:
- Polimorfas iekļautās kešatmiņas — ļaut vienai
LOAD_MEMBERizsaukuma vietai saglabāt 2–4 kešotas formas, pirms pāriet uz lēnāku izsaukumu apstrādi. Palīdz kodam, kas apstrādā dažādu tipu saņēmējus. yield*un try-with-yield kadru momentuzņēmumu ģeneratoru ceļā — šīs formas pašlaik tiek novirzītas uz Fiber balstītu koka apstaigātāju. Lai tās varētu droši tvert momentuzņēmumos, katrai nepieciešama skaidra stāvokļu mašīnas apstrāde (delegāta iterētāja pārsūtīšana, apstrādātāju steka saglabāšana apturēšanas laikā).- Asinhronie ģeneratori un
awaitmomentuzņēmumos — specifikācija apvieno ģeneratora apturēšanu ar mikrouzdevumu rindu. Kad baitu koda pamatkods atbalstīs ganyield, ganawait, arī asinhronie ģeneratori būs piemēroti momentuzņēmumiem. - Parametru tipu secināšana JsToPhp — funkciju parametriem pēc noklusējuma tiek piešķirts skaitlisks tips, tāpēc
function (obj) { obj.method() }liek kompilatoram atteikties. Ja objektu tipa parametrus varētu secināt pēc to izmantošanas pamatkodā, būtu iespējams izsaukt metodes funkcijas argumentiem, neprasot, lai saņēmējs būtu lokāli izveidots arnewpalīdzību. - Tieša opcache ģenerēšana — izlaist
eval()posmu JsToPhp kompilatorā, tieši rakstot opcache formāta opkodus. Sarežģītākais uzdevums; pārējos var paveikt esošajā arhitektūrā.
Nekas no minētā nav nepieciešams iegulto risinājumu slodzēm, kurām Phasis ir paredzēts.