A few weeks ago, I wrote a short article highlighting GUI solutions for monitoring and controlling PHP OPcache. We all know that enabling PHP OPcache provides massive performance gains (see the benchmark graph at the end of the article). Also, since PHP 5.5, OPcache is now enabled by default. With these facts in mind, is it possible to extract a bit more performance from PHP by modifying the OPcache directives? That’s what I am ready to answer.
Benchmarking PHP: Default OPcache vs OPcache + Tweaks
Today, I ran some quick benchmarks capturing second run data of the tests. First, on a 32GB/16 CPU core VPS (Ubuntu 16.04 LTS), resulting in the below PHP7 + OPcache vs PHP7 + OPcache + Tweaks Benchmark graph using Apache Bench (AB):
After this, I also tested with 1GB/1 CPU core VPS, result:
Also, although OPcache works regardless of the PHP handler used, I wanted to make sure the results were the same with PHP-FPM. so i changed the default mpm_prefork to mpm_event (More about mpm_event: Stripping Apache to Improve Performance and Memory Efficiency) and swap mod_PHP for PHP-FPM On the same 1GB/1 CPU core VPS:
These are not mind blowing results. However, depending on your current throughput of PHP requests, you might be happy to take whatever improvements you can find. Also, this test was with WordPress only; As with other PHP web apps and scripts, these results can result in even greater performance gains, or less… You can read the following configuration options and be the judge. Share your sweet-spot settings and advice for OPcache.
When enabled (“1” by default), OPcache will check each update script opcache.revalidate_freq=# of seconds. when disabled, opcache.revalidate_freq are ignored, and you must manually reset OPcache by opcache_reset(), opcache_invalidate(), or restarting PHP for the changes to the file system to take effect.
So by default, OPcache tries to be as developer-friendly as possible with the timestamps for validating cached files. However, this convenience comes at the cost of performance as it adds to the operational overhead. For multiple production servers, especially when you have a separate development server, this directive can be safely disabled.
If you need to keep it enabled, watch the end of it this post In regards to increasing the time between checks from 2 seconds to maybe 10 or more, depending on what you can live with.
(default “2”) prevents caching of files older than this second. This avoids caching of incompletely updated files. You can increase the performance by setting it to “0”. documentation is limited,
Fast shutdown tries to use a faster mechanism to clean up memory. If enabled, an immediate shutdown sequence is used that does not free each allocated block. Instead, it largely relies on the Zend Engine memory manager to remove the entire set of request variables. Use it with PHP7+. You may experience segfaults with older versions of PHP.
PHP 8 performance tips.
Also, see PHP 8 compatibility checks and performance tips.
Here is a copy of the config (opcache.ini) that I used…
Default PHP OPcache:
PHP OPcache+ Tweaks:
zend_extension=opcache.so opcache.fast_shutdown=1 opcache.file_update_protection=0 opcache.validate_timestamps=0 opcache.interned_strings_buffer=16
ab -n 1000 -c 20 -g opcache_yes.dat This is ApacheBench, Version 2.3 <$Revision: 1706008 $> Copyright 1996 Adam Twiss, Zeus Technology Ltd, Licensed to The Apache Software Foundation, Benchmarking localhost (be patient) Completed 100 requests Completed 200 requests Completed 300 requests Completed 400 requests Completed 500 requests Completed 600 requests Completed 700 requests Completed 800 requests Completed 900 requests Completed 1000 requests Finished 1000 requests Server Software: Apache/2.4.18 Server Hostname: localhost Server Port: 80 Document Path: / Document Length: 51919 bytes Concurrency Level: 20 Time taken for tests: 1.815 seconds Complete requests: 1000 Failed requests: 0 Total transferred: 52154000 bytes HTML transferred: 51919000 bytes Requests per second: 551.08 [#/sec] (mean) Time per request: 36.292 [ms] (mean) Time per request: 1.815 [ms] (mean, across all concurrent requests) Transfer rate: 28067.40 [Kbytes/sec] received Connection Times (ms) min mean[+/-sd] median max Connect: 0 0 0.1 0 0 Processing: 19 36 5.6 35 66 Waiting: 17 33 5.4 33 62 Total: 19 36 5.6 35 66 Percentage of the requests served within a certain time (ms) 50% 35 66% 37 75% 39 80% 40 90% 43 95% 46 98% 51 99% 53 100% 66 (longest request)
If you’re wondering why all the fuss about PHP Opcache, here’s a benchmark PHP 7 without OPcache vs PHP 7 +OPcache (concurrency is reduced to 2, because without OPcache, PHP fails 90% of requests).