
# المعايير

Phasis أبطأ **بنحو درجتين من حيث المقدار مقارنةً بـ V8** عند التعامل مع JavaScript المقيدة بعملية التوزيع. هذا الحد الأقصى هو التكلفة الملازمة لمفسر مستضاف على PHP مقارنةً بمترجم JIT أصلي. السؤال الذي ينبغي لمن يدمج الأداة طرحه ليس «كيف يقارن أداؤه بـ V8؟»، بل «هل هو سريع بما يكفي لما أفعله؟». والإجابة هي نعم في معظم أعباء عمل التضمين.

## متى لا يكون الحد مهمًا

- **إنشاء القوالب** — عرض بأسلوب SSR لصفحة اعتيادية في أقل بكثير من 10 ms.
- **قواعد التحقق** — يكتمل تنفيذ JS الذي يقدّمه المستخدم للتحقق من النماذج خلال ميكروثوانٍ.
- **تحويلات البيانات** — يكتمل تطبيق `array.map(transform)` على مئات العناصر خلال عشرات الملّي ثانية.
- **مشغّلات البيئات المعزولة** — تترك النصوص البرمجية القصيرة التي يقدّمها المستخدم، مع حدّ للمضيف قدره 1 ثانية، هامشًا زمنيًا واسعًا.

## متى يكون الحد مهمًا

- **حلقات داخلية كثيفة الحسابات** — معالجة الصور، واختزال المصفوفات الكبيرة، والمحاكاة. انقل الحساب إلى مكتبة PHP أصلية وأتحها كـ[دالة مضيف](https://phasis.inline0.dev/ar/docs/interop/host-functions).
- **الرسوم المتحركة الآنية** — كل ما يقود 60 fps. يجب أن تكون شيفرة JS هذه في العميل (المتصفح أو التطبيق الأصلي)، لا في المحرك المضمّن.
- **إعادة تنفيذ خوارزميات مكلفة حسابيًا بـJS** — التشفير والضغط والتحليل. لدى PHP بدائل أصلية أسرع بـ1000×؛ استخدمها.

النموذج الذهني المناسب: Phasis **طبقة ربط** لمنطق بصيغة JS مضمّن في تطبيقات بصيغة PHP. يتولى المضيف PHP الحسابات، وتتولى طبقة JS الإعدادات والتفرّع والتحويلات الصغيرة.

## ما الذي يجعل المحرك سريعًا (مقارنةً بمتجوّل شجرة ساذج)

- **آلة البايت كود** — تمر معظم عمليات الإرسال الساخنة عبر مفتاح عمليات `VM::execute`، لا عبر AST.
- **مكدس استدعاءات مخصص** — يحتفظ كل استدعاء JS بحالته داخل `VM::execute` ويحفظ إطار المستدعي في مجموعة؛ فلا يُنشأ إطار PHP جديد لكل استدعاء JS. راجع [آلة البايت كود § مكدس الاستدعاءات المخصص](https://phasis.inline0.dev/ar/docs/advanced/bytecode-vm).
- **ذاكرات التخزين المؤقت المضمنة** — تجعل ذاكرة أحادية الشكل لكل PC قراءات طريقة النموذج الأولي على نسخة (نمط `c.method()`) تتجاوز اجتياز سلسلة النماذج الأولية.
- **مولّدات لقطة الإطار** — تعلّق أجسام المولّدات البسيطة بالتقاط حالة الإرسال في كائن على الكومة بدلًا من العبور عبر Fiber من PHP.
- **محوّل JsToPhp** — تُترجم الأجسام التي تكثر فيها الأعداد أو المتغيرات المحلية (بما فيها قراءات `obj.method()` و`new Ctor()` و`this.member`) إلى إغلاقات PHP يخفضها JIT التتبّعي في PHP 8.5 إلى شيفرة آلة أصلية.
- **ذاكرة تخزين مؤقت لـJSON.stringify** — يخزّن `JSON.stringify(o)` مخرجاته في كائن الإدخال مع إبطال للإصدارات المتعدية، ما يسرّع أسلوب الاستنساخ العميق `JSON.parse(JSON.stringify(o))`.

## قياس أحمال العمل لديك

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

يشغّل هذا مجموعة الاختبارات المعيارية المصغّرة المرفقة ضمن `bench/microbench.js` — مجموعة من أحمال العمل الاصطناعية (حسابات الحلقات، والدوال递归ية، وإنشاء الكائنات، واستدعاءات طرائق النماذج الأولية، وإضافة عناصر إلى المصفوفات، وذهابًا وإيابًا لـJSON، وغيرها) ويطبع متوسط زمن التنفيذ لكل اختبار. يفيد كفحص أولي؛ والأرقام الحالية محفوظة في [`BENCH.md`](https://github.com/inline0/phasis/blob/main/BENCH.md) عند كل تشغيل لاختبارات CI المعيارية.

لشيفرتك الخاصة، استبدل أي نص برمجي:

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

لتحليل الأداء على مستوى PHP، يعمل محلّل الأداء في Xdebug مع Phasis تمامًا كما يعمل مع أي تطبيق PHP آخر. شغّل نصًا برمجيًا باستخدام `xdebug.mode=profile` وافحص مخرجات cachegrind لمعرفة فئات `Phasis\` المهيمنة.

## خارطة الطريق

ما الذي سيقلّص الفجوة مع V8 أكثر، مرتّبًا تقريبًا حسب سهولة التنفيذ:

- **ذاكرات تخزين مؤقت مضمنة متعددة الأشكال** — تتيح لموضع استدعاء `LOAD_MEMBER` واحد الاحتفاظ بنمطين إلى 4 أنماط مخزّنة قبل الرجوع إلى الإرسال البطيء. يفيد هذا الشيفرة التي تعالج مستقبلات غير متجانسة.
- **`yield*` وtry-with-yield ضمن مسار مولّدات لقطة الإطار** — تُوجّه هذه البنى حاليًا إلى متجوّل الشجرة المدعوم بـFiber. يحتاج كل منها إلى معالجة صريحة بآلة حالات (تمرير المفوّض للمتكرّر، والحفاظ على مكدس المعالجات أثناء التعليق) قبل أن تصبح آمنة لالتقاط اللقطات.
- **المولّدات غير المتزامنة و`await` على اللقطات** — تجمع المواصفات بين تعليق المولّد وطابور المهام الدقيقة. ما إن يدعم جسم البايت كود كلاً من `yield` و`await`، ستصبح المولّدات غير المتزامنة ملائمة لالتقاط اللقطات أيضًا.
- **استنتاج أنواع المعاملات في JsToPhp** — تكون أنواع معاملات الدوال رقمية افتراضيًا، لذلك يتراجع المترجم عند `function (obj) { obj.method() }`. واستنتاج معاملات ذات نوع كائن من طريقة استخدامها في الجسم سيتيح استدعاء الطرائق على معاملات الدوال دون اشتراط إنشاء المستقبل محليًا عبر `new`.
- **إصدار مباشر لـopcache** — تجاوز خطوة `eval()` في JsToPhp عبر كتابة عمليات بتنسيق opcache مباشرةً. هذه أعمق البنود؛ ويمكن تنفيذ البقية ضمن البنية الحالية.

لا يلزم أي من هذه التحسينات لأحمال العمل المضمّنة التي يستهدفها Phasis.
