magento-lts icon indicating copy to clipboard operation
magento-lts copied to clipboard

Obsolete code in block for configurable products

Open theroch opened this issue 2 years ago • 11 comments

We have inherited a development that implements a booking function via a calendar with time selection. This is realized via configurable products. Depending on the available time slots, there can be as many as 800 options. We know that this is not the best solution to this problem. But that should not be the topic here.

Preconditions (*)

  1. 8xCPUs Intel Xeon 1,8 GHz, 16GB RAM, SATA-SSD
  2. OpenMage 19.4.16 and earlier and also 20.0.14 and earlier

Steps to reproduce (*)

  1. Create attribute for configurable product with at least 200 options
  2. Create configurable product for this attribute
  3. Add subproducts to this attribute option
  4. View the product in frontend

Expected result (*)

  1. The request to view this product should be completed in under 1s

Actual result (*)

  1. The request to view this product takes a long time. Per 100 options, the request will take 1s more to complete
  2. With 800 options the request will take about 8s to complete.

Cause of the problem

The Problem is located in app/code/core/Mage/Catalog/Block/Product/View/Type/Configurable.php starting at line 227:

/**
 * Prepare formated values for options choose
 */
foreach ($optionPrices as $optionPrice) {
    foreach ($optionPrices as $additional) {
        $this->_preparePrice(abs($additional-$optionPrice));
    }
}

Because _preparePrice and all sub calls to all other methods operate with return values and not with objects or session data, the result of this method is never considered. We think the loops and the call to to _preparePrice starting at line 227 is not needed for correct functionality. This function is a performance brake and only burns time. Can this part of code safely be removed?

Can someone please verify our assessment?

theroch avatar Jun 22 '22 13:06 theroch

From the first glance it does seem useless as it doesn't cause any side-effects, just returning stuff.

Have you tried removing that code and reloading the page? What was the loading time?

elidrissidev avatar Jun 22 '22 14:06 elidrissidev

If I see correctly Its not an no-brainer. The code has several side effects. $this->_preparePrice calls internally Mage_Catalog_Helper_Product_Type_Composite::preparePrice which calls $product->getFinalPrice() and Mage_Catalog_Helper_Product_Type_Composite::registerJsPrice

and getFinalPrice sets 'final_price' field on product which is calculated in Mage_Catalog_Model_Product_Type_Price::getFinalPrice (which also triggers a catalog_product_get_final_price event)

So more digging/profiling is needed to optimize the code without breaking.

tmotyl avatar Jun 22 '22 16:06 tmotyl

$isPercent is set to false by default so the code inside the block is never executed. https://github.com/OpenMage/magento-lts/blob/412bee01b9cc77f50b4333b098e25d116bf9e820/app/code/core/Mage/Catalog/Helper/Product/Type/Composite.php#L45-L52

elidrissidev avatar Jun 22 '22 16:06 elidrissidev

$isPercent is set to false by default so the code inside the block is never executed.

What about custom code that sets $isPercent to true?

sreichel avatar Jun 23 '22 01:06 sreichel

What about custom code that sets $isPercent to true?

This makes no sense. The code https://github.com/OpenMage/magento-lts/blob/412bee01b9cc77f50b4333b098e25d116bf9e820/app/code/core/Mage/Catalog/Block/Product/View/Type/Configurable.php#L231-L235 depends on https://github.com/OpenMage/magento-lts/blob/412bee01b9cc77f50b4333b098e25d116bf9e820/app/code/core/Mage/Catalog/Block/Product/View/Type/Configurable.php#L196-L198 So is percent is considered in lines 196-198 and the result will never be in percent.

theroch avatar Jun 23 '22 07:06 theroch

Overwrites the current call of the loop https://github.com/OpenMage/magento-lts/blob/412bee01b9cc77f50b4333b098e25d116bf9e820/app/code/core/Mage/Catalog/Block/Product/View/Type/Configurable.php#L231-L235 not all preceding ones? Thus it would be sufficient to call _preparePrice only once? However, this would also be pointless, since then only

$this->_preparePrice(0);

would remain?

theroch avatar Jun 23 '22 07:06 theroch

What about custom code that sets $isPercent to true?

I was only talking about the execution path mentioned in OP, I don't know about the usage in other places.

elidrissidev avatar Jun 23 '22 08:06 elidrissidev

Have you tried removing that code and reloading the page? What was the loading time?

We commented out that code block and the request completed in under a second. We have not noticed any side effects but we only tested our special test case and no other ones.

theroch avatar Jun 23 '22 08:06 theroch

@theroch Hey, are you still using your workaround in production? Any issues noticed?

elidrissidev avatar Sep 25 '22 16:09 elidrissidev

@theroch Hey, are you still using your workaround in production? Any issues noticed?

We still use this code without any issues.

theroch avatar Oct 11 '22 14:10 theroch

@theroch Thank you! Feel free to open a PR to be reviewed if you wish, otherwise I'll do it later.

elidrissidev avatar Oct 11 '22 14:10 elidrissidev