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.
Related
So, we have a Laravel 5.1 based project we want to release soon, but we're noticing poor performance, and we're trying to optimize the server setup.
As listed in the title, we're deploying this on a CentOS 6.7 server, with Nginx 1.8.1 and PHP 7 with PHP-FPM. Since CentOS 6.7's repositories do not offer PHP 7, we're using IUS' replacement packages.
One of the things we noticed that might be causing poor performance is the fact that Zend Opcache, despite being enabled and working (we have a good hit rate), does not seem to be caching all of the files in our project. We're using opcache-gui to help visualize the contents of the cache and, while many of the project's files are there (including files from third party libraries), most are missing, including our main controller and many of the supporting classes. In fact, when we disable Opcache, the response times remain virtually the same. The opcache blacklist is currently empty, so that's not the reason why they're not being included.
We've attempted to forcefully cache the missing files using opcache_compile_file(), and while the files do get compiled and cached, they never get any hits.
It was my understanding that Opcache would cache all of the files being executed, but that doesn't seem to be what's happening here. I've looked at the opcache settings, but could not find one that would obviously influence this kind of behavior, apart from the blacklist.
Is there anything else that I'm missing? Any other criteria that PHP would rely on when deciding on what to cache or not?
Any help on the matter would be appreciated!
Can you check the value of opcache.max_file_size? Maybe that's your issue, as compiled files are larger than original file.
Can you test the files you don't see in opcache-gui with http://php.net/opcache-is-script-cached?
Also, as a test, can you try to force the compile? Use http://php.net/opcache-compile-file for this matter. It's just to see if there's a true and if it can compile it in the first place.
I have the latest PHPUnit as a phar, placed in /usr/local/bin/phpunit (4.1.3). When I execute this file on my vagrant host (ubuntu 12.04, php 5.3.10), it takes what seems to be 30s to 60s before it actually starts performing the unit tests. I cannot figure out why.
Any ideas?
I ran into a similar problem when running phars in production (AWS's phar. Unfortunately, PHP doesn't do any caching around phar archives, even when using APC as an OpCode cache. So, on each request, PHP is unarchiving and parsing the entire phar. My workaround has been to avoid phars in production unless the archive is small.
If you have the option to upgrade PHP 5.5 w/ OpCode caching, you shouldn't have this problem.
I am going to close this for now as I believe the primary issue is that I am working with a shared folder, and I cannot update to 5.5 like monte suggested. I appreciate your response! I will just have to deal with it for now. If I get a moment I will try a vagrant with 5.5 and OpCode like you suggested, and just run phpunit to see if it is faster, even in a shared folder. If so, I will change my accepted answer.
I've been setting up PHP deployments with Capistrano on CentOS 6 and have run into an interesting issue. The way capistrano works, it sets up folders like this:
/var/www/myapp.com/
current (symlink to latest release in /releases)
shared
releases
20130826172737
20130826172114
When I look at the "current" symlink, it points to the most recent release. At first, when opening my web app, everything worked fine. After deploying a new release, the current folder correctly points to the new release, but the web application tries to load files from the old release (which has been deleted in a Capistrano cleanup process). Also, the virtual host is configured to point at /var/www/myapp.com/current/Public.
Are symlinks cached in any way?
The specific PHP code that fails (which initializes my framework) is this:
require_once dirname(dirname(__FILE__)) . '/App/App.php';
App\App::run();
That is in index.php currently located at /var/www/app.com/current/Public/index.php.
My Apache error logs show:
PHP Fatal error: require_once(): Failed opening required '/var/www/myapp.com/releases/20130826172237/App/App.php' (include_path='.:/usr/share/pear:/usr/share/php') in /var/www/myapp.com/releases/20130826172237/Public/index.php
And the current symlink shows:
current -> /var/www/zverse/releases/20130826172641
Obviously 20130826172641 != 20130826172237 which the latter was the previous version.
Any ideas or areas I can look at?
I can't verify this, but it seems that there is some unpredictable behaviour with Apache following / caching the old location of symlinks:
Is there a way to mimic symlink behavior with an apache configuration?
Case Against Using Symlinks For Code Promotion
The only thing that would absolutely clear up this issue was to cycle Apache, which we would prefer not to do on every deployment. -- Mike Brittain
He suggests moving the whole directory, instead of updating the symlink.
Have you checked the realpath_cache_size and realpath_cache_ttl directives? By default, php > 5.1 caches the real paths of symlinked files for 120 seconds. This will cause problems with capistrano deployments. The main problems are caching - that even if you clear your cache, your old php files will continue to be served for two minutes, repopulating it with old data - and interaction between php and static files. Static files are served directly by Apache, so will be updated immediately. The php code will still be from the previous release for two minutes after deploying though, so it will be expecting the old versions of any changed static files. That's especially a problem if you use a cache breaking procedure that changes the names of those files; in that case the php code won't be able to find the files it's expecting at all.
Anyway, there are two solutions. The first is to set realpath_cache_size to 0 in php.ini. (Note: setting realpath_cache_ttl to 0 does not disable the cache.) Or, if you want to keep it enabled, you should be able to use the clearstatcache function to clear the realpath cache immediately after deploying your symlink, using a capistrano hook. Be aware though, if you're using mod_php, the php cli and apache runtimes are separate, so you would need to call that function using a php script invoked by apache, similarly to what's done for clearing the APC cache here. I haven't tested that though, as I didn't notice a significant performance impact from simply disabling the cache.
I have installed PHP5 - PHP5-MEMCACHE - PHP-APC.
Can they work like that together? Will the loading be fast with these modules ?
I tried to use them, I don't "see" particular differences, maybe the CPU is used less with these modules. My website doesn't have high traffic, but If i can save resources is better!
Thank you
APC keeps cache of PHP bytecode. Memcache keeps cache of your vars, that you set.
So answer is Yes, they can. They're made for different things.
They work together very well, you just need to use them properly :
Memcached is a distributed cache system. What that means in a nutshell is that if you have a cluster of servers all of them can access the same cache pool
APC is an opcache and local cache system. Meaning it optimizes the php scripts so when going through the compiler less operations are made and the code is executed way faster. Another use of APC is local cache, which means you can store values in the cache and access them from the machine running the code.
Yes, they can work together. Whether they will on a production system is another story...
Personally, I had to give up trying to get the following to work for any extended period of time:
Ubuntu 10.04
NGINX 0.7.65
PHP 5.3.2
php-apc
php5-memcache
It will run for awhile, but after stress testing php errors out. I can restart php-fastcgi via /etc/init.d/php-fastcgi and things will role along for some time more, but it always crashes again sooner than later.
I can run either/or without issue, but the two together won't cooperate for me. FYI I tried using binaries (apt-get packages), installing as PECL extensions, downloading source, but all roads lead me to the same sad fate. I also tried running the memache daemon local & remotely on my web host, but same outcome.
I'm working on mmo game based on JavaScript and PHP. We are using both of them. I can't tell you more, beacause I am only frontend developer, however I think if APC and memcache were bad we were not using it.
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