تنظیم بهینه OPcache در وردپرس یعنی هم‌خوان‌کردن مقدار حافظه، تعداد فایل قابل کش و بازه اعتبارسنجی با الگوی واقعی اجرای کد، به‌گونه‌ای که کامپایل مجدد فایل‌های PHP فقط در موارد ضروری رخ دهد.

تنظیمات پیش‌فرض OPcache برای شروع کار کافی است، اما زیر بار واقعی وردپرس نه.

سه متغیر کلیدی این ناکافی‌بودن را می‌سازند: opcache.memory_consumption، opcache.max_accelerated_files و opcache.revalidate_freq.

هر یک از این سه، اگر با اندازه واقعی سایت هم‌خوان نباشد، یا منجر به پر شدن حافظه OPcache می‌شود یا باعث می‌شود تغییرات کد دیر اعمال شوند.

هدف این نوشته، رسیدن از پیکربندی پیش‌فرض به تنظیمی است که در محیط تولید قابل دفاع بماند.

شایع‌ترین تجربه‌ای که با OPcache دارم این است: کسی یک فایل PHP را ویرایش می‌کند، صفحه را دوباره می‌خواند و تغییری نمی‌بیند. به‌جای بررسی تنظیمات، به سراغ کش افزونه یا کش مرورگر می‌رود و مدتی را در مسیر اشتباه طی می‌کند. ریشه، در همان چند خط تنظیم OPcache است که کسی وقت نکرده بازشان کند.

OPcache دقیقاً چه چیزی را کش می‌کند

PHP در هر اجرا کد منبع را می‌خواند، به Opcode تبدیل می‌کند و سپس اجرا می‌کند. دو مرحله اول هزینه دارند. OPcache نتیجه این تبدیل را در حافظه نگه می‌دارد تا در درخواست‌های بعدی، مرحله خواندن و کامپایل حذف شود.

نتیجه این کار، کاهش مصرف CPU و کاهش زمان پاسخ داینامیک است. در سایت‌های وردپرسی که هر درخواست به ده‌ها یا صدها فایل PHP دسترسی دارد، اثر این حذف قابل توجه است.

OPcache (PHP Opcode Cache) در هسته PHP ادغام شده است و در بیشتر نصب‌ها به‌طور پیش‌فرض فعال است. اما فعال بودن با بهینه بودن تفاوت زیادی دارد.

این لایه، پیش‌نیاز هر مسیر بهینه‌سازی دیگری است. اجرای تنظیم PHP-FPM برای وردپرس بدون OPcache تنظیم‌شده، عملاً یک لایه ظرفیت را بی‌استفاده می‌گذارد.

چرا تنظیمات پیش‌فرض کافی نیست

تنظیمات پیش‌فرض OPcache با فرض یک بار سبک و پروژه‌ای کوچک تنظیم شده‌اند. وردپرس با هسته، افزونه‌ها، قالب و کتابخانه‌های PHP می‌تواند به‌سادگی چند هزار فایل PHP داشته باشد.

مقدار پیش‌فرض opcache.memory_consumption معمولاً ۶۴ یا ۱۲۸ مگابایت است. مقدار پیش‌فرض opcache.max_accelerated_files معمولاً ۲۰۰۰ یا ۴۰۰۰ است. برای یک سایت وردپرسی فعال، این اعداد سریع پر می‌شوند.

وقتی حافظه OPcache پر می‌شود، کش با روش‌های جایگزینی شروع به حذف ورودی‌های قدیمی می‌کند. نتیجه، حالت کش و بی‌ثباتی است که به‌جای صرفه‌جویی، هزینه کامپایل مجدد را بازمی‌گرداند.

وقتی کش پر می‌شود، سرور به‌جای سریع‌تر شدن، کد را بیشتر کامپایل می‌کند؛ اثری که بسیاری آن را به گردن چیز دیگری می‌اندازند.

افزون بر این، OPcache تنها نیست. در ترکیب با بهینه‌سازی Nginx برای وردپرس یا پیکربندی Apache برای وردپرس، مقدار حافظه‌ای که OPcache می‌تواند به‌طور مؤثر استفاده کند به منابع باقی‌مانده سرور بستگی دارد.

opcache.memory_consumption و ابعاد واقعی سایت

این مقدار تعیین می‌کند OPcache چه اندازه حافظه برای نگه‌داشتن Opcode در اختیار داشته باشد. انتخاب این عدد باید بر اساس تعداد و اندازه فایل‌های PHP سایت انجام شود، نه بر اساس توصیه‌های کلی.

