Zend Config Ini Caching
Asked Answered
A

4

5

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 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?

Aggrade answered 27/7, 2011 at 10:8 Comment(0)
B
10

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.

Bicipital answered 27/7, 2011 at 11:46 Comment(1)
Marcin, your post helped me out and now I have better performance using it. But what about, instead of just attempting to load the cache object with: $cache = $cacheManager->getCache('configFiles'); doing an extra check if it exists first like the following: if ($cacheManager->hasCache($routeCache)) { $cache = $cacheManager->getCache($routeCache); // ... }Sungkiang
D
4

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.

Distribute answered 27/7, 2011 at 14:16 Comment(2)
Generally, this answer would be correct, you don't want to microoptimize. However, Zend has a lot of action going on behind the scenes. In recent profiling I did of an older version of the framework (1.11.4), there is some terrible performance coming from the Zend_Config classes. There are custom array recursion functions in use, which are called thousands of times while loading/parsing the config files, leading to several hundred milliseconds of load time. Caching the config objects in this case is definitely worth it.Cockfight
@Cockfight fair enough. The recursion you mention I think is for the merging/cascading of the different section and quite frankly I would not advocate to have to many information besides and outside of the production section on a production system. I guess it is the main reason why this has been removed from ZF2.Distribute
D
3

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.

Doze answered 8/6, 2014 at 17:50 Comment(0)
R
0

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);
}
Reyreyes answered 29/12, 2014 at 10:41 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.