
# Výkonnostné testy

Phasis je pri úlohách závislých od dispečingu JavaScript **približne o dva rády pomalší než V8**. Tento limit vyplýva zo samotnej podstaty interpretera hostovaného v PHP v porovnaní s natívnym JIT kompilátorom. Vkladateľ sa nemusí pýtať „ako si vedie v porovnaní s V8“, ale „je dosť rýchly na to, čo potrebujem“. Pri väčšine úloh s vloženým enginom je odpoveď áno.

## Kedy na limite nezáleží

- **Šablóny** — vykreslenie typickej stránky v štýle SSR trvá výrazne menej než 10 ms.
- **Pravidlá validácie** — validácia formulára pomocou používateľom zadaného JS sa dokončí za mikrosekundy.
- **Transformácie údajov** — `array.map(transform)` nad stovkami položiek sa dokončí za desiatky milisekúnd.
- **Spúšťače v izolovanom prostredí** — pri krátkych skriptoch dodaných používateľom a limite hostiteľa 1 sekunda zostáva dostatočná časová rezerva.

## Kedy na limite záleží

- **Výpočtovo náročné vnútorné slučky** — spracovanie obrázkov, redukcie veľkých polí, simulácie. Presuňte výpočty do natívnej knižnice PHP a sprístupnite ju ako [hostiteľskú funkciu](https://phasis.inline0.dev/sk/docs/interop/host-functions).
- **Animácia v reálnom čase** — všetko, čo má bežať pri 60 snímkach za sekundu. To JS patrí do klienta (prehliadača, natívnej aplikácie), nie do vloženého enginu.
- **JS opätovné implementácie výpočtovo náročných algoritmov** — kryptografia, kompresia, parsovanie. PHP má natívne ekvivalenty, ktoré sú 1000× rýchlejšie; použite ich.

Správny mentálny model: Phasis je **prepojovacia vrstva** pre logiku v štýle JS vloženú do aplikácií v štýle PHP. Hostiteľ PHP zabezpečuje výpočty; vrstva JS sa stará o konfiguráciu, vetvenie a malé transformácie.

## Vďaka čomu je engine rýchly (v porovnaní s naivným stromovým interpreterom)

- **VM s bajtkódom** — väčšina horúceho dispečingu prebieha cez prepínač opkódov `VM::execute`, nie cez AST.
- **Vlastný zásobník volaní** — každé volanie JS udržiava stav v `VM::execute` a ukladá rámec volajúceho do fondu; pri každom volaní JS sa nevytvára nový rámec PHP. Pozrite si [Virtuálny stroj bajtkódu § Vlastný zásobník volaní](https://phasis.inline0.dev/sk/docs/advanced/bytecode-vm).
- **Inline cache** — monomorfná cache pre každé PC umožňuje pri čítaní metódy prototypu na inštancii (vzor `c.method()`) preskočiť prehľadávanie reťazca prototypov.
- **Generátory so snímkou rámca** — jednoduché telá generátorov sa pozastavia zachytením stavu dispečingu do objektu na halde namiesto prechodu cez Fiber PHP.
- **Transpilátor JsToPhp** — telá funkcií s číselnými hodnotami a množstvom lokálnych premenných (vrátane čítaní `obj.method()`, `new Ctor()` a `this.member`) sa kompilujú do uzáverov PHP, ktoré trasovací JIT nástroja PHP 8.5 prekladá na natívny strojový kód.
- **Cache JSON.stringify** — `JSON.stringify(o)` ukladá výstup do vstupného objektu a používa tranzitívnu invalidáciu verzií, čím zrýchľuje idiom hlbokého klonovania `JSON.parse(JSON.stringify(o))`.

## Meranie vlastnej záťaže

```bash
php bench/run.php
```

Týmto sa spustí sada mikrobenchmarkov dodávaná s `bench/microbench.js` — niekoľkými syntetickými úlohami (aritmetika v cykloch, rekurzívne funkcie, vytváranie objektov, volania metód prototypu, pridávanie prvkov do poľa, spiatočný prevod JSON a podobne) — a vypíše medián času vykonania každého testu. Je to užitočná kontrola; aktuálne výsledky sa pri každom spustení benchmarkov CI ukladajú do [`BENCH.md`](https://github.com/inline0/phasis/blob/main/BENCH.md).

Pre vlastný kód môžete použiť ľubovoľný skript:

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

Na profilovanie na úrovni PHP funguje profiler nástroja Xdebug s Phasis rovnako ako s akoukoľvek inou aplikáciou PHP. Spustite skript pomocou `xdebug.mode=profile` a vyskúmajte výstup cachegrind, aby ste zistili, ktoré triedy `Phasis\` zaberajú najviac času.

## Plán vývoja

Čo by najviac zmenšilo rozdiel v V8, zoradené približne podľa náročnosti realizácie:

- **Polymorfné inline cache** — umožniť jednému volaciemu miestu `LOAD_MEMBER` uchovávať 2-4 tvary v cache, kým sa prejde na pomalšie spracovanie. Pomáha kódu, ktorý spracúva rôznorodé prijímajúce objekty.
- **`yield*` a try-with-yield v ceste generátora so snímkou rámca** — tieto konštrukcie sa momentálne presmerujú do stromového interpretera založeného na Fiber. Pred bezpečným vytváraním snímok si každá vyžaduje explicitné spracovanie stavového automatu (posúvanie delegovania iterátora, zachovanie zásobníka obslužných rutín počas pozastavenia).
- **Asynchrónne generátory a `await` v snímkach** — špecifikácia kombinuje pozastavenie generátora s frontom mikroúloh. Keď telo bajtkódu podporí `yield` aj `await`, asynchrónne generátory budú tiež kompatibilné so snímkami.
- **Odvodzovanie typov parametrov v JsToPhp** — parametre funkcií majú predvolene číselný typ, preto kompilátor pri `function (obj) { obj.method() }` zlyhá. Odvodenie parametrov objektového typu podľa ich použitia v tele funkcie by sprístupnilo volania metód nad argumentmi funkcie bez toho, aby sa prijímajúci objekt musel vytvoriť lokálne pomocou `new`.
- **Priame generovanie opkódov opcache** — preskočenie kroku `eval()` transpilátora JsToPhp priamym zapisovaním opkódov vo formáte opcache. Najnáročnejšia položka; ostatné možno realizovať v rámci existujúcej architektúry.

Žiadna z týchto zmien nie je potrebná pre úlohy s vloženým enginom, na ktoré je Phasis určený.
