Prestandatester
Phasis är ungefär två storleksordningar långsammare än V8 vid dispatch-begränsade JavaScript. Det taket är den inneboende kostnaden för en interpreter som körs i PHP jämfört med en inbyggd JIT-kompilator. Frågan för den som bäddar in den är inte ”hur står den sig mot V8?” utan ”är den tillräckligt snabb för det jag gör?”. För de flesta inbäddningsarbetsbelastningar är svaret ja.
När prestandataket saknar betydelse
- Mallhantering – SSR-liknande rendering av en typisk sida på långt under 10 ms.
- Valideringsregler – användartillhandahållen JS för formulärvalidering körs på mikrosekunder.
- Datatransformeringar –
array.map(transform)över hundratals objekt tar några tiotals millisekunder. - Sandlådekörning – korta skript från användaren med en värdgräns på 1 sekund lämnar gott om marginal.
När prestandataket spelar roll
- Beräkningstunga inre loopar – bildbehandling, reduktioner av stora arrayer, simuleringar. Flytta beräkningen till ett inbyggt PHP-bibliotek och exponera det som en värdfunktion.
- Animation i realtid – allt som driver 60 fps. Sådan JS hör hemma på klienten (i webbläsaren eller en inbyggd app), inte i den inbäddade motorn.
- JS-omimplementeringar av beräkningstunga algoritmer – kryptografi, komprimering, parsning. PHP har inbyggda motsvarigheter som är 1000× snabbare; använd dem.
Rätt mental modell: Phasis är ett limlager för logik formad som JS som bäddas in i program formade som PHP. Värden på värdsidan PHP hanterar beräkningar; lagret JS hanterar konfiguration, förgreningar och små transformationer.
Vad som gör motorn snabb (jämfört med en naiv trädvandrare)
- Bytecode-VM — den mesta heta dispatchen går genom
VM::executes opkodsväxel, inte AST:t. - Anpassad anropsstack — varje JS-anrop behåller tillståndet i
VM::executeoch sparar anroparens stackram i en pool; ingen ny PHP-ram per JS-anrop. Se Bytecode-VM § Anpassad anropsstack. - Inline-cacher — en monomorf cache per PC gör att läsningar av prototypmetoder på instanser (mönstret
c.method()) kan hoppa över genomgången av prototypkedjan. - Generatorer med stackramsögonblicksbilder — enkla generatorer pausar genom att fånga dispatchtillståndet i ett heap-objekt i stället för att gå via en PHP Fiber.
- JsToPhp-transpilerare — numeriska kroppar med många lokala variabler (inklusive läsningar av
obj.method(),new Ctor()ochthis.member) kompileras till PHP-closures som PHP 8.5:s spårande JIT sänker till inbyggd maskinkod. - JSON.stringify-cache —
JSON.stringify(o)cachar sin utdata på indataobjektet med transitiv versionsogiltigförklaring, vilket snabbar upp det djupklonande idiometJSON.parse(JSON.stringify(o)).
Mäta din egen arbetsbelastning
php bench/run.php
Det här kör mikrobänksvit som levereras under bench/microbench.js — en handfull syntetiska arbetsbelastningar (looparitmetik, rekursiva funktioner, objektskapande, anrop av prototypmetoder, array-push, JSON tur och retur med mera) och skriver ut medianväggtid per test. Användbart som rimlighetskontroll; aktuella siffror checkas in i BENCH.md vid varje CI-bänkkörning.
För din egen kod kan du byta in valfritt skript:
php -d xdebug.mode=off bench/run.php path/to/your-script.js
För profilering på PHP-nivå fungerar Xdebugs profiler med Phasis precis som med alla andra PHP-program. Kör ett skript under xdebug.mode=profile och granska cachegrind-utdata för att se vilka Phasis\-klasser som dominerar.
Färdplan
Vad som skulle minska V8-gapet mest, ungefär i prioritetsordning efter genomförbarhet:
- Polymorfa inline-cacher — låt en enda
LOAD_MEMBER-anropsplats hålla 2–4 cachade former innan den faller tillbaka till långsam dispatch. Hjälper kod som bearbetar heterogena mottagare. yield*och try-with-yield i generatorvägen med stackramsögonblicksbilder — dessa former går för närvarande via den Fiber-baserade trädtolkaren. Var och en kräver uttrycklig hantering av tillståndsmaskinen (vidarebefordran av delegerade iteratorer, hanterarstack bevarad under paus) innan de kan hanteras säkert med ögonblicksbilder.- Asynkrona generatorer och
awaitmed ögonblicksbilder — specifikationen kombinerar generatorpauser med mikrouppgiftskön. När bytekodskroppen stöder bådeyieldochawaitblir även asynkrona generatorer lämpliga för ögonblicksbilder. - Inferens av parametertyper i JsToPhp — funktionsparametrar får numerisk typ som standard, så
function (obj) { obj.method() }får kompilatorn att avbryta. Att härleda objekttyper för parametrar utifrån hur de används i kroppen skulle möjliggöra metodanrop på funktionsargument utan att mottagaren behöver skapas lokalt vianew. - Direkt generering av opcache — hoppa över JsToPhps steg
eval()genom att skriva opkoder direkt i opcache-format. Det mest omfattande arbetet; de övriga går att genomföra inom den befintliga arkitekturen.
Inget av detta behövs för de inbäddningsarbetsbelastningar som Phasis riktar sig till.