Advanced ways to improve Magento TTFB

Spend time shaving time

Beyond quick Magento performance wins, there's a lot more that can be done to improve performance; but these take a little more time, a little more testing - but often provide the best results.

TTFB Advanced

Change your search back-end

The native Magento MySQL search is not only woefully inaccurate, its also slow. Replacing it with an alternative back-end not only means improved search accuracy, but also performance.

MageStack natively supports,

If you are using Enterprise Edition - you'll have the benefit of built in SOLR, so its case of enable it and go - in seconds. If you are using Community Edition, you'll need to install a 3rd party module to provide the communication between the back-end and Magento. I can't provide any recommendations, but I know that customers have been happy with Mirasvit Sphinx, SOLRBridge and Solarium and BubbleShop Elasticsearch.

Remove unused modules

Often stores have modules that are no longer used, that are still installed. Not only does this pose a security risk, but it also adds overhead.

I've found that breaking down modules into three categories is the best way to plan what should stay and go,

Category Example
Essential for functionality Payment gateway etc.
Nice to have Layered navigation module etc.
No longer need Disabled/unused modules etc.

Go through all the modules on your store and categorise them, then anything in the "No longer need" column should be fully deleted (not just disabled).

You can generate a list of installed modules using the following SSH command,

cd /microcloud/domains/example/domains/example.com/http
find app/code/community/ app/code/local -maxdepth 2 -mindepth 2 2>/dev/null | sed 's#app/code# - #g'

Cache top navigation

Magento made a change to the way the top navigation block caching was handled, so that a separate cache entry was held per category. The only reason for this change was to facilitate the ability for a CSS class to be added to the active category.

This change had a monumental effect on performance, and resulted in every category page having to generate the top navigation (which can take 0-2 seconds), and also means the cache size is multiplied by the number of categories on the store.

Reverting this change means that you'll reduce cache swelling and improve performance considerably, site-wide; its as simple as removing a couple of lines of code. Whilst editing the core isn't recommended, this is a change I wouldn't hesitate to make, if needs be, bundle it into a custom module - or just throw caution to the wind and edit the core (I would).

In app/code/core/Mage/Catalog/Block/Navigation.php, remove/comment the lines marked with -,

public function getCacheKeyInfo()
...
- $this->getCurrenCategoryKey()
...
- $cacheId['category_path'] = $this->getCurrenCategoryKey();

The only consideration that you need to make after this change is to use JavaScript to find/remove the .active class, and correctly apply it on the right category link as necessary.

Block search suggestions

Sadly, there's no simple way to disable AJAX search suggestions via the admin and often many stores don't use AJAX suggest at all. If you aren't using this feature (or specifically, if your customers don't actually take advantage of it), then the simplest way to disable it is to block the request on the server.

Add a rule to ___general/example.com.conf,

if ($request_uri ~* "/catalogsearch/ajax/") {
return 403;
}

Outbound CURL requests

A true devastator of performance that occurs in both normal operation and especially in a peak situation is modules that "call home" creating a shared fate scenario. In this context, calling home often means,

  • Checking a module licence validity against a remote web server
  • Fetching resources from a remote location (often happens with product review/rating modules)
  • Stealing customer card holder information On MageStack, we log all outbound requests; both for HTTP and HTTPS - so that we can track the impact of modules calling home. Existing customers should submit a ticket for more help diagnosing this.

For those self-hosting, a simple way of viewing traffic is using tcpflow (adjust your interface name to suit),

tcpflow -p -c -i eth0 '( dst port 80 )'

So for performance, reliability and security reasons - you need to be and must be tracking outbound connections from your store, so you can identify the modules doing it and remove the respective offenders.

Code-profiling

Code-profiling is the single, best way to identify poorly performing code and fix it. The native Magento profiling tool is an excellent start for this, supplemented by Xdebug and Webgrind where necessary.

This process identifies load()'s being called in loops, excessive collection loading (versus walking) and greedy SQL queries. Ultimately, with the goal of finding performance (and by proxy, scalability) bottlenecks and fixing them.

Code-profiling isn't just getting recommendations to combine CSS/JS or sprite images; it is a highly technical deep-dive into the PHP code executed on your store to find real performance problems and address then.

Full page caching and optimisation modules

I'll let you in to a secret, Magento stores go faster with less modules, not more. So forget about the idea that you can install another module to hide the performance problems of your other modules; it doesn't work like that.

Magento is slow

Sadly, the number one Magento myth is that Magento is slow - but it is not; its wonderfully fast. What makes Magento slow is badly built modules and inappropriate hosting.

Full page caching improves performance

Wrong again. It doesn't, it barely even hides poor performance. The finer details of the downsides of these modules as a solution for performance are covered in a separate article on 3rd party caches - I would definitely recommend reading it.

The best advice I can offer is to remove all caching and "optimisation" modules; address the root cause of the performance problem, then when you are ready, consider caching as a strategy to improve capacity, not performance. Far too frequently we see performance degradation when using modules like GTSpeed, Smush.it and other popular JS/CSS combine modules - and after removal, see an immediate performance improvement.

Your APM is hurting you

Magento APM

Please note - the overhead added by New Relic has been significantly reduced in more recent versions of both PHP and the New Relic agent itself following optimizations over time since this article was originally written, so this point in particular isn't as accurate anymore.

I love New Relic and App Neta - they are great tools that provide some fascinating information that would otherwise require a few steps to aggregate and collect. But, and this is a big one, they often come with a performance overhead.

Ironically, most people install APM's to identify and fix performance bottlencks, but in reality, they usually add overhead themselves and cause further degradation.

If you are using an APM, I'd recommend doing some performance measurements, with ~500 requests, with it both enabled and disabled. You might be surprised to find that it is slowing you down.

There are clever ways to deploy APM's so that the don't have any overhead, and its pretty simple. You split the resources on your load balancer (native in MageStack) to send 90% of traffic to a standard web server, and 10% to an APM enabled web server; and perform sampling yourself (in addition to the APM level sampling). If you've got sufficient web traffic, you'll be able to provide minimum customer disruption, whilst still providing useful metrics.

Alternatively, learning to use the tools available on MageStack will not only be cheaper, but faster too. Check out Kibana and use the existing dashboards, or even make your own to present the information you need.

Use native Geo IP

Performing Geo IP lookups is a slow, intensive process. In the majority of deployments I've seen, they actually poll a remote Maxmind hosted instance, causing a shared fate situation and huge performance and scalability issue.

MageStack has native, high performance Geo IP lookups as standard - every request that comes in is already tagged with the appropriate Geo IP information - you do not need to use the PHP library, or hosted services - you can simply grab the information from the $_SERVER variable.

See pre-defined server variables for a full list of Geo IP data.

[nectar_btn size="large" button_style="regular" button_color_2="Extra-Color-1" solid_text_color_override="#13348e" class="button button-bigger" text="Next article: Quick total load time wins" url="https://www.sonassi.com/blog/quick-total-load-time-wins" /]