
# 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](https://phasis.inline0.dev/et/docs/interop/host-functions).
- **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](https://phasis.inline0.dev/et/docs/advanced/bytecode-vm).
- **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

```bash
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`](https://github.com/inline0/phasis/blob/main/BENCH.md).

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

```bash
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.
