Magento has a built-in cache. In version 1.5.0.1 Magento added a Full Page Cache option to Magento which gives us the ability to use holepunch techniques to cache blocks. This section here doesn't deal with the full page cache at all, rather just uses the standard Magento cache and we add the ability for Magento to cache category lists
In the below examples, we haven't yet added the caching. We use the following (example) command from Apache Benchmark on the local machine the tests are being run on to run the tests, which eliminates network contention
ab -c 5 -n 100 http://www.testdomain.com/category
Before: Stats Showing # of Database Queries & Time Taken for 100 requests
Below, you can see that we had 153 requests to the database. The total time to run the tests was 19.452 seconds resulting in 5.14 requests per second. The median wait time to process each request was 666 milliseconds
Concurrency Level: 5
Time taken for tests: 19.452007 seconds
Complete requests: 100
Failed requests: 0
Write errors: 0
Total transferred: 12481500 bytes
HTML transferred: 12433700 bytes
Requests per second: 5.14 [#/sec] (mean)
Time per request: 972.600 [ms] (mean)
Time per request: 194.520 [ms] (mean, across all concurrent requests)
Transfer rate: 626.57 [Kbytes/sec] received
Connection Times (ms)
min mean[+/-sd] median max
Connect: 0 0 0.4 0 3
Processing: 608 961 579.6 700 4578
Waiting: 580 924 581.1 666 4542
Total: 608 961 579.7 700 4579
Percentage of the requests served within a certain time (ms)
50% 700
66% 851
75% 1053
80% 1160
90% 1670
95% 2258
98% 2778
99% 4579
100% 4579 (longest request)
Below are the database statistics provided by the profiler
Executed 153 queries in 0.0114271640778 seconds Average query length: 7.46873469135E-5 seconds Queries per second: 13389.1487826 Longest query length: 0.000326871871948
After: Stats Showing # of Database Queries & Time Taken for 100 requests
Now we have made the changes, you can see that we had 64 requests to the database. The total time to run the tests was 12.546 seconds resulting in 7.97 requests per second. The median wait time to process each request was 439 milliseconds.
Concurrency Level: 5
Time taken for tests: 12.546279 seconds
Complete requests: 100
Failed requests: 0
Write errors: 0
Total transferred: 12481500 bytes
HTML transferred: 12433700 bytes
Requests per second: 7.97 [#/sec] (mean)
Time per request: 627.314 [ms] (mean)
Time per request: 125.463 [ms] (mean, across all concurrent requests)
Transfer rate: 971.44 [Kbytes/sec] received
Connection Times (ms)
min mean[+/-sd] median max
Connect: 0 0 0.0 0 0
Processing: 409 619 339.7 474 2258
Waiting: 383 583 339.5 439 2222
Total: 409 619 339.7 474 2258
Percentage of the requests served within a certain time (ms)
50% 474
66% 541
75% 625
80% 715
90% 922
95% 1518
98% 1928
99% 2258
100% 2258 (longest request)
Below are the database statistics provided by the profiler
Executed 64 queries in 0.00508761405945 seconds Average query length: 7.94939696789E-5 seconds Queries per second: 12579.5705516 Longest query length: 0.000263929367065
This equates to a 50% speedup for category listings
How to Make the Code Changes
We need to override the core List.php file to make these changes. To do this via SSH:
mkdir -p app/code/local/Mage/Catalog/Block/Product/
cp app/code/core/Mage/Catalog/Block/Product/List.php app/code/local/Mage/Catalog/Block/Product/List.php
This overrides our core product list file with our own version that we can now modify accordingly. Now modify the file like so:
app/code/local/Mage/Catalog/Block/Product/List.php
class Mage_Catalog_Block_Product_List extends Mage_Catalog_Block_Product_Abstract
{
/**
* Default toolbar block name
*
* @var string
*/
protected $_defaultToolbarBlock = 'catalog/product_list_toolbar';
to be
class Mage_Catalog_Block_Product_List extends Mage_Catalog_Block_Product_Abstract
{
protected function _construct()
{
$this->addData(array('cache_lifetime' => 9999999999,));
}
public function getCacheTags()
{
return array(Mage_Catalog_Model_Product::CACHE_TAG);
}
public function getCacheKey()
{
return $this->getRequest()->getRequestUri();
}
/**
* Default toolbar block name
*
* @var string
*/
protected $_defaultToolbarBlock = 'catalog/product_list_toolbar';
Credit for much of this goes to Chris Farley on Magento Forums