OPcache وJIT في PHP: مكسب الأداء الحقيقي وحدوده
OPcache يحفظ الكود المترجَم في الذاكرة فيوفّر إعادة تحليل كل ملف في كل طلب، ويرفع الأداء غالباً بين مرتين وثلاث مرات. JIT مكسب إضافي للحساب المكثّف لا لتطبيقات الويب التي يحكمها الإدخال والإخراج.
OPcache هو أرخص وأسرع تحسين أداء تحصل عليه في PHP، وغالباً مفعّل أصلاً لكن بإعدادات غير مضبوطة للإنتاج. الفكرة أن PHP لغة مفسَّرة: في كل طلب تقرأ ملفات الكود من القرص، تحلّلها نصّاً، وتترجمها إلى opcodes قبل التنفيذ، ثم ترمي هذا كله في نهاية الطلب لتعيده من الصفر في الطلب التالي. OPcache يكسر هذه الدورة: يترجم كل ملف مرة واحدة ويحفظ الـ opcodes في الذاكرة المشتركة، فتخدم الطلبات التالية من نسخة جاهزة بلا قراءة قرص ولا إعادة تحليل. النتيجة العملية على تطبيق Laravel أو WordPress نموذجي: زيادة في عدد الطلبات المخدومة في الثانية تتراوح غالباً بين مرتين وثلاث مرات، وانخفاض ملموس في استهلاك vCPU لأن أثقل خطوة (الترجمة) لم تعد تتكرر. الجواب المباشر: فعّل OPcache واضبطه للإنتاج أولاً، ثم فكّر في JIT فقط إن كان حملك حسابياً لا يحكمه الإدخال والإخراج.
كيف يعمل OPcache وما الذي يوفّره فعلاً
عند أول طلب لملف، يترجمه PHP ويخزّن ناتجه في منطقة ذاكرة مشتركة يحدّدها opcache.memory_consumption. الطلبات اللاحقة على نفس الملف تقفز مباشرة إلى التنفيذ. التطبيق الحديث قد يحمّل مئات الملفات في كل طلب، فتخيّل توفير إعادة تحليلها آلاف المرات في الدقيقة. هذا التوفير هو ما يخفض زمن الاستجابة ويحرّر المعالج لخدمة طلبات أكثر على نفس السيرفر. يخدم هذا مباشرة الشركات التي تشغّل أنظمتها المخصّصة على خادم سحابي، حيث كل نقطة مئوية من vCPU مُوفّرة تعني سعة أكبر قبل الحاجة لترقية.
الإعدادات الحرجة للإنتاج
الفرق بين OPcache مضبوط وغير مضبوط كبير. هذه أهم المفاتيح:
| الإعداد | الدور | قيمة إنتاج نموذجية |
|---|---|---|
| opcache.memory_consumption | حجم الذاكرة للـ opcodes | 128 إلى 256 ميغابايت |
| opcache.max_accelerated_files | أقصى عدد ملفات محفوظة | 20000 لتطبيق كبير |
| opcache.validate_timestamps | هل يفحص تغيّر الملفات كل طلب | 0 في الإنتاج |
| opcache.interned_strings_buffer | ذاكرة توحيد النصوص المكرّرة | 16 إلى 32 ميغابايت |
أخطر مفتاح هو validate_timestamps. حين يكون 1، يفحص PHP في كل طلب هل تغيّر الملف على القرص ليعيد ترجمته، وهذا فحص قرص متكرر بلا فائدة في الإنتاج لأن الكود ثابت بين النشرات. اجعله 0 في الإنتاج لتلغي هذا الفحص كلياً، لكن تذكّر الثمن: لن يرى السيرفر أي تعديل على الكود حتى تمسح ذاكرة OPcache أو تعيد تشغيل PHP-FPM. اجعل ذلك خطوة أخيرة في نص النشر. أما max_accelerated_files فإن كان أقل من عدد ملفات مشروعك الفعلي فستُطرد ملفات من الذاكرة وتُترجم من جديد، فاضبطه أعلى من عدد ملفات التطبيق.
راقب معدل الإصابة
الرقم الذي يخبرك أن OPcache يعمل بكفاءة هو معدل الإصابة (hit rate). في إنتاج صحّي يجب أن يتجاوز 99%. إذا رأيته أقل، فغالباً memory_consumption صغير جداً أو max_accelerated_files أقل من ملفاتك، فالذاكرة تمتلئ وتُطرد ملفات ثم يُعاد تحليلها. راقب أيضاً الذاكرة المستهلكة وعدد الملفات المخزّنة، فهذه المؤشرات تكشف إن كنت بحاجة لرفع الحدود.
متى يفيد JIT فعلاً
JIT (المترجم لحظة التنفيذ) أُضيف في PHP 8، وكثيرون توقّعوا منه تسريع كل شيء، لكن الواقع أدقّ. JIT يحوّل الـ opcodes الساخنة إلى كود آلة أصلي يعمل مباشرة على المعالج، فيربح في العمليات الحسابية الكثيفة: معالجة الصور، الرياضيات العددية، الخوارزميات التي تدور ملايين المرات على بيانات في الذاكرة. لكن تطبيق الويب النموذجي لا يقضي وقته في الحساب، بل ينتظر: استعلام قاعدة بيانات، قراءة ملف، استدعاء واجهة خارجية. هذا الانتظار (الإدخال والإخراج) لا يسرّعه JIT إطلاقاً، لأنه لا يتعلّق بسرعة تنفيذ الكود بل بانتظار مورد خارجي. لذا على تطبيق Laravel يحكمه قاعدة البيانات، قد يكون مكسب JIT بضع نقاط مئوية فقط، بينما على مهمة حسابية بحتة قد يضاعف السرعة.
الخلاصة العملية: OPcache مكسب مضمون لكل تطبيق PHP بلا استثناء، فعّله دائماً. JIT مكسب مشروط، جرّبه بأرقام قبل/بعد على حملك الفعلي، ولا تفترض أنه سيسرّع تطبيق ويب عادياً. إن كنت تبني حملاً حسابياً حقيقياً مثل معالجة نماذج ذكاء، فقد يفيدك أكثر توجيه العمل إلى استضافة AI بقوالب جاهزة بدل عصر JIT في PHP.
أرقام قبل/بعد على تطبيق نموذجي
لتقيس الأثر فعلاً، لا تخمّن. شغّل اختبار حمل على صفحة تمثّل تطبيقك، مرة بـ OPcache معطّل ومرة بعد ضبطه للإنتاج. النمط المتكرّر الذي نراه: تطبيق يخدم نحو 150 طلباً في الثانية بلا OPcache يقفز إلى نحو 400 طلب في الثانية بعد تفعيله وضبطه، مع انخفاض متوسط زمن الاستجابة إلى النصف تقريباً وانخفاض استهلاك vCPU لأن الترجمة المتكرّرة اختفت. هذا التحسّن يعني عملياً أن سيرفر أعمال بأربع أنوية قد يحمل ضعف الزيارات قبل أن تفكّر في الترقية.
ترتيب التحسين الصحيح
ابدأ دائماً بالأرخص أثراً: فعّل OPcache واضبطه، فهذا يعطي أكبر مكسب بأقل جهد. بعده حسّن الاستعلامات البطيئة وأضف الفهارس، لأن أغلب بطء تطبيقات الويب في قاعدة البيانات لا في تنفيذ PHP. ثم فكّر في تخزين مؤقت للنتائج المتكرّرة، وأخيراً إن بقي عندك حمل حسابي حقيقي بعد كل ذلك، جرّب JIT وقس. تشغيل JIT قبل ضبط OPcache أو تحسين قاعدة البيانات هو تحسين للمكان الخطأ.
preload: خطوة أبعد من OPcache
PHP يوفّر ميزة أعمق من OPcache العادي اسمها preload، تحمّل ملفات محدّدة مرة واحدة عند إقلاع PHP-FPM وتبقيها في الذاكرة طوال عمر العملية، لا لكل طلب فقط بل مشتركة بين كل الطلبات دون إعادة فحص. الفائدة أن الأصناف والدوال المحمّلة مسبقاً تصير جاهزة فوراً بلا أي تحميل، ما يقصّ جزءاً إضافياً من زمن الإقلاع. لكن لها ثمن إداري: أي تعديل على ملف محمّل مسبقاً لا يظهر حتى تعيد تشغيل PHP-FPM كاملاً، لا مجرد مسح الذاكرة. لذلك preload مناسب للمكتبات المستقرّة التي لا تتغيّر بين النشرات، لا لكودك الذي تعدّله يومياً. اعتبره تحسيناً متقدّماً بعد أن تضبط OPcache الأساسي وتقيس أنك ما زلت تدفع في الإقلاع.
نقطة مهمة عند القياس: تأكد أنك تختبر في بيئة تشبه الإنتاج فعلاً. كثيرون يقيسون على جهاز تطوير بـ validate_timestamps مفعّلاً ثم يستغربون فرق الأرقام. البيئة العادلة للقياس هي نفس إعدادات الإنتاج بالضبط، وإلا فأنت تقارن حالتين مختلفتين وتخرج بنتيجة مضلّلة.
OPcache وعدد العمليات
OPcache ذاكرة مشتركة بين كل عمليات PHP-FPM على السيرفر، فلا يتضاعف استهلاكه مع عدد العمليات، هذا في صالحك. لكن انتبه أن حجم الذاكرة الذي تخصّصه له يُقتطع من ذاكرة السيرفر الكلية. على باقة بذاكرة محدودة، وازن بين ما تعطيه لـ OPcache وما تتركه لعمليات PHP نفسها ولقاعدة البيانات إن كانت على نفس السيرفر. رقم 128 ميغابايت للـ OPcache معقول لأغلب التطبيقات، وترفعه فقط إن رأيت معدل الإصابة ينزل أو الذاكرة تمتلئ، لا لمجرد الاحتياط.
OPcache على الاستضافة المُدارة
لو كان تطبيقك على استضافة سحابية مُدارة بلوحة cPanel بدل سيرفر تديره بنفسك، فغالباً OPcache مفعّل ومضبوط لك من طرفنا بإعدادات إنتاج معقولة، فلا تحتاج لمسّه. هذا أحد معاني الإدارة: طبقات الأداء الأساسية مضبوطة سلفاً. لكن إن كنت تدير سيرفرك بنفسك على خادم سحابي، فالمسؤولية عليك، والمكسب كبير مقابل جهد يسير. اعرف أيّ نموذج تشغيل أنت فيه قبل أن تبحث عن إعداد قد يكون مضبوطاً أصلاً، فتوفّر وقتك وتوجّهه لتحسين استعلاماتك حيث يكمن أغلب البطء الحقيقي.
الخلاصة: خطوات عملية
فعّل OPcache على كل سيرفر إنتاج، وارفع memory_consumption إلى 128 أو 256 ميغابايت وmax_accelerated_files فوق عدد ملفات مشروعك. اجعل validate_timestamps صفراً في الإنتاج وامسح الذاكرة في نهاية كل نشر. راقب معدل الإصابة وأبقه فوق 99%. لا تفعّل JIT إلا بعد قياس أنه يفيد حملك الحسابي، ولا تتوقّع منه سحراً في تطبيق يحكمه الإدخال والإخراج. لو تحتاج سيرفراً سعودياً بزمن استجابة نحو 8ms من الرياض يشغّل تطبيقك بكفاءة، فراجع الخادم السحابي واختر باقة تناسب حملك، فالترقية فورية حين تكبر.


