Why is CakePHPs cake_core_method_cache file getting bigger over time?

How is this cache used

The only references to method_cache in CakePHP are in Dbo Source. This is a cache that is used extensively throughout that class to cache the result of (relatively) expensive quoting operations, or as indicated by a relevant docblock:

Caches result from query parsing operations. Cached results for both DboSource::name() and DboSource::conditions() will be stored here.

Consider the following shell:

<?php

class SoShell extends AppShell {

    function main() {
        $this->Post = ClassRegistry::init('Post');

        $this->Post->find('all', array(
            'conditions' => array(
                'find-this-text' => 'x'
            )
        ));

        debug(DboSource::$methodCache);
    }

}

Running it, produces the following output:

> Console/cake so
########## DEBUG ##########
array(
    'name' => array(
        'f5442d1f57be5d9d8ac80ae9613d5ff9' => '`database_name`',
        'cfacfed443d6f30e67edf9bbcb06ce30' => '`posts`',
        'e13d78515036382daf55fa083088c902' => '`Post`.`id`',
        'aafd056e6d53878a75ab4ee3f18645a1' => '`Post`.`title`',
        '4084e974416e3a7fb06e6a280721637b' => '`Post`.`body`',
        'b4f1ad1de4cdc3a3f82e905f8dfd8673' => '`Post`.`created`',
        'bfeffce70e344d7606e17c9ff24530b5' => '`Post`.`modified`',
        'e42609d9744a7d1ce80c8d838b9ea07c' => '`find-this-text`', # <-
        'c0a33fa0f04ac4682dcdc4b25167b3a8' => '`Post`'
    ),
    'fields' => array(
        '952d56c2bf037c8195bdd5fba57b1024' => array(
            (int) 0 => '`Post`.`id`',
            (int) 1 => '`Post`.`title`',
            (int) 2 => '`Post`.`body`',
            (int) 3 => '`Post`.`created`',
            (int) 4 => '`Post`.`modified`'
        )
    )
)

Note that the cache contains "user" (or developer) input, that array is what is written to the cache at the end of a request.

This example should also highlight why the cache grows with time - the cache is dependent on the queries issued to date and as time goes by more query permutations are issued by an application leading to the method cache growing (but not usually to many MB).

Easy fix

There's a very simple fix to the described problem: Disable the method cache.

i.e. put the following anywhere in your application:

DboSource::$cacheMethods = false;

This will of course mean a deterioration in performance as there will be no method caching used, so relatively expensive preg-based quoting operations will occur on every request.

Better fix

If the cache is being filled with "db-instances of models" - it's quite possible there is an application problem somewhere. It's not normal, it shouldn't happen and is dependent on exactly what the application is doing. Given that it's not possible to give a specific solution.

However, if you can identify any specific key in the cache containing a large chunk of data, you can use it to find what query is responsible. For example:

// anywhere
if (isset(DboSource::$methodCache['name']['e42609d9744a7d1ce80c8d838b9ea07c']) {
    // a query with find-this-text has been issued somewhere
}
    

You can (temporarily) add this kind of logic to where the dbo methodCache property is modified to be able to detect modifications "in situ":

public function cacheMethod($method, $key, $value = null) {
    if ($this->cacheMethods === false) {
        return $value;
    }
    if (!$this->_methodCacheChange && empty(self::$methodCache)) {
        self::$methodCache = Cache::read('method_cache', '_cake_core_');
    }
    if ($value === null) {
        return (isset(self::$methodCache[$method][$key])) ? self::$methodCache[$method][$key] : null;
    }
    $this->_methodCacheChange = true;
    
    // Added
    if ($method === 'name' && $key === 'e42609d9744a7d1ce80c8d838b9ea07c') {
        App::uses('Debugger', 'Utility');
        $this->log("Query with find-this-text in it issued", "wat-debug");      
        $this->log(Debugger::trace(), "wat-debug");     
    }
    // Added end

    return self::$methodCache[$method][$key] = $value;
}

This would permit you to identify what is directly responsible for injecting large volumes of data into the method cache; to then correct the application code so that the method cache can be enabled and used as designed.