Partner and Community Forums
Windows Cache Extension for PHP
PHP 7.2 and future of WinCache
Re: PHP 7.2 and future of WinCache
Sep 12, 2017 09:27 PM|DropPhone|LINK
Out of curiosity, what would happen if opcache.enable_file_override and reroute_enabled were both on?
The way PHP Core lets developers hook functions is by chaining to the existing value. In this case, Zend Opcache is special, in that it's a zend_extension, and therefore gets first/final crack at all the hooks. Which means Zend Opcache is the last one
to hook things, which ensures it's always called first when a hooked function is called.
If both WinCache and Zend Opcache are hooking the Exists() function, it would look like this:
[calling script] | | -- zend_opcache.Exists
Here's the thing: Zend Opcache's cache and WinCache's file cache contain different, but overlapping, items. Zend Opcache's cache contains only *.php script files. WinCache's file cache contains anything that was opened via the PHP streams interface.
So, let's walk through a couple of examples:
A script starts executing. PHP Core calls Compile script (remember, it's an interpreted language! PHP must call compile every single time a script is executed in order to get the array of Intermediate Language opcodes). The Compile function is actually
hooked by Zend Opcache, which checks to see if the opcode array for the script was previously cached. In this example, it hasn't. Zend Opcache calls the PHP Core compile, which reads the *.php script file via the streams interface, which WinCache has hooked.
WinCache checks to see if the stream exists in its file cache (which, for this example, it hasn't). WinCache calls the PHP Core stream APIs, and caches the result. PHP Core parses, compiles, optimizes, and returns the opcode array to Zend Opcache, which
caches it. Then, PHP Core executes the script.
A script calls Readfile('foo.txt'), which is actually hooked by WinCache. WinCache.Readfile checks to see if the file exists in its cache. If it does, it returns it. If it hasn't, it calls the PHP Core Readfile('foo.txt'), and caches the result before
returning to the script.
A script calls file_exists('foo.txt'), which redirects to Zend Opcache's file_exists. Zend Opcache looks to see if it has the file cached. It won't, because it's not a *.php file, so it calls the next file_exists(), which redirects to WinCache's file_exists.
If WinCache has the file cached, it will return TRUE. If it's not cached, it calls the PHP Core file_exists(). NOTE: Neither WinCache nor Zend Opcache maintain a "negative cache"! Which means that if PHP Core file_exists() returns FALSE, neither WinCache
nor Zend Opcache will cache that FALSE result. This is because there are many, many ways for a script to create a file that it becomes prohibitive to hook all the different ways and 100% accurately detect when a file is created. So, do yourself a favor,
and try not to call file_exists() all over the place for files you know don't exist. It's painful, and hits every component that hooks the file_exists() function before eventually hitting the file system.
I hope this helps!