PHP APC in CLI mode - php

Does APC module in PHP when running in CLI mode support code optimization? For example, when I run a file with php -f <file> will the file be optimized with APC before executing or not? Presuming APC is set to load in config file. Also, will the scripts included with require_once be also optimized?
I know optimization works fine when running in fastcgi mode, but I'm wondering if it also works in CLI.
apc_* functions work, but I'm wondering about the code optimization, which is the main thing I'm after here.
Happy day,
Matic

The documentation of apc.enable_cli, which control whether APC should be activated in CLI mode, says (quoting) :
Mostly for testing and debugging.
Setting this enables APC for the CLI
version of PHP. Under normal
circumstances, it is not ideal to
create, populate and destroy the APC
cache on every CLI request, but for
various test scenarios it is useful to
be able to enable APC for the CLI
version of PHP easily.
Maybe APC will store the opcodes in memory, but as the PHP executable dies at the end of the script, that memory will be lost : it will not persist between executions of the script.
So opcode-cache in APC is useless in CLI mode : it will not optimize anything, as PHP will still have to re-compile the source to opcodes each time PHP's executable is launched.
Actually, APC doesn't "optimize" : the standard way of executing a PHP script is like this :
read the file, and compile it into opcodes
execute the opcodes
What APC does is store in opcodes in memory, so the execution of a PHP script becomes :
read the opcodes from memory (much faster than compiling the source-code)
execute the opcodes
But this means you must have some place in memory to store the opcodes. When running PHP as an Apache module, Apache is responsible for the persistence of that memory segment... When PHP is run from CLI, there is nothing to keep the memory segment there, so it is destroyed at the end of PHP's execution.
(I don't know how it works exactly, but it's something like that, at least in the principles, even if my words are not very "technical" ^^ )
Or, by "optimization" you mean something else than opcode cache, like the configuration directive apc.optimization ? If so, this one has been removed in APC 3.0.13

If you have CLI code that generates any configuration based on the environment, then the CLI code will think that APC isn't enabled. For example, when generating Symfony's DI container through the CLI, it will tell Doctrine not to use APC (details).
Also, I have not tested it but there's a chance APC may improve the speed of scripts for files included after a pcntl_fork(). Edit: I've asked the question about APC & pcntl_fork() here.
For completeness, to enable APC on the CLI (in Ubuntu):
echo 'apc.enable_cli = 1' > /etc/php5/cli/conf.d/enable-apc-cli.ini

Well, there's a good reason for APC in CLI Mode:
UnitTesting: I wanna do my unit test using an environment as close to the later production environment as possible. Zend Framework has an internal caching solution, which may use APC's Variable Cache as Storage Backend - and I wanna use this.

There is another reason to use it in CLI mode: some scripts are able to use it as a cache

Related

Zend OPCache - opcache.enable_cli 1 or 0? What does it do?

