Skip to content

Commit

Permalink
Merge pull request #3912 from magento-helix/MC-6273
Browse files Browse the repository at this point in the history
[Performance] Mysql url_rewrite select make on product view page 170+ times per request
Bug:
- MC-6273 Mysql url_rewrite select make on product view page 170+ times per request
- MAGETWO-98592 [Elastic] Fix catalog search with elasticsearch6
  • Loading branch information
duhon authored Mar 22, 2019
2 parents 8f45cf8 + b5e4c92 commit 06269b7
Show file tree
Hide file tree
Showing 10 changed files with 347 additions and 185 deletions.
129 changes: 50 additions & 79 deletions app/code/Magento/Config/App/Config/Type/System.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/

namespace Magento\Config\App\Config\Type;

use Magento\Framework\App\Config\ConfigSourceInterface;
Expand All @@ -13,18 +14,20 @@
use Magento\Config\App\Config\Type\System\Reader;
use Magento\Framework\App\ScopeInterface;
use Magento\Framework\Cache\FrontendInterface;
use Magento\Framework\Cache\LockGuardedCacheLoader;
use Magento\Framework\Lock\LockManagerInterface;
use Magento\Framework\Serialize\SerializerInterface;
use Magento\Store\Model\Config\Processor\Fallback;
use Magento\Store\Model\ScopeInterface as StoreScope;
use Magento\Framework\Encryption\Encryptor;
use Magento\Store\Model\ScopeInterface as StoreScope;

