OOM and timeout when using cart promotions

Viewed 57

When having a shop with large quantity items, using promotions becomes impossible due to the way that promotions are calculated. For example when having a global 5% cart discount, for every qty, a seperate line item is loaded into memory. This is called 6 times which makes it not only memory-hungry, but also slow when having a lot of qty's.

This makes the cart crash as soon as you have more than a few hundred items in your cart.

The screenshot attached is a Blackfire screenshot from a cart with 1 lineitem and 1 promotion (active on the whole cart, so no line item splitting needed I would think?) with a qty of 1000.

Environment: PRD

Steps to reproduce:

Create promotion Put max cart limit high Change quantity to large number Expected result:

Quantity change works and cart is loaded correctly Actual result:

Quantity does not get changed because the site goes out of memory. Site returns a 500 error.

Screenshot Blackfire

1 Answers

That is a neat catch. I have to admit I'm not super familiar with the promotion calculation procedure but what caught my eye was that trail of cloned objects, which I doubt are necessary for the price calculation (MediaEntity, MediaThumbnailCollection) and yet accumulate memory consumption. Obviously the objects are cloned to avoid mutation but I couldn't tell to what degree this actually is necessary.

I had a quick go at the LineItemQuantitySplitter trying to instantiate a new LineItem and re-assigning properties from the original instance.

public function split(LineItem $item, int $quantity, SalesChannelContext $context): LineItem
{
    /** @var LineItem $tmpItem */
    $tmpItem = LineItem::createFrom($item);

    if ($item->getQuantity() === $quantity) {
        // return clone $item;
        return $tmpItem;
    }

    // $tmpItem = clone $item;

    // ...
}

Now I'm not sure about any unwanted side effects this change might bring and there very well could be some. But a quick test seemed to yield the same results with some performance improvements.

Before:
before

After:
enter image description here

I'll pass along your findings and I'm optimistic we can find a way to improve things regarding this issue.

Related