Skip to content

Commit

Permalink
[9.x] Attribute Cast Performance Improvements (laravel#43554)
Browse files Browse the repository at this point in the history
* Remove repeated calls to getCasts() in same method

* Switch strncmp to starts_with_str

Marginally faster, better readability, and matches similar functions

* Add castTypeCache

getCastType is called a lot when processing models with defined casts and contributes to a significant number of overall calls.  Caching the results of the key conversion can result in significant performance improvement when processing large numbers of models.
  • Loading branch information
serpentblade authored and chu121su12 committed Aug 7, 2022
1 parent d29a524 commit 9f2005b
Showing 1 changed file with 29 additions and 14 deletions.
43 changes: 29 additions & 14 deletions src/Illuminate/Database/Eloquent/Concerns/HasAttributes.php
Expand Up @@ -156,6 +156,13 @@ trait HasAttributes
*/
protected static $setAttributeMutatorCache = [];

/**
* The cache of the converted cast types.
*
* @var array
*/
protected static $castTypeCache = [];

/**
* The encrypter instance that is used to encrypt attributes.
*
Expand Down Expand Up @@ -822,19 +829,23 @@ protected function getEnumCastableAttributeValue($key, $value)
*/
protected function getCastType($key)
{
if ($this->isCustomDateTimeCast($this->getCasts()[$key])) {
return 'custom_datetime';
}
$castType = $this->getCasts()[$key];

if ($this->isImmutableCustomDateTimeCast($this->getCasts()[$key])) {
return 'immutable_custom_datetime';
if (isset(static::$castTypeCache[$castType])) {
return static::$castTypeCache[$castType];
}

if ($this->isDecimalCast($this->getCasts()[$key])) {
return 'decimal';
if ($this->isCustomDateTimeCast($castType)) {
$convertedCastType = 'custom_datetime';
} elseif ($this->isImmutableCustomDateTimeCast($castType)) {
$convertedCastType = 'immutable_custom_datetime';
} elseif ($this->isDecimalCast($castType)) {
$convertedCastType = 'decimal';
} else {
$convertedCastType = trim(strtolower($castType));
}

return trim(strtolower($this->getCasts()[$key]));
return static::$castTypeCache[$castType] = $convertedCastType;
}

/**
Expand Down Expand Up @@ -886,8 +897,8 @@ protected function isCustomDateTimeCast($cast)
*/
protected function isImmutableCustomDateTimeCast($cast)
{
return strncmp($cast, 'immutable_date:', 15) === 0 ||
strncmp($cast, 'immutable_datetime:', 19) === 0;
return str_starts_with($cast, 'immutable_date:') ||
str_starts_with($cast, 'immutable_datetime:');
}

/**
Expand Down Expand Up @@ -1514,11 +1525,13 @@ protected function isEncryptedCastable($key)
*/
protected function isClassCastable($key)
{
if (! array_key_exists($key, $this->getCasts())) {
$casts = $this->getCasts();

if (! array_key_exists($key, $casts)) {
return false;
}

$castType = $this->parseCasterClass($this->getCasts()[$key]);
$castType = $this->parseCasterClass($casts[$key]);

if (in_array($castType, static::$primitiveCastTypes)) {
return false;
Expand All @@ -1539,11 +1552,13 @@ protected function isClassCastable($key)
*/
protected function isEnumCastable($key)
{
if (! array_key_exists($key, $this->getCasts())) {
$casts = $this->getCasts();

if (! array_key_exists($key, $casts)) {
return false;
}

$castType = $this->getCasts()[$key];
$castType = $casts[$key];

if (in_array($castType, static::$primitiveCastTypes)) {
return false;
Expand Down

0 comments on commit 9f2005b

Please sign in to comment.