In the documentation it says "mostly used for debugging" which would lead me think "never enable it unless you've a problem and need to do some debugging," however reading mostly everything that I could find about it says to enable it "opcache.enable_cli 1" but why? I could not find any information concerning this matter, so if anybody knows, why should I enable it if the documentation basically says to keep it on 0?
With PHP7 and file-based caching, it can now make sense to enable opcache for CLI. The best possibility would be to have a separate php.ini for CLI with the following configuration:
opcache.enable=1
opcache.enable_cli=1
opcache.file_cache="/tmp/php-file-cache"
opcache.file_cache_only=1
opcache.file_cache_consistency_checks=1
opcache.file_cache_only=1 makes sure that the in-memory opcache is disabled and only files are used, which is what you want for CLI. This should boost execution time by quite a bit.
In the php.ini for FPM, you will want to have the same settings but use opcache.file_cache_only=0, so in-memory opcache is used and the file cache is used as a fallback (which also makes FPM faster, because the file cache reduces warmup time when FPM is restarted or opcache is reset, because the cached files remain).
This way, CLI and FPM share the file cache, and FPM has the in-memory cache as a second primary cache for maximum speed. A great improvement in PHP7! Just make sure to choose a directory for opcache.file_cache that both CLI and FPM can write to, and that the same user does the writing/reading.
UPDATE 2017
I would not recommend to use the file cache with FPM anymore (only use it for CLI), because there is no way to reset the cache when setting opcache.validate_timestamps=0 - the file cache prevents PHP-FPM from recognizing any changes, because opcache_reset() or even a complete PHP-FPM restart does not affect the file cache and there is no equivalent for the file cache, so changed scripts are never noticed. I reported this as a "bug"/"feature request" in March 2016, but this is currently not seen as an issue. Just beware if you use opcache.validate_timestamps=0!
Leave it off. It's primarily there for use while debugging issues with OPcache itself.
The opcache.enable_cli option enables PHP OPcache when running PHP scripts from the command line (using the php command). However, keep in mind that for PHP 5.x the OPcache extension works by storing cached opcodes in the memory of the current process. This is only useful when the process that's running PHP is going to be handling multiple requests that can reuse these opcodes, like in a web server or under FastCGI. For a process like the PHP CLI, which runs one "request" and exits, it just wastes memory and time.
As per PHP docs:
opcache.enable_cli boolean enables the opcode cache for the CLI version of PHP. This is mostly useful for testing and debugging.
Therefore it should be disabled unless you're really need this.
This can be useful when you've some long-term migration process running from the command-line (personally I've tested OPcache v7.0.3 for CLI by running some extensive migration script and I didn't see much performance improvements).

PHP include path order and status cache

I am building a framework where product instances use the main framework files, until there is a copy of it's own version of that file. To achieve this I have done the following:
set_include_path(MY_PRODUCT_ROOT.'/' . PATH_SEPARATOR . MY_FRAMEWORK_ROOT.'/');
So if I call include('view-users.php'); it will first look in MY_PRODUCT_ROOT for /view-users.php and if that's not found, it will then look to MY_FRAMEWORK_ROOT/view-users.php.
This procedure is working very nicely until I add files to the product root. I know that PHP/Apache is caching the includes and one would think to run clearstatcache(true); to clear any status caching. PHP likely uses file_exists inside it's include(); and thinks the new file still does not exist. I have tried restarting Apache with no effect.
Unfortunately running clearstatcache(true); does not help either. Only once I have deleted MY_FRAMEWORK_ROOT/file does it think to clear cache and try again, thus finding MY_PRODUCT_ROOT/file.
Im a little stumped, I know we need to refresh PHP/Apache's understanding of whether the file(s) exist or not, but clearstatcache(true); is not helping...
Any ideas?
UPDATE: Correction, restarting Apache seems to help now. I reiterate that this only occurs when trying to ADD a file to MY_PRODUCT_ROOT, to overlap an existing MY_FRAMEWORK_ROOT file, for customization
UPDATE: Development environment is Zend Server CE PHP 5.3.14 on Windows, Production environment Centos linux httpd, PHP 5.3+. The fact that Zend optimizer is enabled on my dev environment could have an effect, Also not using APC or any other caching scripts
Zend Optimizer+ speeds up PHP execution by opcode caching and optimization. It stores precompiled script bytecode in shared memory. This eliminates the stages of reading code from the disk and compiling it on future access. For further performance improvements, the stored bytecode is optimized for faster execution.
This is caching the file contents found in the includes, thus clearstatcache does not work. I have disabled my Zend Optimizer and it works now.

Why is the use of pcntl library in php is discouraged on prod-serv?

