
# Teljesítménymérések

A Phasis diszpécseléskorlátos JavaScript esetén **nagyjából két nagyságrenddel lassabb, mint a V8**. Ez a PHP-alapú értelmező natív JIT-fordítóhoz viszonyított, eredendő költsége. A beágyazó számára nem az a kérdés, hogy „hogyan viszonyul a V8-hez”, hanem az, hogy „elég gyors-e ahhoz, amit csinálok”. A legtöbb beágyazási terhelésnél igen a válasz.

## Amikor a teljesítménykorlát nem számít

- **Sablonkezelés** — egy tipikus oldal SSR-stílusú megjelenítése jóval 10 ms alatt.
- **Validációs szabályok** — az űrlapellenőrzéshez megadott JS mikroszekundumok alatt lefut.
- **Adatátalakítások** — több száz elemen végzett `array.map(transform)` művelet tíz milliszekundum alatt befejeződik.
- **Sandbox-futtatók** — az 1 másodperces gazdaoldali korláttal futó, rövid, felhasználó által megadott szkripteknek bőven marad tartalékidejük.

## Amikor a teljesítménykorlát számít

- **Számításigényes belső ciklusok** — képfeldolgozás, nagy tömbök redukciója, szimulációk. Helyezze át a számításokat egy natív PHP könyvtárba, és tegye elérhetővé egy [gazdafüggvényen](https://phasis.inline0.dev/hu/docs/interop/host-functions) keresztül.
- **Valós idejű animáció** — minden, ami 60 fps-sel működik. Ennek a JS-nek a kliensben (böngészőben, natív alkalmazásban) van a helye, nem a beágyazott motorban.
- **JS újraimplementációk számításigényes algoritmusokhoz** — kriptográfia, tömörítés, elemzés. A PHP natív megfelelői 1000× gyorsabbak; használja azokat.

A megfelelő gondolati modell: a Phasis **ragasztóréteg** a PHP-alakú alkalmazásokba ágyazott, JS-alakú logikához. A PHP-gazda végzi a számításokat; a JS-réteg kezeli a konfigurációt, az elágazásokat és a kisebb átalakításokat.

## Mitől gyors a motor (egy naiv fastruktúra-bejáróhoz képest)

- **Bájtkód-VM** — a gyakran végrehajtott diszpécselések többsége a `VM::execute` opcode-váltásán fut keresztül, nem az AST-n.
- **Egyedi hívásiverem-kezelés** — minden JS hívás állapotát a `VM::execute`-n belül tartja, a hívó keretét pedig egy készletbe menti; minden JS híváshoz nem jön létre új PHP keret. Lásd: [Bájtkód-VM § Egyedi hívásiverem-kezelés](https://phasis.inline0.dev/hu/docs/advanced/bytecode-vm).
- **Inline gyorsítótárak** — a programszámlálóhelyenkénti monomorf gyorsítótár kihagyja a prototípuslánc bejárását a példányon végzett prototípusmetódus-olvasásoknál (az `c.method()` mintánál).
- **Keretpillanatképes generátorok** — az egyszerű generátortörzsek a diszpécselés állapotát egy halomobjektumba mentve függesztik fel a végrehajtást, így nem kell átlépniük a PHP Fiberbe.
- **JsToPhp transzpiláló** — a numerikus vagy sok lokális változót használó törzsek (beleértve a `obj.method()`, `new Ctor()` és `this.member` olvasásokat) PHP lezárásokra fordulnak, amelyeket a PHP 8.5 nyomkövető JIT-je natív gépi kóddá alakít.
- **JSON.stringify gyorsítótár** — a `JSON.stringify(o)` az eredményét a bemeneti objektumon tárolja tranzitív verzióérvénytelenítéssel, gyorsítva az `JSON.parse(JSON.stringify(o))` mélymásolási idiómát.

## Saját terhelés mérése

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

Ez a `bench/microbench.js` alatt található mikromérési csomagot futtatja — néhány szintetikus terhelést (ciklusos aritmetika, rekurzív függvények, objektum-létrehozás, prototípusmetódus-hívások, tömbbővítés, JSON oda-vissza alakítás stb.), majd tesztenként kiírja a medián futásidőt. Józan ész szerinti ellenőrzésként hasznos; az aktuális számok minden CI-mérési futáskor bekerülnek a [`BENCH.md`](https://github.com/inline0/phasis/blob/main/BENCH.md) helyre.

A saját kód méréséhez cserélje ki tetszőleges szkriptre:

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

PHP-szintű profilozáshoz a Xdebug profilozója pontosan úgy működik a Phasis-val, mint bármely más PHP alkalmazással. Futtasson egy szkriptet a `xdebug.mode=profile` alatt, majd vizsgálja meg a cachegrind kimenetét, hogy lássa, mely `Phasis\` osztályok dominálnak.

## Ütemterv

A megvalósíthatóság durva sorrendjében ezek csökkentenék leginkább a V8 lemaradását:

- **Polimorf inline gyorsítótárak** — egyetlen `LOAD_MEMBER` hívási hely 2–4 gyorsítótárazott alakot is kezelhetne, mielőtt lassú diszpécselésre vált. Ez a heterogén fogadókon dolgozó kódnak segít.
- **`yield*` és try-with-yield a keretpillanatképes generátorok útvonalán** — ezek az alakok jelenleg a Fiber-alapú fastruktúra-bejáróra kerülnek. A pillanatképek támogatásához mindegyikhez explicit állapotgép-kezelés kell (a delegált iterátor továbbítása, a felfüggesztés alatt megőrzött kezelőverem).
- **Aszinkron generátorok és `await` pillanatképeken** — a specifikáció a generátor felfüggesztését a mikrotask-sorral kombinálja. Amint a bájtkód törzse mindkét `yield` és `await` működést támogatja, az aszinkron generátorok is alkalmassá válnak a pillanatképezésre.
- **Paramétertípusok kikövetkeztetése a JsToPhp-ban** — a függvényparaméterek alapértelmezés szerint numerikus típusúak, ezért a `function (obj) { obj.method() }` megszakítja a fordítást. Ha a paraméterek objektumtípusát a törzsön belüli használatukból következtetnénk ki, a függvényargumentumokon végzett metódushívásokhoz nem kellene a fogadót helyben, a `new` segítségével létrehozni.
- **Közvetlen opcache-kibocsátás** — a `eval()` lépés kihagyásával a JsToPhp közvetlenül írná ki az opcache-formátumú opcode-okat. Ez a legnagyobb falat; a többi a meglévő architektúrán belül megvalósítható.

Ezek egyike sem szükséges azokhoz a beágyazási terhelésekhez, amelyeket a Phasis céloz.
