diff --git a/vendor/magento/module-catalog-import-export/Model/Export/Product.php b/vendor/magento/module-catalog-import-export/Model/Export/Product.php index 4d3dceeb3eb62..6bc167b1c6d53 100644 --- a/vendor/magento/module-catalog-import-export/Model/Export/Product.php +++ b/vendor/magento/module-catalog-import-export/Model/Export/Product.php @@ -1,7 +1,7 @@ _itemsPerPage === null) { + if ($this->_itemsPerPage === null || + $this->currentMemoryUsage < memory_get_usage(true) || + $this->currentMaxAllowedMemoryUsage < memory_get_usage(true) + ) { $memoryLimitConfigValue = trim(ini_get('memory_limit')); $lastMemoryLimitLetter = strtolower($memoryLimitConfigValue[strlen($memoryLimitConfigValue) - 1]); $memoryLimit = (int) $memoryLimitConfigValue; @@ -883,9 +896,19 @@ protected function getItemsPerPage() // Maximal Products limit $maxProductsLimit = 5000; + $this->currentMaxAllowedMemoryUsage = (int)($memoryLimit * $memoryUsagePercent); + $this->currentMemoryUsage = memory_get_usage(true); + $this->_itemsPerPage = (int)( - ($memoryLimit * $memoryUsagePercent - memory_get_usage(true)) / $memoryPerProduct + ($this->currentMaxAllowedMemoryUsage - $this->currentMemoryUsage) / $memoryPerProduct ); + + $this->_itemsPerPage = $this->adjustItemsPerPageByAttributeOptions( + $this->_itemsPerPage, + $this->currentMaxAllowedMemoryUsage, + $this->currentMemoryUsage + ); + if ($this->_itemsPerPage < $minProductsLimit) { $this->_itemsPerPage = $minProductsLimit; } @@ -896,6 +919,61 @@ protected function getItemsPerPage() return $this->_itemsPerPage; } + /** + * Adjust items per page by attribute options + * + * @param int $initialItemsPerPage + * @param int $memoryLimit + * @param int $currentMemoryUsage + * @return int + */ + private function adjustItemsPerPageByAttributeOptions( + int $initialItemsPerPage, + int $memoryLimit, + int $currentMemoryUsage + ): int { + $maxAttributeOptions = $this->getMaxAttributeValues(); + $minProductsLimit = 500; + $maxProductsLimit = 5000; + $memoryPerProduct = 500000; + + if ($maxAttributeOptions > 5000) { + $adjustedItemsPerPage = max(1000, (int)($initialItemsPerPage * 0.25)); + } elseif ($maxAttributeOptions > 2500) { + $adjustedItemsPerPage = max(2500, (int)($initialItemsPerPage * 0.5)); + } elseif ($maxAttributeOptions > 1000) { + $adjustedItemsPerPage = max(3500, (int)($initialItemsPerPage * 0.75)); + } else { + $adjustedItemsPerPage = $initialItemsPerPage; + } + + $availableMemory = $memoryLimit - $currentMemoryUsage; + $maxItemsByMemory = (int)($availableMemory / $memoryPerProduct); + + $adjustedItemsPerPage = min($adjustedItemsPerPage, $maxItemsByMemory); + $adjustedItemsPerPage = max($minProductsLimit, $adjustedItemsPerPage); + $adjustedItemsPerPage = min($maxProductsLimit, $adjustedItemsPerPage); + + return $adjustedItemsPerPage; + } + + /** + * Get max attribute values + * + * @return int + */ + + private function getMaxAttributeValues(): int + { + $maxCount = 0; + + foreach ($this->_attributeValues as $attributeValues) { + $maxCount = max($maxCount, count($attributeValues)); + } + + return $maxCount; + } + /** * Set page and page size to collection *