There are already many (partly outdated) blog entries (e.g. 8-ways-to-speed-up-cakephp-apps) and stackoverflow questions/answers (e.g. speeding-up-cakephp) regarding this question. But from years of experience I want to outline the more important ones pretty quick.
I will not talk about the little things or the ones that will only affect 5% of the website.
And no – debug level 0 is not a speed improvement. It is an absolute requirement for any live application and can therefore be seen as default setting.
One last note: I want to address dynamic websites here that cannot make use of extensive view caching or even html caching as described in the first link – at least for most of the pages. They undoubtedly are the fasted way to serve content but can usually only applied to very few views. The tips below are valid for all requests across your application.
1. Opcode Cache
Opcode Cache will keep your php files in the memory. It will usually also store the compiled bytecode of it to further improve execution time. But it is not only improving speed a great bit, it is also reducing the memory used for a single request by more than 50% allowing your server to serve twice as much requests (and therefore users) before overworking itself. A mediumsized cake2 application of mine uses 13.9 MB memory. With Opcode Cache it is reduced to 7.7 MB. And the speed is pretty much accordingly.
Installation is almost too easy. Example for ubuntu and apache: apt-get install php-apc and restarting the apache should do the trick.
But there are other modules, as well (Xcache, Memcached, …)
Gain: in most cases more than 100% (more than twice as fast)
2. Also use memory caching for all temporary data
This mainly includes “tmp files” via CacheEngine which can be cake core tmp files or app tmp files. All your cached elements will be included faster this way, as well. If you cache your sql queries they will also be affected positively compared to a simple file cache (although a file cache itself is better than nothing).
Cake2.x automatically tries to use the fastest CacheEngine if available (and defined in your core.php):
$engine = 'File'; if (extension_loaded('apc') && function_exists('apc_dec') && (php_sapi_name() !== 'cli' || ini_get('apc.enable_cli'))) { $engine = 'Apc'; }
Gain: 10-40%
3. Speed up (Reverse) Routing
This will help for sites with many dynamic links. Without caching the generated urls Router class creates them over and over again. You can use my UrlCache plugin which basically does exactly that. I used the ideas of lorenzo and mcurry and applied some fixes and improvements. It now stores commonly used links (without any params) in a global cache file while using single cache files per site for the specific urls (e.g. from pagination/filtering).
If you only got a bunch of those links on a single page, this is wasted time, though. But for most projects it is a real time saver – from 0.3 seconds up to 1 second less request time.
Important note: You need to manually configure your _cake_core_ cache for this:
Cache::config('_cake_core_', array( 'engine' => $engine, 'prefix' => 'cake_core_', 'path' => CACHE . 'persistent' . DS, 'serialize' => ($engine === 'File'), 'duration' => $duration, 'lock' => true, # !!! ));Note the exclamation marks. If you do not apply
'lock' => true you will end up with quite a few broken cache files. This will reset the whole thing all the time due to concurrent requests/writing and you gain nothing… See this ticket for details. With this setting the problems seems not to occur.
To further optimize performance I invented a dual cache system with reading unlocked and writing locked. See the plugin for details on how to use it for best results.
Gain: 10-50% (the more links on a page the more gain)
4. Optimize data, compress and cache assets
If you got 50 icons on your site, you might want to create a single sprite instead of creating +50 requests to your server here. You also should combine your js/jss and apply some compressing.
In general it is a good idea to send all data gzip compressed – using apache’s mod_deflate module for example. This way only half the amount of bytes need to be sent to the user. Especially with (slow) mobile connections this will increase speed up to 100%.
Using mod_headers you can make sure asset files are not permanently requested if they didn’t change. The website will feel faster for the user and the server has to serve less requests.
Files of the same type (css, js) should be packed and sent combined to a single file (as opposed to maybe 20-30 single files). Undoubtedly Mark Story’s AssetCompress plugin is one of the best ones out there to address exactly these issues.
Gain: 10-30% (might also depend on the browser)
Some stuff I didn’t try yet
In Cake2 you can even store sessions in the Cache (and therefore probably in the memory). This should also speed up the application remarkably compared to database sessions for example.
And the list of obligatory tips which should already be well known at last
- Use containable to restrict the amount of data to be fetched as the database connection usually is the bottle neck of any app
- Try to load stuff dynamically and only if needed (With Cake2 and lazy loading everywhere via App::uses() this shouldn’t be difficult to do anymore)
- Try to decouple time consuming stuff from the frontend. So rendering large images, creating complicated pdfs, sending bulk emails can all be passed on to some “Queue” which asynchronously works them off piece by piece without slowing down the response time for the action.
- As mentioned above you can cache complete pages to the View cache preventing the complete dispatch process to run. Such a pre-rendered html file will be served right away. This is useful for pages with mainly static content.
- Avoiding $uses in the controller (except for its own model, of course) – meaning we should never have more than the primary model attached to it.
- Make sure you send the right headers for proper client-side caching. Some browsers might not respect it, but the ones that do will profit from the increase in speed.
- Don’t use
requestAction
Update – 2012-02-20 – Benchmark
There is a benchmark site comparing all kinds of frameworks.. Unfortunately, using 1.3 instead of 2.x. But either way it displays how important it is to apply above optimization. If that is the case I bet the results will be way less dramatic.
