Zināmie ierobežojumi
Phasis mērķis ir visos novērojamajos specifikācijas testos darboties identiski V8. Šajā lapā aprakstītas situācijas, kurās praksē šī identitāte izbeidzas — parasti būtisku atšķirību dēļ starp koku šķērsojošu PHP interpretētāju un JIT kompilētu C++ dzinēju.
Veiktspējas griesti
Dzinējs ir koka interpretētājs ar optimistisku baitkoda virtuālo mašīnu un JsToPhp transpilatoru, kas skaitļošanas un lokālo mainīgo intensīvus koda blokus (tostarp obj.method(), new Ctor() un this.member formas) pārveido par vietējām PHP slēguma funkcijām, ko PHP 8.5 izsekojošais JIT var kompilēt mašīnkodā. Lielākā daļa aktīvās izpildes notiek VM pārslēgšanās ciklā vai tieši JIT kompilētā PHP kodā, nevis AST šķērsošanas laikā, taču par katru VM opkodu joprojām jāmaksā PHP izpildes izmaksas, un formas, ko JsToPhp vēl neatbalsta, tiek izpildītas lēnākajā VM. Izpildes robeža noslodzēm, ko ierobežo izsaukumu pārslēgšanās, ir aptuveni 100× lēnāk nekā V8.
Iegultas izpildes gadījumos — kad lietotāja iesniegtā loģika tiek izpildīta ar PHP datiem, satura pārveidošanas konveijeros vai validācijas noteikumos — šī robeža reti ir būtiska. V8 darbība aizņem 100 ms; Phasis — 10 s; abi rādītāji ir krietni zem pieprasījuma taimauta. Lai plaisu vēl samazinātu, JsToPhp būtu jāiemāca vairāk formu (parametru tipu secināšana, await / yield* pārveidošana) vai opcache opkodi jāģenerē tieši, nevis ar eval() starpniecību. Skatiet ceļveža sadaļu “Etalonmērījumi”.
Vairāku aģentu vienlaicīga izpilde
JavaScript SharedArrayBuffer + Atomics.wait + postMessage modelis pieņem, ka resursdators spēj palaist īstus OS pavedienus. PHP to nespēj bez pcntl_fork, kas nav pieejams visos resursdatoros.
Phasis simulē vienu aģentu — Atomics.wait uzreiz atgriež vērtību “not-equal” vai “timed-out”, bet notify vienmēr atgriež 0. Tas iztur visus test262 testus, kas darbojas ar vienu aģentu (ievades validācija, kļūdu scenāriji, paziņojums bez darbības), un aptver 376 no 376 Atomics testiem.
Divu vienlaicīgu aģentu savstarpēju novērošanu pieprasošie testi netiek atbalstīti. Patiesai paralēlai izpildei izmantojiet darba rindu PHP līmenī (Redis, Beanstalkd, …).
Darbības vides semantika
ShadowRealm ir ieviesta, taču katra pakārtotā darbības vide darbojas tajā pašā PHP procesā, kurā atrodas resursdators. Resursdatora funkcijas var nopludināt atsauces starp darbības vidēm, ja neparūpēsieties par to, lai PHP kods būtu izolēts. Specifikācija to pieļauj; V8 nodrošina stingrāku izolāciju, izmantojot atsevišķas v8::Isolate instances.
createRealm() (resursdatora āķis test262) iekšēji izveido jaunu Phasis\Engine un savieno standarta bibliotēku.
Regulāro izteiksmju dzinēja izvēle
Phasis izmanto PHP PCRE2 kā galveno regulāro izteiksmju apstrādes aizmugursistēmu, bet gadījumiem, ko PCRE2 nespēj apstrādāt precīzi, ir pielāgots atbilstības meklētājs (atpakaļskata apgalvojumi ar tveršanas grupām, kvantificētas grupas ar atiestatīšanu, noteiktu /v karodziņu semantika). Pielāgotais meklētājs ir lēnāks par PCRE2, un to izmanto tikai tad, ja izsaukumu pārslēgšana konstatē nesaderīgu rakstu.
Ievērojamās sekas: PCRE2 reģistrjutības pārveidošanas tabula var atšķirties no V8 ICU versijas, it īpaši vecākos Linux distributīvos (Ubuntu 22.04 ir iekļauts ICU 70; Phasis komplektācijā ir ICU 76+ reģistrjutības tabula, kas ignorē resursdatora versijas atšķirības /iu rakstos).
Atmiņas modelis
PHP atsauču skaitīšanas atkritumu savācējs atšķiras no V8 izsekojošā atkritumu savācēja. PHP objekti, ko tvērušas resursdatora slēguma funkcijas, paliek dzīvi, kamēr vien dzinējs glabā šīs funkcijas, un cikli starp tiem netiek savākti, līdz tiek iznīcināts Engine. Kešatmiņām, kuras nevēlaties uzturēt dzīvas, izmantojiet WeakMap / WeakRef.
process.memoryUsage() un līdzīgas tikai V8 pieejamas pārbaudes API nav ieviestas.
Moduļu ielādētājs
ES moduļu ielādētājs atrisina relatīvo importu ceļus, izmantojot failu sistēmu, bet nesaprot komplektētāju konvencijas:
- Nav
node_modulesatrisināšanas. - Nav
package.jsonexportskartes. - Nav faila paplašinājuma noteikšanas (jāraksta
import './foo.mjs', nevisimport './foo'). - Nav HTTP importu.
Tas atbilst tīrajai ECMAScript specifikācijai, taču ne Node darbībai. Pielāgotam moduļu atrisinātājam nav āķa. Lai izmantotu npm pakotnes, pirms nodošanas Phasis apvienojiet tās vienā skriptā vai modulī, izmantojot tādu rīku kā esbuild.
Wasm
WebAssembly nav ieviests. Nav PHP wasm izpildlaika, ar ko to sasaistīt.
Tikai pārlūkprogrammā pieejamās Web API, kuras izlaižam
Phasis ietver pilnu Web Platform Pack (URL, TextEncoder/TextDecoder, atob/btoa, structuredClone, performance, DOMException), pilnu Fetch Pack (fetch, Request, Response, Headers, Body, AbortController/AbortSignal, Blob/File, FormData, EventTarget/Event, pilnu WHATWG Streams, navigator), kā arī crypto (getRandomValues, randomUUID, pilns SubtleCrypto: jaucējvērtības aprēķins, HMAC, AES-GCM/CBC/CTR, RSA-OAEP/PSS/PKCS1, ECDSA, ECDH, HKDF, PBKDF2), WebSocket (konstruktors + RFC 6455 kadru kodētājs/dekodētājs, maināms transports), XMLHttpRequest (veidots uz Fetch transporta bāzes) un īstu notikumu ciklu (setTimeout, setInterval, clearTimeout, clearInterval, queueMicrotask, AsyncContext). Skatiet Web API.
Kas nav iekļauts:
window,document, DOM koks — Phasis nav pārlūkprogramma.localStorage,sessionStorage,IndexedDB— resursdatora puses uzdevumi; iegultās sistēmas izstrādātājs atbild par datu saglabāšanu.Worker,SharedWorker,MessageChannel— nepieciešami īsti OS pavedieni, ko PHP nepiedāvā.- Service Workers, Push API, Notifications, BroadcastChannel — ārpus pārlūkprogrammas nav nozīmes.
Node globālie mainīgie
process, Buffer, __dirname, __filename, require() — arī neviens no tiem nav pieejams. Tās ir Node resursdatora konvencijas, nevis valodas iespējas.
Ja pārnesat Node kodu, aizstājiet require('foo') ar import 'foo', nomainiet process.env.X pret resursdatoram piesaistītu env.X un nododiet __dirname ekvivalentus ceļus no PHP.
Decimāldaļu precizitāte
ECMAScript skaitļi ir IEEE 754 dubultprecizitātes skaitļi. Aprēķinos ar decimāldaļām, kurās ir vairāk nekā 15 nozīmīgo ciparu, zūd precizitāte tāpat kā jebkurā citā JS dzinējā. Precīziem veselu skaitļu aprēķiniem izmantojiet BigInt, bet precīziem daļskaitļu aprēķiniem — JS decimāldaļu bibliotēku.
PHP bcmath tiek izmantots iekšēji BigInt vajadzībām; vienīgā būtiskā atšķirība no V8 ir tā, ka ļoti lielas bigint darbības PHP ir lēnākas nekā V8 C++ implementācijā. Skaitliskā precizitāte ir identiska.