opcache.memory_consumption = 256
opcache.interned_strings_buffer = 16
opcache.max_accelerated_files = 20000
opcache.validate_timestamps = 0
opcache.revalidate_freq = 0
opcache.save_comments = 1
opcache.enable_file_override = 1

برای سایت‌های وردپرسی متوسط تا سنگین، مقدار ۲۵۶ مگابایت نقطه شروع معقولی است. سایت‌های فروشگاهی با ووکامرس و افزونه‌های متعدد ممکن است به ۵۱۲ مگابایت یا بیشتر نیاز داشته باشند.

اندازه‌گیری مصرف واقعی حافظه OPcache از طریق صفحه وضعیت داخلی آن انجام می‌شود. عدد used_memory در این گزارش نشان می‌دهد چه مقدار از سقف تخصیص‌یافته مصرف شده است. اگر این عدد به‌طور مداوم نزدیک به سقف باشد، افزایش مقدار لازم است.

در همین مسیر، کاهش مصرف کلی حافظه سایت با بهینه‌سازی کد و حذف افزونه‌های بی‌استفاده، مکمل مستقیم این تنظیم است. مطالبی مانند بهینه‌سازی کدهای PHP نقطه شروع مناسبی برای این کار هستند.

opcache.max_accelerated_files و فایل‌های وردپرس

این مقدار تعیین می‌کند OPcache چند فایل PHP را همزمان نگه دارد. مقدار پیش‌فرض برای وردپرس کافی نیست. اگر تعداد فایل‌های سایت از این سقف عبور کند، بخشی از فایل‌ها بارها و بارها کامپایل می‌شوند.

نکته مهم: این مقدار داخلاً به نزدیک‌ترین عدد اول بزرگ‌تر از خودش تبدیل می‌شود. به همین دلیل، عددهایی مانند ۱۶۲۲۹ و ۳۲۵۳۱ رایج هستند. انتخاب مقداری بین این دو، عملاً به همان سقف بالاتر تبدیل می‌شود.

شمارش دقیق فایل‌های PHP سایت با ابزارهای خط فرمان انجام می‌شود. برای سایت وردپرسی متوسط با چند افزونه فعال، عدد ۱۰۰۰۰ نقطه شروع معقولی است. برای سایت‌های سنگین‌تر، عدد ۲۰۰۰۰ یا بیشتر لازم می‌شود.

نکته‌ای که در پروژه‌ها کمتر دیده می‌شود این است که افزونه‌های سنگین می‌توانند صدها فایل PHP اضافه کنند. پیش از تنظیم OPcache، بهتر است فهرست افزونه‌های فعال و حجم آن‌ها بررسی شود. پیدا کردن افزونه‌های اضافی موضوعی است که در شناسایی افزونه‌های اضافی وردپرس به‌تفصیل آمده است.

revalidate_freq، validate_timestamps و رفتار در محیط توسعه

دو تنظیم به‌هم‌پیوسته رفتار به‌روزرسانی کش را کنترل می‌کنند: opcache.validate_timestamps و opcache.revalidate_freq.

اگر validate_timestamps روی ۱ باشد، OPcache هر بار بررسی می‌کند که آیا فایل روی دیسک تغییر کرده است. اگر revalidate_freq بزرگ‌تر از صفر باشد، این بررسی هر چند ثانیه انجام می‌شود، نه هر بار.

روی سرور تولید که کد به‌طور مکرر تغییر نمی‌کند، تنظیم validate_timestamps = 0 بهترین عملکرد را می‌دهد. اما این تنظیم یک پیامد مهم دارد: تغییرات کد بدون پاک‌کردن OPcache اعمال نمی‌شوند.

این پیامد، دلیل اصلی راه‌اندازی مجدد PHP-FPM پس از هر استقرار است. در جریان‌های استقرار خودکار، این مرحله باید بخشی از فرآیند باشد؛ جزئیات این نوع جریان‌ها در پیاده‌سازی CI/CD برای پروژه‌های وردپرسی بررسی شده است.

در محیط توسعه، تنظیمات باید معکوس باشند: validate_timestamps = 1 با revalidate_freq = 0. این ترکیب اطمینان می‌دهد هر تغییر کد بی‌درنگ اعمال می‌شود. اعمال تنظیمات تولیدی روی محیط توسعه، منبع اصلی سردرگمی در تیم‌های توسعه است.

