behnam hoseyni
behnam hoseyni
خواندن ۴ دقیقه·۲ سال پیش

فعال سازی JIT در PHP 8

همونطور که همگی میدونیم PHP در نسخه 8 کامپایلر JIT رو به هسته خودش اضافه کرده که افزایش سرعت قابل توجهی رو همراهش داشته.راستش رو بخواید راه اندازی JIT یکی از گیج کننده ترین کانفیگ های مربوط به extension های PHP هست که تا به امروز دیدم،منتهی چند روش پیکربندی ساده تر هم وجود داره که باز هم برای انجامش باید در مورد پیکربندی JIT دانش عمیقی داشته باشیم، برای همین تو این مقاله با هم این موضوع رو مورد بررسی قرار میدیم.

اول از همه، JIT فقط در صورتی کار می کنه که Opcache فعال باشه که این مورد در اکثر نصب های PHP به صورت پیش فرض فعال است ولی برای اطمینان باید بررسی کنیم که در فایل php.ini مقدارzend_extension برابر Opcache یعنی به این شکل(zend_extension=opcache) و مقدار opcache.enable برابر 1 باشه.بعد از اطمینان از فعال بود Opcache باید خود JIT رو فعال کنیم که این کار با مشخص کردن مقدار opcache.jit_buffer_size در فایل php.ni انجام میشه.


توجه داشته باشید که اگر PHP رو از طریق خط فرمان اجرا می کنیم، می تونیم این گزینه ها را به جای اضافه کردنشون به php.ini از طریق تگ d- نیز ارسال کنیم:

php -d opcache.enable=1 -dopcache.jit_buffer_size=100M

اگر این دستور با مقدار پیش فرض یعنی 0 تنظیم بشه JIT دیگه اجرا نمیشه.

اگر بخوایم JIT رو فقط در محیط خط فرمان تست کنیم، باید به جای opcache.enable از مقدار opcache.enable_cli برای فعال کردن opcache استفاده کنیم:

php -dopcache.enable_cli=1 -dopcache.jit_buffer_size=100M

اگر بخوام دقیق تر توضیح بدم تفاوت بین opcache.enable و opcache.enable_cli در اینه که برای مثال اگه از PHP روی سرور استفاده میکنیم باید از مورد اول و اگه واقعاً یه اسکریپت CLI رو اجرا میکنیم باید از opcache.enable_cli استفاده کنیم.

قبل از ادامه، بیاید مطمئن شیم که JIT واقعاً کار می کنه، یه اسکریپت PHP با محتوای زیر ایجاد میکنیم که از طریق مرورگر یا CLI قابل دسترسی باشد (بسته به جایی که JIT را تست می کنیم):

var_dump(opcache_get_status()['jit']);

خروجی باید چیزی شبیه این باشه:

array(7) {
[&quotenabled&quot]=> bool(true)
[&quoton&quot]=> bool(true)
[&quotkind&quot]=> int(5)
[&quotopt_level&quot]=> int(5)
[&quotopt_flags&quot]=> int(6)
[&quotbuffer_size&quot]=> int(104857584)
[&quotbuffer_free&quot]=> int(104854800)
}

اگر مقدار enable و on برابر true باشن یعنی تا اینجا درست پیش رفتیم.

در مرحله بعد، چندین راه برای پیکربندی JIT وجود داره ( اینجاست که ما به مشکل سختی پیکربندی میخوریم!). میتونیم پیکربندی کنیم که JIT چه زمانی باید اجرا بشه، چقدر باید تلاش کنه تا بهینه بشه و غیره. همه این گزینه ها با استفاده از یک ورودی پیکربندی میشن!

opcache.enable=1
opcache.jit=1255

مقدار پیشفرض برابر 1205 هست که بهتره به 1235 تغییر کنه، این عدد متشکل از چهار رقمِ که هر عدد نماینده یک کانیفگ خاص از مفهومی به نام CRTO هست.

حالا معنی این عدد چیه؟ اگر به RFC مراجعه کنیم تمامی اعداد رو توضیح داده.باید توجه داشته باشیم این اعداد که به نظر فقط یه عدد میان میتونن کانفیگ رو به کل تغییر بدن.

اینجا لیست CRTO رو داریم که در RFC نوشته شده:

O — Optimization level

0 don't JIT
1 minimal JIT (call standard VM handlers)
2 selective VM handler inlining
3 optimized JIT based on static type inference of individual function
4 optimized JIT based on static type inference and call tree
5 optimized JIT based on static type inference and inner procedure analyses

#

T — JIT trigger

0 JIT all functions on first script load
1 JIT function on first execution
2 Profile on first request and compile hot functions on second request
3 Profile on the fly and compile hot functions
4 Compile functions with @jit tag in doc-comments
5 Tracing JIT

#

R — register allocation

0 don't perform register allocation
1 use local liner-scan register allocator
2 use global liner-scan register allocator

#

C — CPU specific optimization flags

0 none
1 enable AVX instruction generation

نکته: RFC این گزینه ها را به ترتیب معکوس فهرست کرده، بنابراین رقم اول نشان دهنده مقدار C، رقم دوم R،رقم سوم T و رقم چهارم C هست. اینکه چرا به سادگی چهار ورودی برای پیکربندی اضافه نشده برام واقعا جای سواله!، احتمالاً برای سریعتر کردن پیکربندی JIT یا شایدم چیزای دیگه؟!

به هر حال، همونطور که گفتم در RFC پیشنهاد شده این عدد برابر 1255 قرار بدیم که یعنی، حداکثر جیتینگ را انجام میده، از JIT ردیابی استفاده می‌کند، از یک تخصیص‌دهنده ثبت اسکن سراسری استفاده میکنه و دستورالعمل AVX را فعال می‌کنه.

بنابراین تنظیمات php.ini ما (یا تگ d-) باید این مقادیر را داشته باشه:

opcache.enable=1
opcache.jit_buffer_size=100M
opcache.jit=1255

نکته :به خاطر داشته باشید که opcache.jit یه گزینه اختیاره که اگر کانفیک هم نشهJIT از یک مقدار پیش فرض استفاده میکنه.

اگر براتون سوال پیش اومده که مقدار پیشفرض چیه باید بگم : opcache.jit=tracing!

برای شمام سوال شد که این همون بالایی نیست؟! دقیقا خودشه! وقتی دیدن عدد نوشتن کاربر پسند نیست اومدن دوتا نام مستعار ایجاد کردن که موقع اجرا به اعداد پیشنهادی خودشون تبدیل میشن. یعنی opcache.jit=tracing و opcache.jit=function.

بنابراین اگر دوست دارید همه چیز رو با جزئیاتی که خودتون میخواین تنظیم کنید باید از لیست بالا استفاده کنید ،اما تنها گزینه‌ای که برای فعال کردن JIT با پیکربندی بهینه‌اش نیاز داریم، opcache.jit_buffer_size است :

opcache.enable=1
opcache.jit_buffer_size=100M
opcache.jit=tracing
jitphp
شاید از این پست‌ها خوشتان بیاید