
# Výkonnostní testy

Phasis je u úloh vázaných na volání zhruba o dva řády pomalejší než V8JavaScript. Tento limit je inherentní cenou interpretru hostovaného v PHP oproti nativnímu JIT kompilátoru. Pro toho, kdo jej vkládá, není otázkou „jak si vede ve srovnání s V8“ — ale „je dost rychlý pro to, co dělám“. Pro většinu úloh s vloženým interpretem je odpověď ano.

## Kdy na limitu nezáleží

- **Šablony** — vykreslení typické stránky ve stylu SSR trvá výrazně méně než 10 ms.
- **Validační pravidla** — uživatelem zadané JS pro ověřování formuláře se dokončí v řádu mikrosekund.
- **Transformace dat** — `array.map(transform)` nad stovkami položek se dokončí v řádu desítek milisekund.
- **Spouštěče v sandboxu** — krátké skripty dodané uživatelem mají při limitu hostitele 1 sekunda dostatečnou rezervu.

## Kdy na limitu záleží

- **Výpočetně náročné vnitřní smyčky** — zpracování obrázků, redukce velkých polí, simulace. Přesuňte výpočty do nativní knihovny PHP a zpřístupněte ji jako [hostitelskou funkci](https://phasis.inline0.dev/cs/docs/interop/host-functions).
- **Animace v reálném čase** — cokoli, co má běžet při 60 fps. Tato zátěž JS patří do klienta (prohlížeče nebo nativní aplikace), ne do vloženého enginu.
- **Opětovné implementace algoritmů náročných na výpočty v JS** — kryptografie, komprese, parsování. PHP má nativní ekvivalenty, které jsou 1000× rychlejší; použijte je.

Vhodný způsob uvažování: Phasis je **propojovací vrstva** pro logiku psanou v duchu JS vloženou do aplikací psaných v duchu PHP. Hostitel PHP zajišťuje výpočty; vrstva JS zajišťuje konfiguraci, větvení a drobné transformace.

## Díky čemu je engine rychlý (ve srovnání s naivním stromovým interpretem)

- **VM s bajtkódem** — většina často prováděných volání prochází přepínačem operačních kódů v `VM::execute`, nikoli AST.
- **Vlastní zásobník volání** — každé volání JS uchovává stav uvnitř `VM::execute` a ukládá rámec volajícího do fondu; při každém volání JS nevzniká nový rámec PHP. Viz [Virtuální stroj s bajtkódem § Vlastní zásobník volání](https://phasis.inline0.dev/cs/docs/advanced/bytecode-vm).
- **Mezipaměti inline** — monomorfní mezipaměť pro každé PC umožňuje při čtení metody prototypu instance (vzor `c.method()`) přeskočit procházení řetězce prototypů.
- **Generátory se snímkem rámce** — jednoduchá těla generátorů se pozastaví zachycením stavu zpracování do objektu na haldě, takže není nutné přecházet přes Fiber PHP.
- **Transpiler JsToPhp** — těla s převahou číselných operací a lokálních proměnných (včetně čtení `obj.method()`, `new Ctor()` a `this.member`) se kompilují do uzávěrů PHP, které trasovací JIT kompilátor v PHP 8.5 převádí na nativní strojový kód.
- **Mezipaměť JSON.stringify** — `JSON.stringify(o)` ukládá výstup do vstupního objektu a transitive invalidací verzí zrychluje idiom hlubokého klonování `JSON.parse(JSON.stringify(o))`.

## Měření vlastního zatížení

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

Spustí sadu mikrovýkonnostních testů dodávanou v `bench/microbench.js` — několik syntetických zátěží (aritmetika ve smyčce, rekurzivní funkce, vytváření objektů, volání metod prototypu, přidávání do pole, převod JSON tam a zpět atd.) — a vypíše medián uplynulého času pro každý test. Hodí se jako základní kontrola; aktuální výsledky se při každém běhu CI testů výkonu ukládají do [`BENCH.md`](https://github.com/inline0/phasis/blob/main/BENCH.md).

U vlastního kódu nahraďte skript libovolným jiným:

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

Pro profilování na úrovni PHP funguje profiler Xdebug s Phasis stejně jako s jakoukoli jinou aplikací PHP. Spusťte skript pod `xdebug.mode=profile` a prohlédněte si výstup cachegrind, abyste zjistili, které třídy `Phasis\` převažují.

## Plán dalšího vývoje

Co by v přibližném pořadí podle náročnosti nejvíc zmenšilo rozdíl ve výkonu V8:

- **Polymorfní mezipaměti inline** — umožnit jednomu místu volání `LOAD_MEMBER` uchovávat 2–4 struktury před přechodem k pomalejšímu zpracování. Pomůže kódu, který zpracovává různorodé příjemce volání.
- **`yield*` a try-with-yield v cestě generátorů se snímkem rámce** — tyto tvary nyní přecházejí ke stromovému interpretu založenému na Fiber. Než budou bezpečné pro snímkování, každý vyžaduje výslovné zpracování stavovým automatem (předávání iterátoru delegáta, zachování zásobníku obslužných rutin při pozastavení).
- **Asynchronní generátory a `await` ve snímcích** — specifikace kombinuje pozastavení generátoru s frontou mikroúloh. Až tělo bajtkódu podpoří `yield` i `await`, budou pro snímkování vhodné také asynchronní generátory.
- **Odvození typů parametrů v JsToPhp** — parametry funkcí mají ve výchozím stavu číselný typ, takže `function (obj) { obj.method() }` zastaví kompilátor. Odvozování objektových typů parametrů podle toho, jak se používají v těle funkce, by umožnilo volání metod nad argumenty funkcí bez nutnosti vytvářet příjemce lokálně pomocí `new`.
- **Přímé generování opkódů pro opcache** — přeskočit krok `eval()` v JsToPhp přímým zápisem opkódů ve formátu opcache. Nejnáročnější položka; ostatní lze zvládnout v rámci stávající architektury.

Nic z toho není potřeba pro integrační zátěže, na které cílí Phasis.
