Skip to content

Commit b6fbaeb

Browse files
authored
Improve performance of DataObject magic calls and addData()
The magic calls from the DataObject are being called over a 100k when there is no block_cache available and depending on the page often thousands of times when all block_cache is available. The small change for addData() is just included because its a tiny optimization and prevents a bug from happening. When a $value is an array the original call to setData would override the internal $_data array, this is not expected behavior and just setting it directly to $_data is faster anyway. The other change is in the __call magic method and the _underscore function and the change is quite radical. Since this method can be called so often, we want to prevent further function calls if possible. Functional calls are normally not that expensive, but will become more expensive if you use this extensively (thousands of even hundred of thousands extra calls): These are my own benchmarks based on a local environment with opcache and with PROD mode. HOMEPAGE transaction All cache enabled except for FPC (__call is called 975 times): 4.318307ms -> 1.469747ms All cache enabled except for FPC + Block_html (__call is called 100379 times): 385.36412ms -> 88.412914ms PLP transaction: All cache enabled except for FPC (__call is called 4628 times): 19.625463ms -> 5.754514ms All cache enabled except for FPC + Block_html (__call is called 112591 times): 404.84066ms -> 99.390374ms Now this PR also skips some checks. It assumes if a $method call start with 'g' it will be for 'get' for example, this is done in my PR to get the most optimal performance result but might not be preferred. I also removed an index check with $args[1] for the setter since it isn't used anywhere, but might also be something we would want to change.
1 parent 6057eb8 commit b6fbaeb

File tree

1 file changed

+31
-17
lines changed

1 file changed

+31
-17
lines changed

lib/internal/Magento/Framework/DataObject.php

Lines changed: 31 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ public function addData(array $arr)
5757
}
5858

5959
foreach ($arr as $index => $value) {
60-
$this->setData($index, $value);
60+
$this->_data[$key] = $value;
6161
}
6262
return $this;
6363
}
@@ -387,22 +387,26 @@ public function toString($format = '')
387387
*/
388388
public function __call($method, $args)
389389
{
390-
switch (substr((string)$method, 0, 3)) {
391-
case 'get':
392-
$key = $this->_underscore(substr($method, 3));
393-
$index = isset($args[0]) ? $args[0] : null;
394-
return $this->getData($key, $index);
395-
case 'set':
396-
$key = $this->_underscore(substr($method, 3));
397-
$value = isset($args[0]) ? $args[0] : null;
398-
return $this->setData($key, $value);
399-
case 'uns':
400-
$key = $this->_underscore(substr($method, 3));
401-
return $this->unsetData($key);
402-
case 'has':
403-
$key = $this->_underscore(substr($method, 3));
404-
return isset($this->_data[$key]);
390+
switch($method[0]) {
391+
case 'g':
392+
return $this->_data[
393+
self::$_underscoreCache[$method] ?? $this->_underscore($method)
394+
] ?? null;
395+
case 's':
396+
$this->_data[
397+
self::$_underscoreCache[$method] ?? $this->_underscore($method)
398+
] = $args[0] ?? null;
399+
return $this;
400+
case 'u':
401+
return $this->unsetData(self::$_underscoreCache[$method] ?? $this->_underscore($method));
402+
case 'h':
403+
return isset(
404+
$this->_data[
405+
self::$_underscoreCache[$method] ?? $this->_underscore($method)
406+
]
407+
);
405408
}
409+
406410
throw new \Magento\Framework\Exception\LocalizedException(
407411
new \Magento\Framework\Phrase('Invalid method %1::%2', [get_class($this), $method])
408412
);
@@ -435,7 +439,17 @@ protected function _underscore($name)
435439
if (isset(self::$_underscoreCache[$name])) {
436440
return self::$_underscoreCache[$name];
437441
}
438-
$result = strtolower(trim(preg_replace('/([A-Z]|[0-9]+)/', "_$1", $name), '_'));
442+
443+
$result = strtolower(
444+
trim(
445+
preg_replace(
446+
'/([A-Z]|[0-9])/', "_$1",
447+
lcfirst(substr($name, 3))
448+
),
449+
'_'
450+
)
451+
);
452+
439453
self::$_underscoreCache[$name] = $result;
440454
return $result;
441455
}

0 commit comments

Comments
 (0)