APC Object Cache Backend for WordPress

I wrote the original APC Object Cache backend for WordPress back in 2006. Shared it via a link on the wp-hackers list, and until a few days ago, hadn’t touched it since.

It has now been updated to version 2.0.1, and should work more efficiently. It supports increment/decrement, and you can now use it to power Batcache, the whole-page caching engine used on WordPress.com! In fact, for single-server sites, it should perform a lot better than Batcache + Memcached (because Memcached is a separate application and connections from PHP have some latency).

If you have no idea what I’m talking about, read on.

WordPress has a built-in object caching API. It is usually used to store complex data objects or HTML structures which are computationally expensive to create on the fly. By default, the engine is implemented in PHP memory. That means that objects don’t persist in-between requests. The only benefit there is if you’re accessing the same objects multiple times on one request.

Enter persistent object cache backends. These backends store the data objects between page loads, which saves your server a lot of time and speeds up the user experience. APC is both an opcode cache (which speeds up PHP in general) and an in-memory key/value store which persists between page loads. If you have it installed (or can install it), I highly recommend that you do so. Unfortunately this probably won’t be available to anyone on shared hosting — VPS/dedicated only. Once you have APC up and running, as confirmed by phpinfo();, install the APC Object Cache in your WordPress content directory. It is a special kind of plugin, and will not work if placed anywhere else. It also needs to keep its name: object-cache.php

You should notice improved page load times! I’ve seen it improve page generation time 10x.

And what about Batcache? Batcache is a whole-page or “HTML output” caching engine. It stores complete web pages and saves them for later. It needs a persistent object cache backend to function. Furthermore, it needs an object cache backend that supports incrementation (counters, to measure how much traffic each URL is getting), and that does its own object expiration. Memcached has fit the bill, and is the preferred solution for multi-web-server WordPress installs. Now with the new version of the APC Object Cache, there is a preferred single server solution as well.

Note: W3 Total Cache users need not apply — it handles its own object caching, including support for APC.

