
# Tolok Ukur

Phasis **kira-kira dua orde magnitudo lebih lambat daripada V8** pada JavaScript yang dibatasi oleh dispatch. Batas atas itu merupakan biaya bawaan interpreter yang di-host oleh PHP dibandingkan dengan compiler JIT native. Pertanyaan bagi embedder bukanlah "bagaimana perbandingannya dengan V8" — melainkan "apakah cukup cepat untuk kebutuhan saya." Untuk sebagian besar beban kerja embedding, jawabannya ya.

## Saat batas atas tidak menjadi masalah

- **Templating** — render gaya SSR untuk halaman biasa dalam waktu jauh di bawah 10 ms.
- **Aturan validasi** — JS yang diberikan pengguna untuk validasi formulir selesai dalam hitungan mikrodetik.
- **Transformasi data** — `array.map(transform)` pada ratusan item selesai dalam hitungan puluhan milidetik.
- **Runner sandbox** — skrip singkat dari pengguna dengan batas host 1 detik menyisakan banyak ruang.

## Saat batas atas menjadi masalah

- **Loop dalam yang berat komputasi** — pemrosesan gambar, reduksi array besar, simulasi. Pindahkan komputasinya ke pustaka PHP native dan ekspos sebagai [fungsi host](https://phasis.inline0.dev/id/docs/interop/host-functions).
- **Animasi real-time** — apa pun yang berjalan pada 60 fps. JS tersebut sebaiknya berada di klien (browser, aplikasi native), bukan di engine tertanam.
- **Implementasi ulang JS untuk algoritma yang mahal secara komputasi** — kriptografi, kompresi, parsing. PHP memiliki padanan native yang 1000× lebih cepat; gunakan padanan tersebut.

Model mental yang tepat: Phasis adalah **lapisan perekat** untuk logika berbentuk JS yang disematkan dalam aplikasi berbentuk PHP. Host PHP menangani komputasi; lapisan JS menangani konfigurasi, percabangan, dan transformasi kecil.

## Hal yang membuat engine cepat (dibandingkan tree-walker naif)

- **VM Bytecode** — sebagian besar dispatch yang sering terjadi berjalan melalui switch opcode milik `VM::execute`, bukan AST.
- **Call stack khusus** — setiap pemanggilan JS menjaga status di dalam `VM::execute` dan menyimpan frame pemanggil ke dalam pool; tidak ada frame PHP baru untuk setiap pemanggilan JS. Lihat [VM Bytecode § Call stack khusus](https://phasis.inline0.dev/id/docs/advanced/bytecode-vm).
- **Cache inline** — cache monomorfik per-PC membuat pembacaan metode prototipe pada instans (pola `c.method()`) melewati penelusuran rantai prototipe.
- **Generator snapshot frame** — isi generator sederhana ditangguhkan dengan menangkap status dispatch ke objek heap, alih-alih melintasi Fiber PHP.
- **Transpiler JsToPhp** — isi fungsi yang berat pada numerik / variabel lokal (termasuk pembacaan `obj.method()`, `new Ctor()`, dan `this.member`) dikompilasi menjadi closure PHP yang diturunkan oleh tracing JIT PHP 8.5 menjadi kode mesin native.
- **Cache JSON.stringify** — `JSON.stringify(o)` menyimpan output-nya pada objek masukan dengan invalidasi versi transitif, mempercepat idiom deep-clone `JSON.parse(JSON.stringify(o))`.

## Mengukur beban kerja Anda sendiri

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

Perintah ini menjalankan rangkaian microbench yang disertakan di `bench/microbench.js` — beberapa beban kerja sintetis (aritmetika loop, fungsi rekursif, pembuatan objek, pemanggilan metode prototipe, penambahan array, bolak-balik JSON, dan sebagainya) dan mencetak median waktu nyata untuk tiap pengujian. Berguna sebagai pemeriksaan kewajaran; angka saat ini di-commit ke [`BENCH.md`](https://github.com/inline0/phasis/blob/main/BENCH.md) pada setiap kali CI menjalankan benchmark.

Untuk kode Anda sendiri, ganti dengan skrip apa pun:

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

Untuk pembuatan profil tingkat PHP, profiler Xdebug bekerja dengan Phasis sama seperti pada aplikasi PHP lainnya. Jalankan skrip melalui `xdebug.mode=profile` dan periksa output cachegrind untuk melihat kelas `Phasis\` mana yang paling dominan.

## Peta jalan

Hal-hal yang paling berpotensi memperkecil kesenjangan V8, diurutkan secara kasar berdasarkan tingkat kemudahan penerapan:

- **Cache inline polimorfik** — izinkan satu titik pemanggilan `LOAD_MEMBER` menyimpan 2-4 bentuk cache sebelum kembali ke dispatch lambat. Membantu kode yang memproses receiver heterogen.
- **`yield*` dan try-with-yield pada jalur generator snapshot frame** — bentuk-bentuk ini saat ini dialihkan ke tree-walker berbasis Fiber. Masing-masing memerlukan penanganan state machine secara eksplisit (penerusan delegate-iterator, stack handler yang dipertahankan selama suspend) sebelum aman untuk snapshot.
- **Generator asinkron dan `await` pada snapshot** — spesifikasi menggabungkan penangguhan generator dengan antrean microtask. Setelah isi bytecode mendukung `yield` dan `await`, generator asinkron juga akan kompatibel dengan snapshot.
- **Inferensi tipe parameter di JsToPhp** — parameter fungsi secara default bertipe numerik, sehingga `function (obj) { obj.method() }` membuat compiler keluar lebih awal. Inferensi parameter bertipe objek berdasarkan penggunaannya di dalam isi fungsi akan memungkinkan pemanggilan metode pada argumen fungsi tanpa mengharuskan receiver dibuat secara lokal melalui `new`.
- **Emisi opcache langsung** — lewati langkah `eval()` milik JsToPhp dengan menulis opcode berformat opcache secara langsung. Ini item yang paling rumit; yang lain dapat dikerjakan dalam arsitektur yang ada.

Semua ini tidak diperlukan untuk beban kerja embedding yang ditargetkan Phasis.
