OPcache

最後更新: 2023-02-14

 

介紹

package: php56-opcache

This extension OPcache is bundled with PHP 5.5.0 and later, and available in PECL for PHP versions 5.2, 5.3 and 5.4.

ZendOpcache(http://pecl.php.net/package/ZendOpcache)

 


Checking

 

php -r 'phpinfo();' | grep opcache.enable

opcache.enable => On => On
opcache.enable_cli => On => On
opcache.enable_file_override => Off => Off

 


Recommended Settings

 

php.ini

opcache.enable=1

opcache.enable_cli=0

opcache.memory_consumption=96
opcache.interned_strings_buffer=10
opcache.max_accelerated_files=4000
opcache.revalidate_freq=60
opcache.fast_shutdown=1

Notes:

 * Zend OPcache works exclusively with Apache or FastCGI environments (no CLI or CGI support).
 * PHP-FPM and FastCGI are mutually exclusive in PHP 5.6

FastCGI (mod_fcgi)

--enable-fpm
--enable-cgi

Standard OPcache already supports php-fpm and php-cgi (with a functional SMA so long as it build with --enable-fastcgi and ran with PHP_FCGI_CHILDREN is > 0. However these solutions don't scale to the typical shared-hosting infrastructure templates where thousands of vhosts are typically configured per server.

Lets first explore how mod_fcgid works:
When request comes in for PHP, mod_fcgid checks if there is idle php process available for that user. If there is none, it starts a new one (up to FCGIDMaxProcessesPerClass, default 100). The request is served, and php process becomes idle. Until next request comes in.

Lets now add opcode caching, like eAccelerator, APC or xCache. Opcode caching software saves opcode (php pre-compiled into "operation code" ) into shared memory. Next time it has to process same PHP file, PHP process would not compile php, using opcode from cache instead.That will significantly decreasing CPU usage, and improving performance.

PHP processes with opcode cache enabled use shared memory for opcode caching. Yet, PHP processes will be able to "share" that shared memory, only if they were all created (forked) from the same, original PHP process, that allocated that shared memory.

This is not the case with mod_fcgid, as each and every PHP process is started by mod_fcgid itself. As the result, they don't "share" shared memory. In this case. each PHP process has its own shared memory, amd no opcode is shared between processes.

So, if process A is responding for request for index.php, and process B is responding to request for index.php, each of them will store its own copy of opcode in its own cache.

Yet, on the second request for index.php to process A, that process can use cached opcode. Gven that single PHP process can process thousands of requests -- opcode caching is useful with mod_fcgid.

Yet, it basically means that each and every PHP process will maintain its own copy of opcode cache. And if you have 1000 php processes, with 256MB of shared memory set for opcode caching -- you are looking at ~256GB of RAM -- that might be in use (though probably most sites will not need to use all 256MB of RAM).

As the result -- it is not practical in shared hosting with mod_fcgid to allocate 256MB shared memory for opcache. Something like 8MB or 4MB would be much more practical.

Another thing to keep in mind is that shared memory size of opcode cache cannot be more then memory_limit in php.ini, as that value controls shared memory size as well.

 


Configure

 

/etc/php.d/10-opcache.ini

; RAM you are willing to dedicate to storing opcode.(megabytes)
opcache.memory_consumption=64

; number of scripts that can be cached
opcache.max_accelerated_files=4000

; This configuration directive is ignored if opcache.validate_timestamps is disabled.
; 0 = disabled
opcache.validate_timestamps=0
; how often to check script timestamp for updates (seconds)
; "0" means always validate(on every request)
; This configuration directive is ignored if opcache.validate_timestamps is disabled.
opcache.revalidate_freq=2

; The amount of memory used to store interned strings (megabytes)
opcache.interned_strings_buffer=8

;  a fast shutdown sequence is used => doesn't free each allocated block,
; but relies on the Zend Engine memory manager to deallocate the entire set
opcache.fast_shutdown=1

; OPcache appends the current working directory to the script key,
; thus eliminating possible collisions between
; files with the same name
opcache.use_cwd=1

; PHPDoc comments are not loaded from SHM
; all PHPDoc comments are dropped from the code to reduce the size
opcache.load_comments=0

; Check the cache checksum each N requests. 0 = disabled
; This should only be enabled when debugging
opcache.consistency_checks=0

; If disabled, existing cached files using the same include_path will be reused.
; Thus, if a file with the same name is elsewhere in the include_path, it won't be found.
opcache.revalidate_path=1

; the names of files that should not be accelerated.
opcache.blacklist_filename=/etc/php.d/opcache*.blacklist

 


file_cache

 

Enables and sets the second level cache directory.

The default "" disables file based caching.

It should improve performance when SHM memory is full, at server restart or SHM reset.

 


opcache blacklist

 

/etc/php.d/10-opcache.ini

opcache.blacklist_filename=/etc/php.d/opcache*.blacklist

/etc/php.d/opcache-default.blacklist

; <- comments
; The filename may be a full path or just a file prefix
; /var/www/x <- /var/www/x*
; Script 被加入 blacklist 的原因
; 1) Directories that contain auto generated code
; 2) Code that does not work well when accelerated
; 3) Code that triggers an OPcache bug
; i.e.
/usr/share/phpmyadmin/
/usr/share/opcache-gui/

 


