I recently had the task to boost the performance of a really really slow catalog search in Magento. One of the problems was the autocomplete that needed about 5 seconds to load. You definitely finished writing up to then and don’t need any autocomplete anymore.
So first things first, find out what makes your AJAX call so slow if it just returns some kB (1.5kB for me). In my opinion, the best tool to use is AOE Profiler by Fabricio Branca. After installation you can go to System > Configuration > Developer > Debug > Profiler and enable tracking. This sets a cookie and for the time being active (you can deactivate it in the same place again) every request sent to your shop frontend will be tracked in detail. And when I say detail, I mean every detail. Information about controllers, actions, blocks, templates, events or observers are logged hierarchical and you can see the time spent in those “buckets”. So you can easily find the buckets where your request spends its valueable time.
In my case I found out that although the request needed to return only a list of possible search terms, the whole page layout was loaded. Although never being rendered, this was really unnecessary.
So the first thing I did was skipping $this->loadLayout()
inside my controller action. Notice that you will not be able to load any blocks from a not loaded layout then.
This already saved around 1s of loading time.
The second goal was to decrease the response as much as possible.The old response looked pretty much like this:
{ items: '<div class="search-terms"> <ul> <li class="search-term active"> <a class="search-term-link" href="https://URL/autocomplete/ajax/get?q=term1">term1</a> </li> <li class="search-term"> <a class="search-term-link" href="https://URL/autocomplete/ajax/get?q=term2">term2</a> </li> <li class="search-term"> <a class="search-term-link" href="https://URL/autocomplete/ajax/get?q=term3">term3</a> </li> </ul> <div class="loading wheel">Search terms are loaded</div> </div>', success:true, query:'term' }
A lot of data for just 3 words, isn’t it? The markup is the same for every link so why transfer it? Why transfer the markup for the loading wheel over and over again?
So what I did then is remove the rendering of any blocks from the controller action and replace it by a neat little json output.
{ items: ['term1','term2','term3'], success: true, query: 'term' }
The DOM elements are then created by the javascript processing the response.
Did it work?
In the end, I rechecked the loading time of my AJAX request. Actually I was more than surprised when seeing, that those two little changes doubled the speed. My request now loads in only 1.7-2 seconds. At this point, there is still room for improvement, but this didn’t take a lot of effort and made a huge difference for usability.
At the end we added those paths to the full page cache (that already existed but wasn’t used for AJAX calls). This makes the second call of the same query incredibly fast. We talk about less than 100 milliseconds here. But don’t think that using the fpc would have solved the problem all alone because
- it would still have transmitted more data than necessary
- the “first” uncached call would still have been slow and not usable
So first eliminate the cause of your performance lack and than boost it using your fpc.