magento2: Performance problem on listings and widgets with Price box

Preconditions (*)

  1. 2.4-develop or any previous version

Usage of \Magento\Catalog\Block\Product\ListProduct::getProductPrice in app/code/Magento/Catalog/view/frontend/templates/product/list.phtml or product boxes in widgets affects listing performance. It calculates price for products again even if the values received from collection. On the screenshot you can see that product items have price values. Selection_047

Then when a product is rendered, magento starts to resolve the price Selection_048

It does these steps:

  • Looks for price renderer
  • loads linked products for composite products
  • Resolve price type (it already available from collection)

Because the prices already available from the collection it’s enough to render formatted price value (amount and currency) [e.g. 10.00 $]. But magento loads prices again does comparations and then renders it. Even when sort by price used.

Steps to reproduce (*)

  1. Render price box from the product collection on listing or search pages
  2. Use simple or composite products
  3. See that price boxes consumes a lot of time for price rendering by calling \Magento\Catalog\Block\Product\ListProduct::getProductPrice in the loop

Expected result (*)

  1. Prices are rendered faster
  2. Redundant loads and price comparations in ListProduct::getProductPrice are eliminated
  3. ListProduct::getProductPrice just formats given price float values. It does not resolve prices again
  4. Moreover it does not load linked/child products

Actual result (*)

  1. Prices are rendered slowly
  2. ListProduct::getProductPrice loads extra price data and performs comparations
  3. ListProduct::getProductPrice does not use data already available from collection, loads prices again
  4. ListProduct::getProductPrice loads child/linked products and performs redundant price resolve.

About this issue

  • Original URL
  • State: open
  • Created 4 years ago
  • Reactions: 13
  • Comments: 19 (9 by maintainers)

Commits related to this issue

Most upvoted comments

This one still valid today. Hope someone can take a look at it

I had also performance issue for configurable product which have almost 2000 simple products (Magento CE 2.4.4). For me the most slow was function \Magento\InventoryConfigurableProduct\Plugin\Model\Product\Type\Configurable\IsSalableOptionPlugin::filterProducts, so I just overridden it with follow code:

--- vendor/magento/module-inventory-configurable-product/Plugin/Model/Product/Type/Configurable/IsSalableOptionPlugin.php   
+++ vendor/magento/module-inventory-configurable-product/Plugin/Model/Product/Type/Configurable/IsSalableOptionPlugin.php
@@ -106,15 +106,24 @@
      * @param array $isSalableResults
      * @return void
      */
-    private function filterProducts(array $products, array $isSalableResults) : void
+    private function filterProducts(array &$products, array $isSalableResults) : void
     {
+        $isSalableResultsTest = [];
+        foreach ($isSalableResults as $result) {
+            if (!$result->isSalable()) {
+                $isSalableResultsTest[$result->getSku()] = $result->isSalable();
+            }
+        }
+
+        if (empty($isSalableResultsTest)) {
+            return;
+        }
+
         foreach ($products as $key => $product) {
-            foreach ($isSalableResults as $result) {
-                if ($result->getSku() === $product->getSku() && !$result->isSalable()) {
-                    $product->setIsSalable(0);
-                    if (!$this->stockConfiguration->isShowOutOfStock()) {
-                        unset($products[$key]);
-                    }
+            if (array_key_exists($product->getSku(), $isSalableResultsTest)) {
+                $product->setIsSalable(0);
+                if (!$this->stockConfiguration->isShowOutOfStock()) {
+                    unset($products[$key]);
                 }
             }
         }

still valid on 2.4.5. I think this issue should be upgraded to P1 priority.