Get Statistics

 

phpinfo

  • Cache hits
  • Cache misses
  • Used memory
  • Free memory
  • Wasted Memory - bytes of memory used by invalid or outdated code

Zend OpCache has a setting that will cause the restart of your OpCache if the wasted memory exceeds a threshold.
(opcache.max_wasted_percentage)

  • Interned strings usage

if you have the string "foobar" 1000 times in your code,

internally PHP will store 1 immutable variable for this string and just use a pointer to it for the other 999 times you use it.

opcache-gui by amnuts

  • support php7
  • real-time updates (refresh_time) <- React javascript library
  • All the files currently in the cache
  • Reset cache (allow_reset / allow_invalidate)

HomePage: https://github.com/amnuts/opcache-gui

有用資訊

opcache statistics

number of cached files: 2,086
number of hits: 67,399
number of misses: 2,086
blacklist misses: 4          # 由於 opcache-gui 了, 所以每次 refress 都會 miss
number of cached keys: 3,372
max cached keys: 16,229

interned strings usage

buffer size: 12.00MB
used memory: 8.60MB
free memory: 3.40MB
number of strings: 139,799

 


opcache gui

 

Download & Install

mkdir /usr/share/opcache-gui

cd /usr/share/opcache-gui

wget https://raw.github.com/amnuts/opcache-gui/master/index.php

vim /etc/httpd/conf.d/opcache-gui.conf

Alias /opcache-gui /usr/share/opcache-gui

<Directory /usr/share/opcache-gui>
    Require ip R.R.R.R
    Options -Indexes
    AllowOverride None
    # php74
    <FilesMatch ".+\.php$">
        SetHandler application/x-httpd-php
        SetHandler "proxy:fcgi://127.0.0.1:9074"
    </FilesMatch>
</Directory>

systemctl reload httpd

echo '/usr/share/opcache-gui' >> /etc/opt/remi/php74/php.d/opcache-default.blacklist

systemctl restart php74-php-fpm

 


opcache.optimization_level

 

# Default: 0x7FFFBFFF

opcache.optimization_level=0xffffffff

設定值 = 要 "+" 所有要開啟的值

參考: https://github.com/zendtech/ZendOptimizerPlus/blob/master/Optimizer/zend...

pass 1 ~ pass 10

Value

  • CSE, STRING construction [1]
  • Constant conversion and jumps [2]
  • ++, +=, series of jumps [4]
  • INIT_FCALL_BY_NAME -> DO_FCALL [8]
  • ...

 


My Configure

 

opcache.enable_cli=1               # fpm 要它
opcache.memory_consumption=64
opcache.max_accelerated_files=4000
opcache.validate_timestamps=1
opcache.revalidate_freq=30
opcache.interned_strings_buffer=8
opcache.fast_shutdown=1
opcache.use_cwd bool=1
opcache.revalidate_path=1
opcache.consistency_checks=0
opcache.save_comments=0

 


Interned Strings

 

; The amount of memory for "interned strings" in Mbytes.
opcache.interned_strings_buffer=8

 


Troubleshoot

 

1) CDN Failed

V2

grep cdn.jsdelivr.net index.php

    <script src="//cdn.jsdelivr.net/react/15.4.2/react.min.js"></script>
    <script src="//cdn.jsdelivr.net/react/15.4.2/react-dom.min.js"></script>
    <script src="//cdn.jsdelivr.net/jquery/3.1.1/jquery.min.js"></script>

Fix

wget cdn.jsdelivr.net/react/15.4.2/react.min.js
wget cdn.jsdelivr.net/react/15.4.2/react-dom.min.js
wget cdn.jsdelivr.net/jquery/3.1.1/jquery.min.js

修改 index.php

 

 


Doc

 

http://php.net/manual/en/opcache.configuration.php

 

 

 

 

 

Creative Commons license icon Creative Commons license icon