JIT در PHP 8 و کاربرد واقعی آن

PHP 8 قابلیت کامپایل در زمان اجرا (Just-In-Time) را معرفی کرد. این قابلیت مسیرهای محاسباتی سنگین را به کد ماشین تبدیل می‌کند و در کارهایی مانند پردازش تصویر، رمزنگاری یا عملیات عددی اثر قابل توجهی دارد.

opcache.jit_buffer_size = 64M
opcache.jit = tracing

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

اما اگر افزونه‌ای روی سایت وجود دارد که پردازش سنگین انجام می‌دهد، مقدار JIT می‌تواند محسوس شود. تنظیم این قابلیت باید بر اساس پروفایل واقعی سایت انجام شود، نه بر اساس توصیه‌های عمومی. مطالبی مانند تفاوت PHP ۷ و PHP ۸ می‌تواند تصویر کلی این تغییرات را روشن کند.

interned_strings_buffer و بهینه‌سازی حافظه رشته‌ها

وردپرس رشته‌های تکراری بسیار زیادی دارد: نام توابع، ثابت‌ها، کلیدهای آرایه و نام کلاس‌ها. OPcache این رشته‌ها را در یک بافر مشترک نگه می‌دارد تا از تکرار آن‌ها در حافظه جلوگیری شود.

مقدار پیش‌فرض این بافر معمولاً ۸ مگابایت است که برای سایت‌های کوچک کافی است، اما برای سایت‌های متوسط و سنگین کافی نیست. مقدار ۱۶ یا ۳۲ مگابایت در بیشتر پروژه‌ها بهبود محسوسی می‌دهد.

اثر این تنظیم روی مصرف کلی حافظه سرور به‌صورت غیرمستقیم ظاهر می‌شود. کاهش مصرف حافظه هر فرآیند PHP، سقف مؤثر فرآیندهای FPM را بالا می‌برد و به همین دلیل، این تنظیم کوچک می‌تواند ظرفیت کلی سرور را افزایش دهد.

هم‌خوانی با PHP-FPM

OPcache و PHP-FPM دو لایه مستقل اما به‌هم‌پیوسته هستند. OPcache حافظه‌ای را در سطح فرآیندهای PHP مصرف می‌کند، و این حافظه از حافظه کل سرور کسر می‌شود. اگر تعداد فرآیندهای PHP-FPM زیاد باشد و هر کدام بخواهد از یک OPcache مشترک با اندازه بزرگ استفاده کند، حافظه کل سرور سریع تمام می‌شود.

نکته فنی مهم: OPcache به‌طور پیش‌فرض در حالت shared memory کار می‌کند. یعنی همه فرآیندهای FPM یک نمونه مشترک از OPcache را می‌بینند، نه یک نسخه مستقل هر فرآیند. این ویژگی به‌شدت کارآمد است، چون حافظه صرفه‌جویی می‌شود و همه فرآیندها از یک کش بهره می‌برند.

به همین دلیل، مقدار opcache.memory_consumption در سرورهایی که چند سایت وردپرسی روی آن‌ها اجرا می‌شود باید با احتیاط بیشتری انتخاب شود. تنظیمات باید در سطح کل سرور هم‌خوان باشند، نه فقط در سطح یک سایت.

OPcache مشترک، بهره‌وری حافظه را بالا می‌برد؛ اما حافظه‌ای که اشغال می‌کند از ظرفیت کلی سرور کسر می‌شود، نه از ظرفیت یک سایت.

تفکیک OPcache وب و CLI

OPcache در حالت وب و در حالت خط فرمان (CLI) دو پیکربندی جدا دارد. این تفکیک در بسیاری از پروژه‌ها نادیده گرفته می‌شود و باعث سردرگمی می‌شود.

ابزارهای خط فرمان PHP مانند WP-CLI برای اجرای دستورات مدیریتی وردپرس استفاده می‌شوند. این ابزارها با OPcache تنظیم‌شده برای وب، رفتار متفاوتی نشان می‌دهند. تنظیمات CLI معمولاً باید محدودتر باشند، چون اجرای آن‌ها کوتاه است و کش کردن کد برای اجرای بعدی سود کمی دارد.

; /etc/php/8.2/cli/conf.d/10-opcache.ini
opcache.enable = 1
opcache.enable_cli = 1
opcache.memory_consumption = 128
opcache.max_accelerated_files = 10000
opcache.validate_timestamps = 1
opcache.revalidate_freq = 0

