php.ini vs configuration at runtime - php

Considering a common LAMP setup, you can leave your PHP configurations at some .ini file to PHP read and apply them upon web server initialization. But how does it compare, in performance matters, to runtime configurations that developers usually leave at the application bootstrap file?!
Since PHP uses a shared nothing architecture , each request will starts a new (sub?)process so it will need to read the *.ini files again? Or it comes already shared by the main PHP process? If yes, changing a lot of configurations at runtime will add much more overhead to each request than leaving that at ini files, right?!

Well, firstly it is not PHP that forks a new process. That is completely up to the Web server that PHP is a apart of. So yes, if you are using LAMP, and therefor Apache, the entirety of the PHP module has to get loaded into memory for each process anyways (each process is upwards of 30-50 MB which is massive!).
And again yes, it will need to read the .ini for each new process, but that is completely negligible to all of the other loading that needs to be done.
Ofcourse, the alternative is to use ini_set which would have to be called on each request. Performance wise, it would be just the same as an .ini file IF processes were recreated for every request. However, processes are oftentimes reused (which is why you should tinker with the min and max process count for the Apache config).
So in conclusion, there is a slight performance benefit for a php.ini file.
However, like all performance concerns with PHP and Apache, do what WORKS! If you are trying to optimize, it's probably your queries!

Related

(How) does PHP cache script and custom INI-files?

Currently I'm storing the configuration for my PHP scripts in variables and constants within another PHP script (e.g. config.php).
So each time a script is called, it includes the configuration script to gain access to the values of the variables/constants.
Since INI-files are easier to parse by other scripts, I thought about storing values for my configuration in such a file an read it using parse_ini_file().
In my notion PHP keeps script-files in memory, so including a script-file does (usually) not cause IO (Or does Zend do the caching? Or are the sources not cached at all?).
How is it with reading custom INI-files. I know that for .user.ini there is caching (see user_ini.cache_ttl), but does PHP also cache custom INI-files?, or does a call to parse_ini_file() always cause IO?
Summary
The time required to load configuration directives (which is not the same as the time needed by the app to perform those directives) is usually negligible - below one millisecond for most "reasonably sized" configurations. So don't worry - INI, PHP, or JSON are, performance wise, all equally good choices. Even if PHP were ten times faster than JSON, that would be like loading in 0.001s instead of 0.01s; very few will ever notice.
That said, there are considerations when deciding where to store config data.
.ini vs .php config storage
Time to load: mostly identical unless caching is involved (see below), and as I said, not really important.
ease of use: .ini is easier to read and modify for a human. This may be an advantage, or a disadvantage (if the latter, think integrity check).
data format: PHP can store more structured data than .ini files, unless really complicated workarounds are used. But consider the possibility of using JSON instead of INI.
More structured data means that you can more easily create a "super configuration" PHP or JSON holding the equivalent of several INI files, while keeping information well isolated.
automatic redundancy control: PHP file inclusion can be streamlined with require_once.
user modifications: there are visual INI and JSON editors that can allow a user to modify a INI or JSON file while keeping it, at least, syntactically valid. Not so for PHP (you would need to roll your own).
Caching
The PHP core does not do caching. Period. That said, you'll never use the PHP core alone: it will be loaded as a (fast)CGI, an Apache module, et cetera. Also you might not use a "barebones" installation but you could have (chances are that you will have) several modules installed.
Both the "loader" part and the "module" part might do caching; and their both doing this could lead to unnecessary duplications or conflicts, so it is worth checking this out:
the file (but this does not change between INI, JSON and PHP files) will be cached into the filesystem I/O subsystem layer and, unless memory is really at a premium, will be loaded from there (on a related note, this is one of the reasons why not all filesystems are equally good for all websites).
if you need the configuration in several files, and use require_once in all of them, the configuration will be loaded once only, as soon as it is needed. This is not caching, but it is a performance improvement nonetheless.
several modules exist (Zend, opcache, APC, ...) that will cache all PHP files, configuration included. They will not cache INI files, though.
the caching done by modules (e.g. opcache) can (a) ignore further modifications to the file system, which means that upon modifying a PHP file, you'll need to somehow reload or invalidate the cache; how to do this changes from module to module; (b) implement shortcuts that might conflict with either the file system data management or its file structure (famously, opcache can ignore the path part of a file, allowing for much faster performances unless you have two files with the same name in different directories, when it risks loading one instead of the other).
Performance enhancement: cache digested data instead of config directives
Quite often it will be the case that depending on some config directive, you will have to perform one of several not trivial operations. Then you will use the results for the actual output.
What slows down the workflow in this case is not reading whether, say, "config.layout" is "VERTICAL" or "HORIZONTAL", but actually generating the layout (or whatever else). In this case you might reap huge benefits by storing the generated object somewhere:
serialized inside a file (e.g. cache/config.layout.vertical.html.gz). You will probably need to deploy some kind of 'stale data check' if the layout changes, or some kind of cache invalidation procedure. (For layouts specifically, you could check out Twig, which also does parameterized template caching).
inside a keystore, such as Redis.
in a RDBMS database such as MySQL (even if that's overkill - you'd use it as a keystore, basically).
faster NoSQL alternatives such as MongoDB.
Additional options
You will probably want to read about client caching and headers, and possibly explore whatever options your hosting offers (load balancers, HTTP caches such as Varnish, etc.).
parse_ini_file() uses standard operations to convert the file into an array.

