Volatile Data Caching Harms Your Performance

No alt text provided for this image
Two Approaches to Performance Optimization

Yesterday I posted a small teaser about 260k real SKUs with many configurable products.

I asked my followers on multiple platforms to pick which utilizes cache and which does not, and the majority took Option A. Although this option sounds incredibly reasonable, it is that Option B relies heavily on caching to achieve its performance goals and is a very problematic way to solve performance issues.

Problem with Caching

Let's examine Option B more thoroughly and explain its problem.

Let's run an identical load test, but this time, we are going to emulate the activity on the website when our product-related caches get invalidated (store manager updates products, customers buy products, etc.):

No alt text provided for this image
Heavy Performance Optimization Using Cache when we invalidate the cache

As you can see, TTFB is all over the place, and the system hits cache misses like crazy. The reason is in the default strategy utilized by the core team and by most developers when encountering a slow-performing code path - wrap around this slow code into a cached statement.

The problem with this approach is that cache storage is costly in PHP. There is no shared in-memory storage across all requests unless you write your web server in a non-blocking framework like AMPHP or ReactPHP.

In Magento, putting something into the cache involves an I/O call to a server like Redis, which sends packets over the data center network.

No alt text provided for this image
Category page with configurable products

Let's take a look now at the webshop we are testing.

Each configurable product on this page has an entry in the cache for the price of the configurable product.

It means that when you render a page, we make 36 requests to the cache server to try to find a cache entry and then generate ones when there is a miss and writes an entry to cache storage.

In my load test, the difference is manageable because both Redis and PHP are on the same machine. Still, it will have a much higher impact on production, and the average render time will be around 600ms+ because packets are traveling over the wire.

Alternative Path

Do you know what the solution is? Rollup up your sleeves and optimize N+1 query issues in your webshop with a data preloader. That's precisely what we did during the training I organized in Barcelona this year.

First, we started with finding culprits with the help of Blackfire.io .

No alt text provided for this image
Profile of category page with configurable before optimization

So based on this profile, we found our main culprit in price rendering and saleability check of configurable products.

We wrote five very simple plugins and four preloaders in a few hours to optimize those places. Now our webshop does not do any unnecessary SQL queries and does not do any reads for that data from the cache either.

No alt text provided for this image
Profile of category page with configurable after optimization

Of course, there are more things that we can optimize there, like currency renderer, but that is a topic for another day. We achieved our goal of not doing additional I/O for each product, and our rendering performance is not affected anymore by updates to product data as we do not rely on the cache.

No alt text provided for this image
Performance Optimization without cache when we invalidate the cache

As a side effect, now our cache does not grow together with our catalog size, so less volatile data like configuration, layout, and menu stay in the cache longer because they won't get evicted by writes related to the product price.

The total number of cache records in storage with this approach during load tests did not go above 160 keys, although we have a lot of products and categories.

Summary

Do not cache highly volatile data and focus on optimizations of the way how you use that data instead.



Yousaf Waseem

Senior Certified Magento Developer | Expert in Building Scalable and Robust eCommerce Platforms.

11mo

Being a Magento Certified Backend Developer, I appreciate your in-depth analysis of the performance optimization approaches, Ivan Chepurnyi It's insightful to see the potential pitfalls of heavy caching, particularly in the context of the costly nature of cache storage in PHP and the impact on TTFB. Your suggestion to tackle N+1 query issues with a data preloader presents a hands-on alternative. However, it would be valuable to delve into the trade-offs and considerations in choosing between caching and query optimization, as their effectiveness may vary based on specific project requirements and constraints. Overall, a balanced exploration of these strategies is crucial for developers navigating performance challenges.

Like
Reply
MANTHAN SONI

Magento and NetSuite API Developer in Toronto

1y

Ivan Chepurnyi First of all thank you very much for great preloader extension. It really helps to overcome N+1 issue and also helps to kill N+1 issue in third party extensions, before I was using registry to save products data to load product custom attribute text, now I apply your strategy and it really works well. Your preloader extension is boon for Magento community, Adobe commerce version has same N+1 issue or they have different architecture?

Like
Reply
Erik Hansen

I build eCommerce technology @ Kraken Commerce

1y

Great article. Data pre-loading is a great strategy.

Like
Reply
Pradip Shah

Founder at luroConnect

1y

Ivan Chepurnyi that is so true! We have had customers who had 8 seconds + for category pages and they would like to use caching to fix it. As a temporary measure we asked them if they can afford stale content!

Like
Reply

To view or add a comment, sign in

Insights from the community

Others also viewed

Explore topics