Caching the config main.php

  1. Introduction:
  2. You will learn:
  3. Lets do it!
  4. A little explanation:
  5. You might think that the config array already cached if you turn on APC or Xcache etc.
  6. Is it worth to do?
  7. Links
  8. Additional info

Introduction:

The config long array included every time, and it's not cached at all!

The config first required In CApplication constructor

CApplication::__construct

just like this

public function __construct($config=null)
{
    Yii::setApplication($this);

    // set basePath at early as possible to avoid trouble
    if(is_string($config))
        $config=require($config);
//...

No caching goes here at all! even if you set it in main.php... At that point main.php event not loaded!

So if you want to cache it for some reason into memory for example, you can!

You will learn:

  • igbinary extension
  • Zend Data Cache (the same like xcache or apc)
  • The long way from app -> run, to the construction

Lets do it!

For this little tutorial I will use Zend Data Cache And igbinary for serialization

just open framework/base/CApplication.php see line 117 for __construct, and replace

if(is_string($config))
        $config=require($config);

With:

if(is_string($config)){		
if(($_config = igbinary_unserialize(zend_shm_cache_fetch("Yii::configs"))) === NULL)
{
zend_shm_cache_store("Yii::configs", igbinary_serialize(require($config)), 6000);
$config = igbinary_unserialize(zend_shm_cache_fetch("Yii::configs"));
}
else
{
    $config = $_config;
}
}

A little explanation:

if cache is NULL

if(($_config = igbinary_unserialize(zend_shm_cache_fetch("Yii::configs"))) === NULL)

this means it don't exists, or expired, so we will require the config array and cache it.

zend_shm_cache_store("Yii::configs", igbinary_serialize(require($config)), 6000);
$config = igbinary_unserialize(zend_shm_cache_fetch("Yii::configs"));

if the cache still exists and valid, we just read it.

That's it ...

It won't save you a lot of time, but with very big config, it could improve performance a little bit

You might think that the config array already cached if you turn on APC or Xcache etc.

Lets for learning purpose see all the path to CApplication::__construct

In your index.php you have

Yii::createWebApplication($config)->run();

Yii extends YiiBase

And have nothing inside

require(dirname(__FILE__).'/YiiBase.php');
class Yii extends YiiBase
{
}

Thats it...

Yii base have createWebApplication method

public static function createWebApplication($config=null)
	{
		return self::createApplication('CWebApplication',$config);
	}

lets see createApplication

public static function createApplication($class,$config=null)
	{
		return new $class($config);
	}

$class equals CWebApplication

CWebApplication constructor is extended from CApplication

And there you have

public function __construct($config=null)
	{
		Yii::setApplication($this);
		
		if(is_string($config)){
			$config = require($config);//no cache here ;-)
		}

Is it worth to do?

I did a test...

Like this:

$start = array_sum(explode(' ', microtime()));
//...
$end =  array_sum(explode(' ', microtime()));
		$result = $end - $start;
		echo $result;

When using Zend Optimizer+, there is about 0.00005 advantage to simple require (this is of course the array cached to memory automaticly by optimizer+, so you just waste the time with igbinary and cache it again etc.)

If you don't use it, the memory cache work 30 times faster than simple require

simple require takes about 0.003 sec. while my way takes about

0.0001 sec.

So my way works 30 times faster, or with no difference if op code cache used.

so I would say it worth it if you don't use some good op code cache...

Links

igbinary

zend data cache

Additional info

I'm sure most of you dont have Zend Data Cache or Zend Server...

You can use apc or xcache, it is all the same...

And for realization you can use serialize/unserialize instead of igbinary_serialize etc.