repeated application executed from disk. How to execute repeats from memory?

I'm running a linux web server that uses apache, php, and suphp. Each time a guest accesses the server, suphp is started, the php interpreter is started and the php file is processed, but all of these files are on the disk.
I want to make it so that when the suphp and php programs start for the first time, they get cached in memory, and then the next time (and times after that) they try to start again, they will load from memory, making the startup time much smaller.
I think there is a setting inside /proc somewhere that can help me with this, but I'm not sure which one.
What you're trying to change is an aspect of application behavior, not kernel behavior, so there is nothing in /proc that will help you.
PHP opcode caching is not available under suPHP. You will need to use something else (possibly mod_php or FastCGI) to take advantage of it.

Does loading .php files that you don't use affect performance?

Just wondering... Does it? And how much
Like including 20 .php files whith classes in them, but without actually using the classes (they might be used though).
I will give a slight variant Answer to this:
If you are running on a tuned VPS or dedicated server: a trivial amount.
If you are running on a shared hosting service: it can considerably degrade performance of your script execution time.
Why? because in the first case you should have configured a PHP opcode cache such as APC or Xcache, which can, in practical terms, eliminate script load and compilation overheads. Even where files need to be read or stat-checked the meta and file data will be "hot" and therefore largely cached in the file-system cache if the (virtual) server is dedicated to the application.
On a shared service everything is running in the opposite direction: PHP is run as a per-request image in the users UID; no opcode caching solutions support this mode, so everything needs to be compiled. The killer here is that files need to be read and many (perhaps most) shared LAMP hosting providers use a scalable server farm for the LAMP tier, with the user data on shared NFS mounted NAS infrastructure. Since these NFS mounts with have an acremin of less than 1 min, the I/O requests will require RPCs off-server. My blog article gives some benchmarks here. The details for a shared IIS hosting template are different but the net effects are similar.
I run the phpBB forum package on my shared service and I roughly halved response times by aggregating the common set of source includes as I describe here.
Yes, though by how much depends on a number of things. The performance cost isn't too high if you are using a PHP accelerator, but will drastically slow things if you're aren't. Your best bet is generally to use autoloading, so you only load things at the point of actual use, rather than loading everything just in case. That may reduce your memory consumption too.
Of course it affects the performance. Everything you do in PHP does.
How much performance is a matter of how much data is in them, and how long it takes to execute them or in the case of classes, read them.
If your not using them, why include them? I assume your using some main engine file, or header file and should rethink your methods of including files.
EDIT: Or as #Pekka pointed out, you can autoload classes.
Short answer - yes it will.
For longer answers a quick google search revealed these - Will including unnecessary php files slow down website? ; PHP Performance on including multiple files
Searching helps!
--Matīss