/**
* System configuration type
*
* @api
* @since 100.1.2
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
* @SuppressWarnings(PHPMD.UnusedPrivateMethod)
*/
class System implements ConfigTypeInterface
{
Expand All @@ -42,22 +45,6 @@ class System implements ConfigTypeInterface
* @var string
*/
private static $lockName = 'SYSTEM_CONFIG';
/**
* Timeout between retrieves to load the configuration from the cache.
*
* Value of the variable in microseconds.
*
* @var int
*/
private static $delayTimeout = 100000;
/**
* Lifetime of the lock for write in cache.
*
* Value of the variable in seconds.
*
* @var int
*/
private static $lockTimeout = 42;

/**
* @var array
Expand Down Expand Up @@ -106,9 +93,9 @@ class System implements ConfigTypeInterface
private $encryptor;

/**
* @var LockManagerInterface
* @var LockGuardedCacheLoader
*/
private $locker;
private $lockQuery;

/**
* @param ConfigSourceInterface $source
Expand All @@ -122,6 +109,7 @@ class System implements ConfigTypeInterface
* @param Reader|null $reader
* @param Encryptor|null $encryptor
* @param LockManagerInterface|null $locker
* @param LockGuardedCacheLoader|null $lockQuery
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
* @SuppressWarnings(PHPMD.ExcessiveParameterList)
*/
Expand All @@ -136,7 +124,8 @@ public function __construct(
$configType = self::CONFIG_TYPE,
Reader $reader = null,
Encryptor $encryptor = null,
LockManagerInterface $locker = null
LockManagerInterface $locker = null,
LockGuardedCacheLoader $lockQuery = null
) {
$this->postProcessor = $postProcessor;
$this->cache = $cache;
Expand All @@ -145,8 +134,8 @@ public function __construct(
$this->reader = $reader ?: ObjectManager::getInstance()->get(Reader::class);
$this->encryptor = $encryptor
?: ObjectManager::getInstance()->get(Encryptor::class);
$this->locker = $locker
?: ObjectManager::getInstance()->get(LockManagerInterface::class);
$this->lockQuery = $lockQuery
?: ObjectManager::getInstance()->get(LockGuardedCacheLoader::class);
}

/**
Expand Down Expand Up @@ -225,91 +214,64 @@ private function getWithParts($path)
}

/**
* Make lock on data load.
*
* @param callable $dataLoader
* @param bool $flush
* @return array
*/
private function lockedLoadData(callable $dataLoader, bool $flush = false): array
{
$cachedData = $dataLoader(); //optimistic read

while ($cachedData === false && $this->locker->isLocked(self::$lockName)) {
usleep(self::$delayTimeout);
$cachedData = $dataLoader();
}

while ($cachedData === false) {
try {
if ($this->locker->lock(self::$lockName, self::$lockTimeout)) {
if (!$flush) {
$data = $this->readData();
$this->cacheData($data);
$cachedData = $data;
} else {
$this->cache->clean(\Zend_Cache::CLEANING_MODE_MATCHING_TAG, [self::CACHE_TAG]);
$cachedData = [];
}
}
} finally {
$this->locker->unlock(self::$lockName);
}

if ($cachedData === false) {
usleep(self::$delayTimeout);
$cachedData = $dataLoader();
}
}

return $cachedData;
}

/**
* Load configuration data for all scopes
* Load configuration data for all scopes.
*
* @return array
*/
private function loadAllData()
{
return $this->lockedLoadData(function () {
$loadAction = function () {
$cachedData = $this->cache->load($this->configType);
$data = false;
if ($cachedData !== false) {
$data = $this->serializer->unserialize($this->encryptor->decrypt($cachedData));
}
return $data;
});
};

return $this->lockQuery->lockedLoadData(
self::$lockName,
$loadAction,
\Closure::fromCallable([$this, 'readData']),
\Closure::fromCallable([$this, 'cacheData'])
);
}

/**
* Load configuration data for default scope
* Load configuration data for default scope.
*
* @param string $scopeType
* @return array
*/
private function loadDefaultScopeData($scopeType)
{
return $this->lockedLoadData(function () use ($scopeType) {
$loadAction = function () use ($scopeType) {
$cachedData = $this->cache->load($this->configType . '_' . $scopeType);
$scopeData = false;
if ($cachedData !== false) {
$scopeData = [$scopeType => $this->serializer->unserialize($this->encryptor->decrypt($cachedData))];
}
return $scopeData;
});
};

return $this->lockQuery->lockedLoadData(
self::$lockName,
$loadAction,
\Closure::fromCallable([$this, 'readData']),
\Closure::fromCallable([$this, 'cacheData'])
);
}

/**
* Load configuration data for a specified scope
* Load configuration data for a specified scope.
*
* @param string $scopeType
* @param string $scopeId
* @return array
*/
private function loadScopeData($scopeType, $scopeId)
{
return $this->lockedLoadData(function () use ($scopeType, $scopeId) {
$loadAction = function () use ($scopeType, $scopeId) {
$cachedData = $this->cache->load($this->configType . '_' . $scopeType . '_' . $scopeId);
$scopeData = false;
if ($cachedData === false) {
Expand All @@ -329,7 +291,14 @@ private function loadScopeData($scopeType, $scopeId)
}

return $scopeData;
});
};

return $this->lockQuery->lockedLoadData(
self::$lockName,
$loadAction,
\Closure::fromCallable([$this, 'readData']),
\Closure::fromCallable([$this, 'cacheData'])
);
}

/**
Expand Down Expand Up @@ -371,7 +340,7 @@ private function cacheData(array $data)
}

/**
* Walk nested hash map by keys from $pathParts
* Walk nested hash map by keys from $pathParts.
*
* @param array $data to walk in
* @param array $pathParts keys path
Expand Down Expand Up @@ -408,7 +377,7 @@ private function readData(): array
}

/**
* Clean cache and global variables cache
* Clean cache and global variables cache.
*
* Next items cleared:
* - Internal property intended to store already loaded configuration data
Expand All @@ -420,11 +389,13 @@ private function readData(): array
public function clean()
{
$this->data = [];
$this->lockedLoadData(
function () {
return false;
},
true
$cleanAction = function () {
$this->cache->clean(\Zend_Cache::CLEANING_MODE_MATCHING_TAG, [self::CACHE_TAG]);
};

$this->lockQuery->lockedCleanData(
self::$lockName,
$cleanAction
);
}
}
11 changes: 10 additions & 1 deletion app/code/Magento/Config/etc/di.xml
Original file line number Diff line number Diff line change
Expand Up @@ -90,9 +90,18 @@
<argument name="preProcessor" xsi:type="object">Magento\Framework\App\Config\PreProcessorComposite</argument>
<argument name="serializer" xsi:type="object">Magento\Framework\Serialize\Serializer\Serialize</argument>
<argument name="reader" xsi:type="object">Magento\Config\App\Config\Type\System\Reader\Proxy</argument>
<argument name="locker" xsi:type="object">Magento\Framework\Lock\Backend\Cache</argument>
<argument name="lockQuery" xsi:type="object">systemConfigQueryLocker</argument>
</arguments>
</type>

<virtualType name="systemConfigQueryLocker" type="Magento\Framework\Cache\LockGuardedCacheLoader">
<arguments>
<argument name="locker" xsi:type="object">Magento\Framework\Lock\Backend\Cache</argument>
<argument name="lockTimeout" xsi:type="number">42000</argument>
<argument name="delayTimeout" xsi:type="number">100</argument>
</arguments>
</virtualType>

<type name="Magento\Config\App\Config\Type\System\Reader">
<arguments>
<argument name="source" xsi:type="object">systemConfigSourceAggregated</argument>
Expand Down
32 changes: 32 additions & 0 deletions app/code/Magento/Elasticsearch6/etc/di.xml
Original file line number Diff line number Diff line change
Expand Up @@ -170,4 +170,36 @@
</argument>
</arguments>
</type>

<virtualType name="elasticsearchLayerCategoryItemCollectionProvider" type="Magento\Elasticsearch\Model\Layer\Category\ItemCollectionProvider">
<arguments>
<argument name="factories" xsi:type="array">
<item name="elasticsearch6" xsi:type="object">elasticsearchCategoryCollectionFactory</item>
</argument>
</arguments>
</virtualType>

<type name="Magento\CatalogSearch\Model\Search\ItemCollectionProvider">
<arguments>
<argument name="factories" xsi:type="array">
<item name="elasticsearch6" xsi:type="object">elasticsearchAdvancedCollectionFactory</item>
</argument>
</arguments>
</type>

<type name="Magento\CatalogSearch\Model\Advanced\ProductCollectionPrepareStrategyProvider">
<arguments>
<argument name="strategies" xsi:type="array">
<item name="elasticsearch6" xsi:type="object">Magento\Elasticsearch\Model\Advanced\ProductCollectionPrepareStrategy</item>
</argument>
</arguments>
</type>

<virtualType name="elasticsearchLayerSearchItemCollectionProvider" type="Magento\Elasticsearch\Model\Layer\Search\ItemCollectionProvider">
<arguments>
<argument name="factories" xsi:type="array">
<item name="elasticsearch6" xsi:type="object">elasticsearchFulltextSearchCollectionFactory</item>
</argument>
</arguments>
</virtualType>
</config>
7 changes: 7 additions & 0 deletions app/etc/di.xml
Original file line number Diff line number Diff line change
Expand Up @@ -1757,4 +1757,11 @@
</argument>
</arguments>
</type>
<type name="Magento\Framework\Cache\LockGuardedCacheLoader">
<arguments>
<argument name="locker" xsi:type="object">Magento\Framework\Lock\Backend\Cache</argument>
<argument name="lockTimeout" xsi:type="number">10000</argument>
<argument name="delayTimeout" xsi:type="number">20</argument>
</arguments>
</type>
</config>
Original file line number Diff line number Diff line change
Expand Up @@ -213,3 +213,4 @@ Magento/CatalogSearch/Model/ResourceModel/Fulltext
Magento/Elasticsearch/Model/Layer/Search
Magento/Elasticsearch/Model/Adapter/FieldMapper/Product/FieldProvider/FieldName/Resolver
Magento/Elasticsearch6/Model/Client
Magento/Config/App/Config/Type
Loading

0 comments on commit 06269b7

Please sign in to comment.