Zend OPcache: แนวคิด การติดตั้งและการตั้งค่า ค่าใน php.ini และการปิดใช้งาน JIT
Zend OPcache คือส่วนขยายของ PHP ที่คอมไพล์สคริปต์ PHP เป็นไบต์โค้ดแล้วเก็บไว้ในหน่วยความจำที่ใช้ร่วมกัน ทำให้ข้ามขั้นตอนคอมไพล์ได้เมื่อรันไฟล์เดิมซ้ำ เมื่อเปิดใช้งาน JIT บนเซิร์ฟเวอร์ WordPress ที่ใช้ PHP 8.3 แล้วทุกหน้าเกิดข้อผิดพลาด 500 จึงกู้เซิร์ฟเวอร์กลับมาด้วยการคง OPcache ไว้และปิดเฉพาะ JIT
ตั้งแต่ PHP 5.5 เป็นต้นมา OPcache รวมอยู่ใน PHP เป็นค่าเริ่มต้น
1️⃣ แนวคิดของ Zend OPcache: การแคชไบต์โค้ด
ทุกครั้งที่มีคำขอเข้ามา สคริปต์ PHP จะผ่านสามขั้นตอน คือ อ่านไฟล์ คอมไพล์เป็นไบต์โค้ด และรัน เมื่อ OPcache ทำงานอยู่ ตั้งแต่คำขอที่สองของไฟล์เดิมเป็นต้นไป สองขั้นตอนแรกจะหายไปและเหลือเพียงการรัน
หน่วยความจำที่ใช้ร่วมกันซึ่ง OPcache ใช้เก็บไบต์โค้ดถูกใช้ร่วมกันโดยเวิร์กเกอร์ทั้งหมดของ PHP-FPM หากมีหลายเว็บไซต์เชื่อมต่อกับ PHP-FPM ตัวเดียวกัน สคริปต์ของเว็บไซต์เหล่านั้นก็ถูกเก็บในหน่วยความจำที่ใช้ร่วมกันก้อนเดียวกัน
สิ่งที่ OPcache เก็บคือโค้ด PHP ที่คอมไพล์แล้ว ดังนั้นการรัน PHP และการคิวรีฐานข้อมูลยังเกิดขึ้นทุกครั้งที่เปิดหน้าเว็บ การเก็บ HTML ที่สร้างเสร็จแล้วเพื่อข้ามการรัน PHP ไปเลยเป็นหน้าที่ของแคชหน้าเพจ
2️⃣ ตรวจสอบการติดตั้ง PHP OPcache
ตรวจสอบว่าติดตั้ง OPcache แล้วหรือไม่ได้จากบรรทัดสุดท้ายของผลลัพธ์ [php -v]
php -vPHP 8.3.22 (cli) (built: Jun 3 2025 17:17:57) (NTS gcc x86_64)
Copyright (c) The PHP Group
Zend Engine v4.3.22, Copyright (c) Zend Technologies
with Zend OPcache v8.3.22, Copyright (c), by Zend Technologiesหากไม่มีบรรทัดสุดท้าย ให้ติดตั้งด้วย dnf ชื่อแพ็กเกจมักเป็น php-opcache และหากติดตั้ง PHP หลายเวอร์ชันพร้อมกันจากคลังข้อมูล Remi จะมีเวอร์ชันต่อท้าย เช่น php83-php-opcache
dnf -y install php-opcacheแพ็กเกจ php-opcache ของคลังข้อมูล Remi โหลดส่วนขยายผ่านบรรทัด [zend_extension=opcache] ใน [/etc/php.d/10-opcache.ini] หลังติดตั้งแล้ว ให้รีสตาร์ต PHP-FPM เพื่อให้ OPcache มีผลกับคำขอจากเว็บด้วย
3️⃣ การตั้งค่า OPcache: ค่าใน php.ini
การตั้งค่า OPcache อยู่ได้สองที่ คือส่วน [opcache] ของ [/etc/php.ini] และ [/etc/php.d/10-opcache.ini]
php --iniConfiguration File (php.ini) Path: /etc
Loaded Configuration File: /etc/php.ini
Scan for additional .ini files in: /etc/php.d
Additional .ini files parsed: /etc/php.d/10-opcache.ini,ไฟล์ในโฟลเดอร์ php.d ถูกอ่านหลัง php.ini ดังนั้นหากเขียนรายการเดียวกันไว้ทั้งสองที่ ค่าจาก php.d จะมีผล
ตารางด้านล่างแสดงค่าเริ่มต้นของ PHP 8.3 และค่าที่ใช้อยู่บนเซิร์ฟเวอร์ WordPress ที่ตรวจสอบ
| รายการ | ค่าเริ่มต้นของ PHP 8.3 | ค่าที่ใช้ | ความหมาย |
|---|---|---|---|
| opcache.enable | 1 | 1 | เปิดใช้งาน OPcache |
| opcache.enable_cli | 0 | 1 | ใช้กับ PHP บนบรรทัดคำสั่ง (wp-cli เป็นต้น) ด้วย |
| opcache.memory_consumption | 128 | 1024 | หน่วยความจำที่ใช้ร่วมกันสำหรับเก็บไบต์โค้ด (MB) |
| opcache.interned_strings_buffer | 8 | 16 | หน่วยความจำที่เก็บสตริงเดียวกันเพียงครั้งเดียว (MB) |
| opcache.max_accelerated_files | 10000 | 10000 | ขีดจำกัดบนของจำนวนคีย์ที่แคชได้ (ขีดจำกัดจริงคือจำนวนเฉพาะที่เท่ากับหรือมากกว่าค่านี้ เช่น 16229 เมื่อตั้งเป็น 10000) |
| opcache.max_wasted_percentage | 5 | 10 | หากหน่วยความจำไม่พอและพื้นที่ที่สูญเปล่าเกินสัดส่วนนี้ จะล้างแคชแล้วเริ่มใหม่ |
| opcache.validate_timestamps | 1 | 1 | ตรวจสอบว่าไฟล์เปลี่ยนแปลงหรือไม่ |
| opcache.revalidate_freq | 2 | 60 | ระยะเวลาตรวจสอบการเปลี่ยนแปลงของไฟล์ (วินาที) |
| opcache.jit | tracing | disable | รูปแบบของ JIT (ตั้งแต่ PHP 8.4 ค่าเริ่มต้นคือ disable) |
| opcache.jit_buffer_size | 0 | 0 | หน่วยความจำของ JIT หากเป็น 0 JIT จะไม่ทำงาน (ตั้งแต่ PHP 8.4 ค่าเริ่มต้นคือ 64M) |
ค่าที่ใส่ไว้ในส่วน [opcache] ของ [/etc/php.ini] เป็นดังนี้ ขนาดหน่วยความจำกำหนดตามหน่วยความจำของเซิร์ฟเวอร์ และ [opcache.max_accelerated_files] กำหนดตามจำนวนไฟล์ของ WordPress
[opcache]
opcache.enable=1
opcache.enable_cli=1
opcache.memory_consumption=1024
opcache.interned_strings_buffer=16
opcache.max_accelerated_files=10000
opcache.max_wasted_percentage=10
opcache.validate_timestamps=1
opcache.revalidate_freq=60หากใส่บรรทัด [zend_extension] ลงใน php.ini อีกครั้ง ส่วนขยายจะถูกโหลดสองครั้งและมีคำเตือน [Cannot load Zend OPcache] แสดงขึ้น
หาก [opcache.revalidate_freq] เป็น 60 หลังแก้ไขไฟล์ PHP โค้ดเก่าอาจยังทำงานต่อได้นานสูงสุด 60 วินาที
บนเซิร์ฟเวอร์ WordPress ที่ไฟล์ PHP เปลี่ยนบ่อย ให้ตั้ง [opcache.validate_timestamps] เป็น 1 เพื่อให้ตรวจสอบการเปลี่ยนแปลงของไฟล์ ค่า 0 ที่เอกสารของ Symfony แนะนำสำหรับเซิร์ฟเวอร์ใช้งานจริงเหมาะกับเซิร์ฟเวอร์ที่ไฟล์ PHP เปลี่ยนเฉพาะตอนดีพลอยเวอร์ชันใหม่
แม้ตั้ง [opcache.validate_timestamps] เป็น 0 เมื่ออัปเดตจากหน้าผู้ดูแลระบบ WordPress จะล้างแคชของไฟล์ที่เปลี่ยนเอง แต่หากอัปเดตด้วย wp-cli หรือแก้ไฟล์ผ่าน SSH โค้ดเก่าจะยังทำงานอยู่จนกว่าจะรีสตาร์ต PHP-FPM
4️⃣ ปิดใช้งาน JIT ของ OPcache
JIT ของ PHP 8 เป็นฟีเจอร์ที่ทำให้งานซึ่งใช้การคำนวณของ CPU มากเร็วขึ้น จึงเห็นผลน้อยในแอปพลิเคชันอย่าง WordPress ที่ประมวลผลคำขอจากเว็บ ในการวัดผลกับ WordPress ที่ลงไว้ใน PHP JIT RFC ก็เช่นกัน ฝั่งที่เปิดใช้งาน JIT ได้ 326 คำขอต่อวินาที ส่วนฝั่งที่ปิดได้ 315
เปิดใช้งาน JIT บนเซิร์ฟเวอร์ WordPress ที่ใช้ PHP 8.3.22 ด้วย [opcache.jit=tracing] และ [opcache.jit_buffer_size=128M] สามวันต่อมา ในวันที่คำขอเข้ามาพร้อมกันจนเวิร์กเกอร์ของ PHP-FPM รีสตาร์ตหลายครั้ง ทุกหน้าเกิดข้อผิดพลาด 500
ในบันทึกข้อผิดพลาดมีข้อความ [Allowed memory size of 1073741824 bytes exhausted] ส่วน [tried to allocate 4295229440 bytes] ที่ต่อท้ายคือบันทึกว่ามีการพยายามจัดสรร 4GB ในครั้งเดียวทั้งที่ขีดจำกัดหน่วยความจำของ PHP คือ 1GB หลังปิดใช้งาน JIT คำขอเดิมถูกประมวลผลได้ตามปกติ
ปิดใช้งาน JIT ได้โดยใส่สองบรรทัดด้านล่างลงใน [/etc/php.d/10-opcache.ini] แม้ยังมีการตั้งค่า JIT เหลืออยู่ใน [/etc/php.ini] ค่าในไฟล์นี้ก็ยังมีผล
opcache.jit=disable
opcache.jit_buffer_size=0ใน PHP 8.3 ค่าเริ่มต้นของ [opcache.jit_buffer_size] คือ 0 ดังนั้นหากไม่ตั้งค่าแยกต่างหาก JIT จะไม่ทำงาน ตั้งแต่ PHP 8.4 ค่าเริ่มต้นของ [opcache.jit] ก็เป็น disable เช่นกัน
5️⃣ การใช้การตั้งค่าและการตรวจสอบ
การตั้งค่าที่เปลี่ยนจะมีผลเมื่อรีสตาร์ต PHP-FPM แล้วเท่านั้น
systemctl restart php-fpmเมื่อรีสตาร์ต หน่วยความจำที่ใช้ร่วมกันของ OPcache จะถูกล้างและจัดสรรใหม่ตามการตั้งค่าใหม่
php -i | grep -E '^opcache\.(enable|memory_consumption|revalidate_freq|validate_timestamps|jit) 'opcache.enable => On => On
opcache.jit => disable => disable
opcache.memory_consumption => 1024 => 1024
opcache.revalidate_freq => 60 => 60
opcache.validate_timestamps => On => Onค่าที่ [php -i] แสดงคือการตั้งค่าของ PHP บนบรรทัดคำสั่ง ส่วนในตระกูล RHEL PHP-FPM อ่านไฟล์ [/etc/php.ini] และ [/etc/php.d] ชุดเดียวกัน ค่าจึงเหมือนกัน
หากเรียก [opcache_get_status()] บนบรรทัดคำสั่ง จะแสดงสคริปต์ที่แคชไว้ 0 ไฟล์ เพราะ PHP บนบรรทัดคำสั่งสร้างหน่วยความจำที่ใช้ร่วมกันใหม่ทุกครั้งที่รัน การดูการใช้งานของ PHP-FPM จึงต้องวางไฟล์ด้านล่างไว้ในโฟลเดอร์เอกสารของเว็บแล้วเปิดดูในเบราว์เซอร์
<?php
header('Content-Type: text/plain');
$s = opcache_get_status(false);
print_r($s['memory_usage']);
print_r($s['opcache_statistics']);
print_r($s['interned_strings_usage']);
var_dump($s['cache_full']);หาก [cache_full] เป็น true แปลว่าหน่วยความจำที่ใช้ร่วมกันหรือคีย์เต็มแล้ว หลังตรวจสอบเสร็จให้ลบไฟล์นี้ทันที
บนเซิร์ฟเวอร์ที่มีเว็บไซต์ WordPress สามแห่งใช้ PHP-FPM ตัวเดียวกัน มีการใช้หน่วยความจำที่ใช้ร่วมกัน 317MB จากทั้งหมด 1024MB สคริปต์ที่แคชไว้มีเว็บไซต์ละ 3,366 ถึง 4,222 ไฟล์ รวม 11,358 ไฟล์
OPcache เก็บสคริปต์ด้วยพาธจริง และสำหรับไฟล์ที่โหลดผ่านพาธแบบสัมพัทธ์ จะสร้างคีย์เพิ่มอีกหนึ่งอันที่ต่อไดเรกทอรีทำงานเข้าไป จำนวนคีย์จึงมากกว่าจำนวนสคริปต์ เมื่อมีสคริปต์ 11,358 ไฟล์ คีย์เต็มถึงขีดจำกัด 16,229 และบัฟเฟอร์สตริง 16MB ก็ไม่เหลือที่ว่างด้วย
เมื่อคีย์เต็ม สคริปต์ใหม่จะไม่ถูกแคชและต้องคอมไพล์ในทุกคำขอ ในเวลา 5 นาที 21 วินาที แคชพลาดเพิ่มจาก 18,408 เป็น 36,027 ครั้ง แต่จำนวนสคริปต์ที่แคชไว้ยังคงเป็น 11,358 ไฟล์
บนเซิร์ฟเวอร์ที่รัน WordPress หลายเว็บไซต์หรือมีปลั๊กอินจำนวนมาก ให้กำหนด [opcache.max_accelerated_files] ให้เผื่อไว้เพื่อไม่ให้ขีดจำกัดของคีย์เต็ม หากตั้งเป็น 20000 ขีดจำกัดจริงของคีย์จะเป็น 32,531 หากบัฟเฟอร์สตริงเต็ม ให้เพิ่ม [opcache.interned_strings_buffer] ไปพร้อมกัน
🔢 FAQ & เนื้อหาแนะนำ
แคช
แคช: ความหมายและทุกด้านที่ใช้การแคช
บทความที่แบ่งด้านที่ใช้แคช รวมถึง OPcache ที่เก็บโค้ด PHP ที่คอมไพล์แล้ว และแคชหน้าเพจที่เก็บ HTML ที่สร้างเสร็จแล้ว
PHP-FPM
คำเตือน php-fpm max_children: หาสาเหตุจากล็อกก่อนเพิ่มเวิร์กเกอร์
บทความเกี่ยวกับการแยกสาเหตุจากบันทึกของคำเตือนที่ปรากฏเมื่อเวิร์กเกอร์ของ PHP-FPM ที่ใช้หน่วยความจำที่ใช้ร่วมกันของ OPcache ร่วมกันเต็มทั้งหมด
PHP-FPM
PHP-FPM คืออะไร | ติดตั้งและตั้งค่า PHP-FPM
บทความเกี่ยวกับการติดตั้ง PHP-FPM ที่ OPcache ทำงานอยู่ภายใน การตั้งค่าพูลใน www.conf และวิธีรีสตาร์ต
ℹ️ ประกาศเรื่องลิงก์แอฟฟิลิเอต
เนื้อหาของเว็บไซต์นี้มีลิงก์แอฟฟิลิเอต หากผู้เข้าชมซื้อสินค้าหรือบริการผ่านลิงก์เหล่านี้ เว็บไซต์นี้จะได้รับค่าคอมมิชชันจากผู้ขาย ในกระบวนการนี้ ราคาที่ผู้ซื้อจ่าย(ราคาจะลดลงเมื่อมีโปรโมชัน↓)จะไม่สูงขึ้นแต่อย่างใด ราคา ส่วนลด และข้อมูลสต็อกที่แสดงเป็นข้อมูล ณ เวลาที่เขียนและอาจต่างจากความเป็นจริง โปรดตรวจสอบกับผู้ขายอีกครั้งก่อนซื้อ การเลือกและการประเมินสินค้าเขียนตามเกณฑ์ของเราเอง และการได้รับค่าคอมมิชชันหรือไม่ไม่มีผลต่อลำดับการแนะนำหรือเนื้อหาการประเมิน