نکته مهم: اگر تنظیمات CLI با تنظیمات وب قاطی شود، ممکن است عملیات استقرار کد با نتیجه‌ای ناهمخوان روبه‌رو شود. تفکیک این دو پیکربندی، عملی ساده اما اثرگذار است.

اشکال‌زدایی و مشاهده وضعیت کش

OPcache یک صفحه وضعیت داخلی دارد که با پیکربندی زیر در محیط توسعه فعال می‌شود. این صفحه نمایش دقیقی از مصرف حافظه، تعداد فایل‌های کش‌شده، نرخ بازدید موفق کش و زمان‌های صرف‌شده ارائه می‌دهد.

; /etc/php/8.2/fpm/conf.d/10-opcache.ini
opcache.enable = 1
opcache.validate_timestamps = 1
opcache.revalidate_freq = 0

; /etc/php/8.2/fpm/pool.d/www.conf
php_admin_value[opcache.file_update_protection] = 0

برای مشاهده گزارش، ابزارهایی مانند opcache-gui یا اسکریپت‌های مشابه به‌کار می‌روند. در محیط تولید، دسترسی به این صفحه باید محدود به آدرس‌های مشخص باشد؛ افشای عمومی این گزارش، اطلاعات سرور را در معرض دید قرار می‌دهد.

سه عدد کلیدی در این گزارش وجود دارد. مقدار used_memory مصرف فعلی حافظه، مقدار free_memory حافظه آزاد و مقدار wasted_memory حافظه هدررفته. اگر wasted_memory به‌طور مداوم بالا باشد، مقدار حافظه تخصیص‌یافته کمتر از نیاز واقعی است.

در همین راستا، تجربه نشان داده است که مشکلات ظاهری مانند عدم امکان ورود به پیشخوان وردپرس گاهی ریشه در پیکربندی OPcache دارند، نه در سیستم احراز هویت. تفکیک این دو منبع خطا، زمان عیب‌یابی را به‌شدت کم می‌کند.

در لایه پایگاه داده هم باید توجه داشت که OPcache فقط کد را کش می‌کند، نه داده. اگر کوئری‌ها کند باشند، سرعت اجرای کد کمکی به بهبود تجربه کاربر نمی‌کند. مسیر بهینه‌سازی کوئری‌های MySQL مکمل ضروری این لایه است.

جدول تصمیم‌گیری تنظیمات کلیدی

تنظیممحیط توسعهمحیط تولیدریسک محیط تولید
validate_timestamps10تغییرات کد بدون راه‌اندازی مجدد اعمال نمی‌شوند
revalidate_freq00در صورت غیرصفر بودن همراه با validate، بررسی مکرر فایل‌ها
memory_consumption128256 یا بیشترپر شدن سریع کش در سایت‌های سنگین
max_accelerated_files400016229 یا 32531حذف مکرر ورودی‌ها از کش
jit_buffer_size00 یا 64Mاثر محدود در بیشتر سایت‌های وردپرسی

اشتباهات رایج

نخستین اشتباه، فعال‌کردن validate_timestamps = 0 در محیط توسعه است. نتیجه، تغییراتی است که اعمال نمی‌شوند و زمان صرف‌شده در اشکال‌زدایی مسیر اشتباه.

دومین اشتباه، نگه‌داشتن مقادیر پیش‌فرض روی سرور تولید است. این انتخاب، بیشترین ظرفیت OPcache را بی‌استفاده می‌گذارد و باعث حذف مکرر ورودی‌ها از کش می‌شود.

سومین اشتباه، انتخاب مقدار حافظه بسیار بزرگ است. مقدار ۱۰۲۴ مگابایت روی سروری که ۴ گیگابایت حافظه کل دارد، از ظرفیت دیگر لایه‌ها می‌کاهد.

چهارمین اشتباه، نادیده گرفتن interned_strings_buffer است. این تنظیم کوچک، اثر قابل توجهی روی مصرف حافظه سرورهای چندسایتی دارد.

پنجمین اشتباه، فراموش‌کردن پاک‌سازی OPcache پس از هر استقرار است. در جریان‌های استقرار خودکار، این مرحله باید بخشی از فرآیند باشد؛ همین موضوع در بهینه‌سازی پیشرفته دیتابیس وردپرس نیز به‌عنوان یک الگوی کلی تأکید شده است: هر تغییر ساختاری باید همراه با اعتبارسنجی و پاک‌سازی کش باشد.

