Using APC cache with Doctrine & Symfony? Check again!

If you have read the documentation you probably know that having a Metadata cache for Doctrine is something you really want to have in production.

The setup in Symfony is pretty easy, you just have to edit the config_prod.yml:

doctrine:
    orm:
        metadata_cache_driver: apc
        query_cache_driver: apc

The problem is that the Dependency Injection Container is generated through the Command Line Interface, and if you do not have apc.enable_cli=1 in your php.ini DIC will use FileCacheReader instead.

You can check your /app/cache/prod/appProdProjectContainer.php to see if you are using APC cache.

    protected function getDoctrine_Orm_DefaultEntityManagerService()
    {
        $a = $this->get('annotation_reader');
        $b = new \Doctrine\Common\Cache\ApcCache();
        $b->setNamespace('sf2orm_default_5cdc3404d84577b226d7772ca9818908');
        $c = new \Doctrine\Common\Cache\ApcCache();
        $c->setNamespace('sf2orm_default_5cdc3404d84577b226d7772ca9818908');
// ...
        $g = new \Doctrine\ORM\Configuration();
        $g->setMetadataCacheImpl($b);
        $g->setQueryCacheImpl($c);
// ...
    }

If you can not find \Doctrine\Common\Cache\ApcCache you are not using APC to cache your metadata.

For a simple page with one query the difference between APC and File based caching can be quite big. Take a look at the numbers I got from XHProf for a simple page:

Cache type Wall time CPU time Memory usage
APC 254,972 µs 242,020 µs 10,352,536 bytes
File 355,617 µs 325,320 µs 11,579,568 bytes
Difference 39.47 % 34.42 % 11.85 %

4 thoughts on “Using APC cache with Doctrine & Symfony? Check again!

  1. Kuba

    The problem is that data stored in APC is removed when the process finishes. This means you’re starting with an empty cache each time you’re executing a script in CLI.

  2. Goran Jurić Post author

    Yes, that is true, APC is of no use in CLI, but the Dependency Injection Container that is being compiled from CLI is later used while serving requests through the web server.

    And if during compilation you don’t have access to APC, DIC will be compiled so that the Doctrine uses the File cache, which is suboptimal.

    The problem is actually in a way Doctrine is configured if you do not specify concrete Cache implementation you would like to use, from the Docs:

    If $devMode is false, check for Caches in the order APC, Xcache, Memcache (127.0.0.1:11211), Redis (127.0.0.1:6379) unless $cache is passed as fourth argument.

    You could specify in the DIC that you want to use APC cache specifically, but then again you can’t use that container definition in CLI scripts if you do not have APC enabled.

  3. Daniel Richter

    What about clearing the cache while passing the -d apc.enable_cli=1 parameter? That way the container should be built while apc is enabled, but other cli tasks still run without apc. I actually had problems running composer with apc enabled, so I didn’t want to permanently enable it in php.ini.

  4. Bertrand

    Hi.
    Thank you so much for this information, Goran, you helped me a lot.
    For those who use Zend Framework 2 Doctrine ORM Module (https://github.com/doctrine/DoctrineORMModule) like me, putting 'metadata_cache' => 'apc' in the Doctrine configuration didn’t work well. Adding apc.enable_cli=1 in my CLI conf.d/apc.ini and reloading Apache conf solved the problem.
    Regards.

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>