61 thoughts on “APC Object Cache Backend for WordPress

  1. I’m currently moving all my sites into a single multi-site install. Right now for each separate site I use W3 Total Cache with APC enabled (I do run a VPS).

    In your opinion, what would be the best caching method for my new multi-site install? I don’t know the repercussions of installing W3 Total Cache on each site, because I know in ways that might not be the most optimal caching situation.

    The caching mechanisms in WordPress are still a little foreign to me, as I have always had decent success with just using a caching plugin, and never had to dig into the details. But lately I have been thinking of building out this multi-site install into a platform for my clients to create their own sites, and am becoming more interested in how to squeeze every last bit out of these servers.

    Thanks Mark, I always enjoy your posts.

    1. It depends. I like Batcache, because it is simple, and only caches when a page gets hit a lot. It uses a formula like this: “If URL ‘U’ gets hit X times in Y seconds, cache it for Z seconds.” So you don’t have to worry (too much) about parts of your site that you want to remain dynamic.

      But W3 Total Cache is definitely more full-featured. For popular and media-heavy sites, the CDN feature is killer. And it does HTML/CSS/JS minification plus a bunch of other stuff. W3TC probably will result in faster average page generation time. So it depends on if you want to make your pages as fast as possible (W3TC) or if you’d sacrifice speed for a more dynamic experience (Batcache).

      And if you have a situation like that of WordPress.com, where they have (I’m assuming) billions of URLs, Batcache is the way to go, because you want to focus your efforts on pages that receive the most traffic. Trying to cache the long tail is not worth it.

  2. What about other caching engines, such as eAccelerator, which is available via cPanel (via its WHM front-end) or separately, Xcache and so forth?

    Peace,
    Gene

    1. I was going to ask the same thing. I run W3 Total Cache with Xcache on a DreamHost PS under nginx, and it definitely seems to be doing its thing nicely on a small site. We all like to think our sites are going to get more popular in the future, and I’d prefer to not get caught up in tweaking later down the line.

      DreamHost PS doesn’t provide automatic setup of APC, so before I install it manually, I’d like some expert opinion.

    2. There are backends available for eAccelerator and Xcache. I’ve just had better luck with APC, and it seems like it has a good future as it is slated to be included in PHP itself.

    3. As far as I know, eaccelerator now only opcode cache, not data cache. Since 0.9.6 release developers removed a lot of functionality from eaccelerator. So, it can’t be used now as the cache for user data. Only as bytecode cache. When I’d saw this – I moved to APC.

  3. If you’re already set up with W3TC don’t bother with this. This is for people with APC who want object caching alone, or want Batcache + object caching.

  4. Are there any similar options for a shared server install? I can’t afford a private server yet, but my site calls a lot of custom fields per page – I think this kind of caching will help decrease the processor load?

  5. Didn’t work here. Led to pages with bizarre HTML output (missing menus, partially rendered pages, etc.). Not sure why, and didn’t see any clues to help. Should the enable_cache still be set to true in wp-config?

    1. Erik — try this version: 2.0.2-beta. I developed version 2 using a newer version of APC. When using an older version, I saw errors like the ones you saw. 2.0.2-beta is working for me when using an older version of APC. Let me know how it goes!

      And ENABLE_CACHE doesn’t do anything in WordPress anymore (but doesn’t hurt anything either).

    2. Indeed, 2.0.2 seems to work. I have APC 3.0.19. I’m going to investigate moving up to 3.1.4 later today. In the meantime, 2.0.2beta seems to work. Thanks.

  6. Mark

    Messing up with your new plugin and it pretty much works for the busy site I was implementing it for, although I am not sure if a ratio of 10 inserts versus 100 reads per second is good enough. I also ended up with 2 GB of user cached variables…

    I just noticed that the numbers of comments for a post, listed on front page are not updated. It seems that WP is using the obsolete post object.

    What do you think, is there a way for us to customize what your object-cache.php does to WP.

  7. update — using wp_cache_flush after each update to the blog. would that be a good idea?

    if (function_exists(‘wp_cache_flush’)) {
    add_action(‘publish_post’, ‘wp_cache_flush’, 99);
    add_action(‘comment_post’, ‘wp_cache_flush’, 99);
    }

  8. This plugin works great, a huge speed up on my self hosted website.

    The only problem I have found is that Google XML site map does not play nice.

    With this plugin enabled, then the sitemap wont run correctly

    disable then the sitemap works fine.

    Th esolution I used was to rename the plugin, run sitemap, then re-enable,

    I am very happy other then that

    1. @colin
      I had same problem, but solved it by disabling and reinstalling google xml sitemaps…
      AND using the “reset to defaults”.
      it seems to like it’s defaults better….. starts fresh.
      then I can change the settings to my liking again.

      This problem mostly occured after trying alternate cacheing systems (w3tc, quick cache, hypercache, etc… in testing).

      once reinstalled and “reset defaults”, played nice as ever.

  9. hi,
    I have APC installed, dropped in your object-cache.php and it populates user variables. done.

    thanks.

    So I move on to batcache, and find no indication of how it should work with apc… all references and docs point to memcache.

    Is there a “how-to” use batcache with apc somewhere?
    in WP, I have ENABLE_CACHE and WP-cache both set to true. Dropped in batcache (picked up from WP plugins directory), installed, no go.
    Moved Advanced_cache.php to wp-contents.
    Ended up with error on site indicating something like format not recognized.

    so to be clear.
    object_cache.php and advanced_cache.php are in wp-contents directory.
    batcache.php is inside folder called “batcache”.

    I’ve missed something?

    1. I gave up on Batcache I could not get it working.

      WP Super Cache has an option to use the object cache and although experimental it works well. Eve though my site only supports half-on, it makes a heck of difference to the speed

    1. nice improvement 🙂

      just to be clear, you mean the page load of the html served up to the browser? (the external calls to css, js, images, etc, seperate from this) . Is that correct?

      I’ve got apc on, and the the apc object-cache.php in, page load, as per above, is around 2.6 seconds.
      quite acceptable… but it would be nice to shave about a sec off that too 🙂

  10. Mark, can you confirm if I’m running multiple instances of WP on a VPS and use the WP_APC_KEY_SALT for each config that they won’t conflict and serve one install on the other? Seems to be the issue I’ve had in the past.

  11. My experience with trying to use APC object caching with multiple instances is that the APC cache “confuses” the different installations, and one site gets served as the other. I *believe* setting the key salt resolves this, but in my attempts to use other suggestions for this, I failed. Getting object caching and any other type of caching, batcache, Super Cache, working together certainly will reduce load on the VPS as I understand it.

    1. This backend automatically distinguishes between different installs, without having to set WP_APC_KEY_SALT. That constant is only if you have some sort of weird pseudo-WPMU setup with a shared wp-config.php file that switches the table name on the fly. So… something really esoteric. Normal usage will be completely separated.

  12. Thanks Mark. I had tried it with the key set in wp-config, and was getting a ton of “Potential cache slam averted for key” errors in my Apache logs, so I removed the object-cache file. I’ll try it without setting the key and see what happens. I googled that error and saw that there might have been a bug somewhere along the line in APC, the blog post everyone links to regarding the error seems to be gone.

  13. still get the potential cache slam averted for key errors from line 235 of the object-cache file. Out of curiosity, what version of APC and PHP did you develop this with? I have 5.3.2 for PHP and 3.1.3p1 for APC.

  14. Hi Mark – thanks for your work on this. I’m getting the same errors in Apache’s error.log as Michael Bishop above:

    [apc-warning] Potential cache slam averted for key ‘xxx’ in /var/www/xxx/public/wp-content/object-cache.php on line 110.

    I also get weird behaviour in admin with objectcache.php and batcache enabled – e.g. widgets not sticking and plugins not enabling or disabling correctly.

    I’m on php 5.3.3 and APC 3.1.3p1 on Debian (via dotdeb repositories).

    I would really like to use batcache as it fits my use case perfectly so I hope you might be able to help.

  15. RedHat ES 5 still uses PHP 5.16. It’s too bad your plugin won’t work with previous versions of PHP 5. I’ll have to wait for RedHat ES 6, which is still in Beta2.

  16. We tried using this on our http://buildaroo.com site where we are running APC 3.0.19 / PHP 5.2.14 w/php-fpm enabled on a WordPress 3.01 installation (multi-site mode enabled) and got the dreaded ‘white screen of death’ after running it for 15 minutes. We even enabled apc.filters to try and avoid it: apc.filters = “(kses\.php)|(wp-cache-.*\.html)”

    but to no avail. our current apc config is below. any ideas?
    ; Enable apc extension module
    extension = apc.so
    ; Options for the apc module
    apc.enabled=1
    apc.shm_segments=1
    apc.optimization=0
    apc.shm_size=128
    apc.ttl=7200
    apc.user_ttl=7200
    apc.num_files_hint=1024
    apc.mmap_file_mask=/tmp/apc.XXXXXX
    apc.enable_cli=0
    apc.cache_by_default=1
    apc.filters = “(kses\.php)|(wp-cache-.*\.html)”

    1. Same issue here. No one on the Internet seems to know what to do about this. White screens are intermittent/rare and simply reloading the page “fixes” the problem. Occasionally, the entire server goes out of whack and all whitescreens. No errors in the log files. The only fix is to restart php-fpm.

      After much experimentation, we’ve come to the conclusion that there is a conflict between WP Super Cache and APC. I’m thinking about dropping APC and replacing it with another opcode cache to see if the problem goes away.

    2. We are now trying the following in php.ini:

      [apc]
      apc.filters = wp-cache-config
      apc.include_once_override = 0

      You don’t have the ‘include_once_override’ line. We are using defaults for everything else.

      We’ll see if this fixes the problem. Probably not. An alternate opcode cache may be the only solution. The author of WP Super Cache knows about the issue and seems to recommend xcache. Other people run into issues with APC and have tried eAccelerator and found stability there. But it is hard to tell what software these people are running on their systems and swapping key parts of PHP into a live production system is not exactly easy or a smart thing to do.

  17. Hi Mark,

    I am running your APC Object Cache 2.02 for WordPress 3.01 with Batcache 1, with APC version 3.14 and PHP version 5.3.3. I also defined a key salt in my wp-config.php:

    define(‘WP_APC_KEY_SALT’, ‘biglongkey’);

    I have multiple single server installs for multiple blogs not sharing the wp-config.php, but I defined the keys uniquely anyway.

    I am seeing the following errors in my log:

    Oct 30 01:10:51 web1 httpd: PHP Warning: apc_store() [function.apc-store]: Potential cache slam averted for key ‘wp:a95b048025de0e319c48be3908a4ff22:1:options:notoptions’ in /var/www/wp-content/object-cache.php on line 235
    Oct 30 01:10:51 web1 httpd: PHP Warning: apc_add() [function.apc-add]: Potential cache slam averted for key ‘wp:a95b048025de0e319c48be3908a4ff22:1:post_tag:43’ in /var/www/wp-content/object-cache.php on line 110
    Oct 30 01:10:52 web1 httpd: PHP Warning: apc_store() [function.apc-store]: Potential cache slam averted for key ‘wp:a95b048025de0e319c48be3908a4ff22:1:options:notoptions’ in /var/www/wp-content/object-cache.php on line 235

    I am not sure how to resolve these errors.

    1. I found there is a known bug in APC 3.14 regarding the cache slam defense. To eliminate the errors, which allowed me to upgrade to APC 3.14, I added the following line to my php.ini:

      apc.slam_defense=0

  18. Why no support for Xcache? I’ve found APC to be very buggy, and it has been in beta for several years, so there is no “stable” version right now that support PHP 5.3. However. Xcache has been stable, and has support PHP since August of 2009.

    I used Xcache for several years on a high traffic single server WordPress install that never even had a hiccup before moving it to memcached.

    I would like to see how your Object Cache plugin for WordPress performs with Xcache. If you decide to modify it a little to support Xcache I’ll give it a try and let you know how it does.

  19. APC has been updated to 3.1.5 and specifically “- Fixed bug #16966, apc produces tons of warnings “Unable to allocate memory for pool”.”

    I’m updating tonight and will test against Mark’s plugin and report back.

  20. I’m getting warnings:

    PHP Warning: apc_add(): Potential cache slam averted for key

    php-5.3.5
    apc-3.1.7
    APC Object Cache 2.0.2

  21. Just wanted to thank you for the plugin. For some reason, WP Super Cache didn’t work on my site. I already installed W3 Total Cache on another site on the same server. I’ve been looking for an alternative for a long time. Somehow only today, I came across this article (and the plugin). Now my site runs APC Object Cache Backend and Batcache. Both are very hard at work and I could definitely see the increased load time.

    Pothi

  22. Using this causes my sidebars to disappear. This is apparently a known issue with the encoding of WordPress sidebars:

    http://wordpress.org/support/topic/catgegories-disappear-from-sidebar-after-object-cache-activated

    Unfortunately the link on that page to “Check out my site for a full explanation, and fix” goes to a broken page 😦 Is there any known solution to this problem? I don’t want to disable this plugin, the performance benefit is wonderful.

  23. Super, thanks. It’s significant, the effect that properly setting MySQL variables can have on speed.

    Thanks, Amy.

  24. Sadece eklenti için teşekkür etmek istedim. Nedense, WP Super Cache sitemde işe yaramadı. Zaten, aynı sunucu üzerinde başka bir sitede W3 Toplam Önbellek yüklü. Ben uzun bir süre için bir alternatif arıyordum. Her nasılsa sadece bugün, ben bu makalenin (Plugin) karşılaştım. Şimdi benim APC Nesne Önbelleği Backend ve Batcache çalışır. Her ikisi de iş çok zor ve ben kesinlikle artan yükü zaman görebiliyordu.

  25. I run a WP site with about 60,000 daily pageviews on a 512 Linode VPS. I’m using nginx and php-fpm. I do quite a lot of custom querying on each page that changes with each pageview, so I don’t think Varnish is for me, but I’ve followed your instructions and installed APC and the APC Object Cache plugin. I immediately saw a reduction in CPU usage (which also seems to react less extremely now to simultaneous requests). My memory usage also went down, which I wasn’t really expecting. Upon activating APC and the drop-in plugin my Disk IO immediately shot up significantly from 100 to over 1000. Switching the mmap to /dev/zero sent this back down to normal. Now, the thing is, I’m not getting much in the way of speed increases. At least Analytics page speed and such don’t seem to be showing any improvement.

    I’ve assigned a apc.shm_size of 140M, having read it should be around double the max size it reaches to avoid fragmentation. It tends not to go above 65 megs used. Despite that, fragmentation steadily increases. Right now, after 20 hours uptime, it’s at 17%. What could be causing that? My file cache shows a 100% hit rate, with 231 files (25 meg). The User Cache seems like it must be the problem:the hit rate is 141 cache requests/second and the miss rate is 1.77 per section.

    I’m just wondering where this increasing fragmentation is coming from, if the size never even goes past half of its allocated maximum. I’ve increased the shm size on the system itself as well, so that’s not the problem.

  26. I created a site for a client who has a host running APC. The site suffers from frequent “ERROR ESTABLISHING DATABASE CONNECTION” messages. It does not have this trouble on its development server, which is at a host without APC. Do you think your plugin will resolve this issue on the production server? There are not a lot of pages in the site, so really, the same page is being pulled over and over again.

    Thanks.

Comments are closed.