Zend Config Ini Caching
My Zend app uses 3 ini config files, with a total of over 200 lines to parse, containing over 100 instructions. Are these files parsed every request? Some people say they are (like here and here). If so, is this not an efficiency issue?
The comments in those links have mixed sentiment - some say you should avoid ini config files and do your config in PHP, some say you could use Zend_Cache_Frontend_File, and some say it's just not an issue. But surely parsing 200 lines of text for every request will quickly become a 开发者_Python百科problem if you are expecting quite a lot of traffic?
If you do recommend using a caching technique, can you please explain exactly how you would implement it?
Yes, they are parsed every time unless you cache them. It really saves time (i checked it in my own project).
So how do you use Zend_Cache_Frontend_File
to cache an ini file? Well I can provide you with an example. In my project I have route.ini file that contains a number of custom routes:
routes.ini
routes.showacc.route = "/@show/:city/:id/:type"
routes.showacc.type = "Zend_Controller_Router_Route"
routes.showacc.defaults.module = default
routes.showacc.defaults.controller = accommodation
routes.showacc.defaults.action = show
routes.showacc.defaults.city =
routes.showacc.defaults.type =
routes.showacc.defaults.id =
routes.showacc.defaults.title =
routes.showacc.reqs.id = "\d+"
;and more
In my Bootstrap.php I load them using cache (if possible):
protected function _initMyRoutes() {
$this->bootstrap('frontcontroller');
$front = Zend_Controller_Front::getInstance();
$router = $front->getRouter();
// get cache for config files
$cacheManager = $this->bootstrap('cachemanager')->getResource('cachemanager');
$cache = $cacheManager->getCache('configFiles');
$cacheId = 'routesini';
// $t1 = microtime(true);
$myRoutes = $cache->load($cacheId);
if (!$myRoutes) {
// not in cache or route.ini was modified.
$myRoutes = new Zend_Config_Ini(APPLICATION_PATH . '/configs/routes.ini');
$cache->save($myRoutes, $cacheId);
}
// $t2 = microtime(true);
// echo ($t2-$t1); // just to check what is time for cache vs no-cache scenerio
$router->addConfig($myRoutes, 'routes');
}
The cache is setup in my application.ini as follows
resources.cachemanager.configFiles.frontend.name = File
resources.cachemanager.configFiles.frontend.customFrontendNaming = false
resources.cachemanager.configFiles.frontend.options.lifetime = false
resources.cachemanager.configFiles.frontend.options.automatic_serialization = true
resources.cachemanager.configFiles.frontend.options.master_files[] = APPLICATION_PATH "/configs/routes.ini"
resources.cachemanager.configFiles.backend.name = File
resources.cachemanager.configFiles.backend.customBackendNaming = false
resources.cachemanager.configFiles.backend.options.cache_dir = APPLICATION_PATH "/../cache"
resources.cachemanager.configFiles.frontendBackendAutoload = false
Hope this helps.
If you load a framework like ZF you load dozens of files with thousands of lines of code. The files have to be read for each and every user and request. Server side you have some caching with disk controllers and whatnot so the files don't have to be actually read from disk each and every time. Also the memory managers in an operating system track it and provide some caching to the memory so this does not have to be read into memory every time--only out. Next you usually have a database where more or less the same thing happens because a database ultimately is stored in a file on a hard drive. The DB server reads the file and same story more or less.
So, would I worry about few lines in a config file? Certainly not because I need the data for my application to work. Where it is coming from is secondary.
About caching with Zend_Cache. If you have data which is compact and does not require a lot of processing like the files in Zend_Config you will gain save tiny microseconds. You are essentially storing a compact format into another compact format; serialized strings which have to be unserialized again. If you can cache data to avoid database access or rendering a whole view including all data requests with models kicking into gear we are talking about a whole different story.
If you assume that PHP file is cached in memory vs parsed ini file which is also in memory you can get performance converting ini file to php file while skipping Zend_Config_Ini class and parsing process.
# public/index.php
$cachedConfigFile = APPLICATION_PATH.'/../cache/application.ini.'.APPLICATION_ENV.'.php';
if(!file_exists($cachedConfigFile) || filemtime($cachedConfigFile) < filemtime(APPLICATION_PATH . '/configs/application.ini'))
{
require_once 'Zend/Config/Ini.php';
$config = new Zend_Config_Ini( APPLICATION_PATH . '/configs/application.ini', APPLICATION_ENV );
file_put_contents($cachedConfigFile, '<?php '.PHP_EOL.'return '.var_export($config->toArray(),true).';' );
}
$application = new Zend_Application(
APPLICATION_ENV,
$cachedConfigFile // originally was APPLICATION_PATH . '/configs/application.ini'
);
$application->bootstrap()
->run();
I'v tested with ab. Non cached config:
ab -n 100 -c 100 -t 10 http://localhost/
Requests per second: 45.57 [#/sec] (mean)
Time per request: 2194.574 [ms] (mean)
Time per request: 21.946 [ms] (mean, across all concurrent requests)
Transfer rate: 3374.08 [Kbytes/sec] received
vs Cached config:
Requests per second: 55.24 [#/sec] (mean)
time per request: 1810.245 [ms] (mean)
Time per request: 18.102 [ms] (mean, across all concurrent requests)
Transfer rate: 4036.00 [Kbytes/sec] received
That is 18% better performance.
According to the our friend who created the files:
https://github.com/QualityCase/Mini-Case/blob/master/modules/admin/Bootstrap.php
I found this very useful:
protected function _initConfig()
{
if(!$config = $this->_cache->load('config')) {
$config = new Zend_Config_Ini(BASE_PATH . '/configs/application.ini');
$config = $config->toArray();
$this->_cache->save($config, 'config');
}
Zend_Registry::set('config', $config);
}
精彩评论