ششمین اشتباه، فعال‌کردن JIT روی سایت‌هایی است که هیچ باری محاسباتی سنگین ندارند. این کار، حافظه OPcache را بی‌دلیل مصرف می‌کند بدون آنکه اثر محسوسی داشته باشد.

هر تنظیمی که با الگوی واقعی بار سایت هم‌خوان نباشد، حتی اگر درست به‌نظر برسد، در عمل به بدهی فنی تبدیل می‌شود.

پرسش‌های پرتکرار درباره OPcache در وردپرس

آیا OPcache به‌طور پیش‌فرض روی سرورهای وردپرسی فعال است؟

در بیشتر نصب‌های مدرن PHP، OPcache فعال است؛ اما مقادیر پیش‌فرض آن برای سایت‌های کوچک تنظیم شده و برای سایت‌های وردپرسی فعال کافی نیست. فعال بودن با بهینه بودن دو موضوع متفاوت است.

چرا تغییرات کد روی سرور اعمال نمی‌شوند؟

اگر validate_timestamps روی صفر باشد، OPcache فایل‌ها را بدون بررسی مجدد از حافظه سرو می‌کند. این تنظیم بهترین عملکرد را می‌دهد اما نیازمند راه‌اندازی مجدد PHP-FPM یا پاک‌سازی صریح کش پس از هر استقرار است.

چه مقدار حافظه برای OPcache کافی است؟

عددی ثابت وجود ندارد. مقدار مناسب از اندازه واقعی سایت و تعداد فایل‌های PHP آن به‌دست می‌آید. برای سایت‌های وردپرسی متوسط، ۲۵۶ مگابایت نقطه شروع معقولی است. اندازه‌گیری مصرف واقعی از طریق گزارش داخلی OPcache صورت می‌گیرد.

آیا JIT سرعت وردپرس را افزایش می‌دهد؟

در بیشتر سایت‌های وردپرسی اثر محسوسی ندارد، چون بار اصلی روی ورودی-خروجی و پایگاه داده است. اگر افزونه‌ای با پردازش محاسباتی سنگین روی سایت فعال باشد، JIT می‌تواند مفید باشد. تنظیم آن باید بر اساس پروفایل واقعی انجام شود.

آیا OPcache جایگزین افزونه کش است؟

خیر. OPcache کد PHP را کش می‌کند، در حالی که افزونه کش پاسخ HTML کامل را ذخیره می‌کند. این دو در دو لایه مختلف کار می‌کنند و مکمل یکدیگرند. سایت‌هایی که از بهترین افزونه‌های کش وردپرس استفاده می‌کنند، در ترکیب با OPcache تنظیم‌شده به بهترین نتیجه می‌رسند.

آیا OPcache برای همه سایت‌های وردپرسی توصیه می‌شود؟

بله، به شرط پیکربندی متناسب. برای محیط توسعه، تنظیمات باید معکوس شوند تا تغییرات کد بی‌درنگ اعمال شوند. برای محیط تولید، بهترین عملکرد با غیرفعال‌کردن بررسی مکرر فایل‌ها و راه‌اندازی مجدد پس از استقرار حاصل می‌شود.

چه زمانی باید OPcache را غیرفعال کرد؟

در شرایط عادی، هرگز. غیرفعال‌کردن OPcache تنها به‌عنوان یک مرحله تشخیصی موقت برای رد کردن احتمال کش شدن کد قدیمی معنا دارد. پس از تشخیص، باید بی‌درنگ بازفعال شود؛ نبود آن به‌معنای از دست دادن بخشی از ظرفیت سرور است.

یک نکته برای ادامه مسیر

تنظیم OPcache یک چرخه است، نه یک فهرست. مقدار حافظه را می‌سنجید، تعداد فایل‌ها را با اندازه واقعی سایت مقایسه می‌کنید، رفتار محیط تولید را از محیط توسعه جدا می‌کنید و پس از هر استقرار، کش را پاک می‌کنید.

اگر روی سرور خودتان این مسیر را طی کرده‌اید، برایم جالب است بدانم کدام بخش بیشترین زمان را گرفت: انتخاب مقدار مناسب max_accelerated_files، جدا کردن تنظیمات CLI از وب، یا جا انداختن پاک‌سازی OPcache در جریان استقرار. تجربه‌تان را در دیدگاه‌ها بنویسید؛ به‌ویژه اگر راه‌حل متفاوتی پیدا کرده‌اید که می‌تواند برای خواننده بعدی مفید باشد.