Currently I’m storing the configuration for my PHP scripts in variables and constants within another PHP script (e.g.
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?
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
- 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).
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_oncein 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.
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.