How to share APC cache between several PHP processes when running under FastCGI?

I'm currently running several copies of PHP/FastCGI, with APC enabled (under Apache+mod_fastcgi, if that matters). Can I share cache between the processes? How can I check if it's shared already? (I think the apc.mmap_file_mask ini setting might be involved, but I don't know how to use it.)
(One of the reasons I think its not shared at the moment is that the apc.mmap_file_mask, as reported by the apc.php web interface flips between about 3 different values as I reload.)
APC does not currently share its cache between multiple php-cgi workers running under fastcgi or fcgid. See this feature request for details: "this behaviour is the intended one as of now".
One workaround is to allow PHP to manage its own workers. You can do this using the PHP_FCGI_CHILDREN environment variable in your wrapper script (plenty of examples all over the web for that). You should also stop fastcgi/fcgid from spawning more than one PHP process if you want to use this method.
The disadvantage with PHP_FCGI_CHILDREN is that its management of the workers is not as good as that provided by fcgid/fastcgi.
So, there we are. APC in a fcgid/fastcgi environment means giving each PHP worker their own cache, or disabling fcgid/fastcgi's process spawning in favor of PHP's built-in management. Let's hope this changes in the future.
While it's not perfect the method Domster suggested is the best. I've been doing this for a short time on some low volume sites without errors. I wrote up a detailed explanation on how to set up mod_fastcgi with a shared opcode cache last night.
I found it very important to use mod_fastcgi rather than the newer mod_fcgid because mod_fcgid will only send one request at a time to the PHP process regardless of how many children PHP has spawned via PHP_FCGI_CHILDREN.
The cache should be shared between processes. You should be seeing the same value for the mmap file between phpinfo() and apc.php invocations. It is working for me with the suggested default APC configuration settings:
extension="apc.so"
apc.enabled=1
apc.shm_segments=1
apc.shm_size=128
apc.ttl=7200
apc.user_ttl=7200
apc.num_files_hint=1024
apc.mmap_file_mask="/tmp/apc.XXXXXX"
apc.enable_cli=1
You may want to post your settings. I've seen warnings that the mmap_file_mask must be exactly one of the values they allow. So if you are missing one of those Xs there is no telling what you will get.
Maybe it involves your fastcgi+apache configuration.

PHP as a thttpd module vs CGI in terms of memory usage

I am planning to use php in an embedded environment. Our current web server is thttpd. I am considering two options now: whether to run it as a cgi or as SAPI module. I know cgi has advantage in terms of security. But if we are to use php as cgi, an instance of the php should be loaded into the memory for each request.
I have tried compiling it as a SAPI module of thttpd and I have observed that thttpd's memory usage, specifically rss, does not grow larger as the number of request increases.
Can anybody explain how thttpd loads php? Is it loaded just one time and stays resident to the memory as long as thttpd is running? If so, we may consider this as an alternative to cgi.
Does it perform multi-threading, i.e. if there's multiple http request at the same time? or does it process request one at a time?
Is there a good documentation discussing behavior of php as a module of thttpd?
I have no experience with thttpd, but here are some pointers:
the PHP engine is thread safe, but some extensions aren't, so usually people shy away from using it in a multi-threaded environment and rather go with the one-process - one-request method
yes, usually webserver modules (like the Apache mod_* stuff) works by staying resident, but the big speedbump for PHP is that it needs to parse the source file (or even multiple source files if you use include / require) for each request. You can cut down on this by using something like APC which caches the parsed version of the files
there is also a protocol called FastCGI which you might want to look at - it basically is a crossover between the module and CGI solution - it spins up a couple of processes, each process hosts a single instance of the CGI problem (PHP in this case) and uses them to process requests. Instances are recycled (ie. they can process multiple requests, one after the other).

Categories