Volatile Data Caching Harms Your Performance
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.):
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.
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 .
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.
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.
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.
Senior Certified Magento Developer | Expert in Building Scalable and Robust eCommerce Platforms.
11moBeing 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.
Magento and NetSuite API Developer in Toronto
1yIvan 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?
I build eCommerce technology @ Kraken Commerce
1yGreat article. Data pre-loading is a great strategy.
Founder at luroConnect
1yIvan 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!