Can anybody tell me why using the pcntl lib on production servers is discouraged? The PHP manual tells very briefly about it, and I'm in a dire need to use this library...
Is there another way to do the same thing in php?
pcntl is discouraged in production environments because the functionality it supports (fork, process control, signal handling) are fairly explicitly things you should not be using in a CGI style application. Now, if you're writing a daemon or command line application in PHP, that is another matter...
From the PHP manual:
Process Control should not be enabled within a web server environment and unexpected results may happen if any Process Control functions are used within a web server environment.
one has to be clear about the differences of a php cli script and a sapi/cgi script.
php on production systems may as well have support for pcntl.
the important thing here is to have 2 php config files. one for cli and one for cgi setup.
one then has to disable pctnl in the cgi setup because the real security issue is, that forking a script when executed by the webserver may leave zombie processes flooding the system.
in a cli environment it might be necessary to be able to write scripts that fork...

Why would apc_store() return false?

The documentation on php.net is very spotty about causes of failure for APC writes. What kind of scenarios would cause a call to apc_store() to fail?
There's plenty of disk space available, and the failures are spotty. Sometimes the store operation will succeed and sometimes it'll fail.
For php cli it needs to be enabled with another option:
apc.enable_cli=On
In my situation it was working when running from a webbrowser, but not when executing the same stuff with php cli.
I had exactly the same situation.
I migrated my code from using Cron Jobs, to using Gearman Workers, which were managed through supervisord.
Everything Broke. I couldn't ever get caches to work through APC, and had to revert back to using filebase caching.
Eventually I figured out that when I was using cron jobs, I would load each page via wget, rather than command line. This difference, meant that supervisord, which would load my PHP scripts via command line, wouldn't work, because by default APC will not work through command line.
The fix....
apc.enable_cli=On
out of memory (allocated memory for apc, that is)
this asinine (and closed, for some reason) bug was my problem:
http://pecl.php.net/bugs/bug.php?id=16814
has to roll back to apc version 3.1.2 to get apc to work. no fiddling with apc settings in php.ini helped (i'm on mac os 10.5, using apache 2, php 5.3).
for me, this test script showed 3 "trues" for 3.1.2 and true/false/true for 3.1.3p1
var_dump( apc_store('test', 'one') );
var_dump( apc_store('test', 'two') );
var_dump( apc_store('diff', 'thr') );
http://php.net/manual/en/apc.configuration.php
the apc.ttl and apc.user_ttl settings on php.ini:
Leaving this at zero means that APC's cache could potentially fill up with stale entries while newer entries won't be cached.
Out of disk space or permission denied to the storage directory?
In addition to what Greg said, I'd add that a configuration error could cause this.
There's a bug in the version installed with ubuntu 10.04 and debian stable. If you replace the package with this version: http://packages.debian.org/sid/php-apc (3.1.7) it works as it should.
apc_store will fail if that specific key already exists and you are trying to write again to it before the TTL expires. Therefore you can pretty much ignore the return false because it really did fail but the cache is still there. If you want to get around this, start using apc_add instead. http://php.net/manual/en/function.apc-add.php

How can I get PHP to use the same APC cache when invoked on the CLI and the web?

I'm using APC to cache user variables (with the apc_store/apc_fetch commands). I've also enabled APC for the CLI with the option "apc.enable_cli = 1". However, the CLI version of PHP seems to access a different APC cache from the version used by Apache.
Is it possible to configure APC to use the same cache for both CLI and web invocations?
Not possible.. The only way to accomplish something like what your asking is to use something like memcacheD. Or run what you need to run through your webserver. What's running CLI that you cannot run via a web script with a cronjob?
You can use shm. This technology lend to access to Unix Shared memory. You can put some variable in shm and then in another scritp, even programmed in another languaje you can get the shared variables.
shm_put_var and shm_get_var.
It's slower than APC, but it's faster than memcached, redis, etc.
I hope It will help you, and I'm sorry for my English....
call your CLI as a CGI
/path-to/cgi-sys/php5.cgi /home/name/crons/engine.php
you would need a web server written in php -- the APC cache is shared only by forked child processes. If you had a php webserver, you could start a master cli, init apc, fork and load/run the web server in one child process, and fork and run your php cli script in another. Kind of a gross hack, huh. Fork and require(), I don't think the apc cache would survive an exec()

Categories