[9.x] Attribute Cast Performance Improvements - #43554
Merged
taylorotwell merged 3 commits intoAug 5, 2022
Merged
Conversation
Marginally faster, better readability, and matches similar functions
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.
serpentblade
force-pushed
the
feature/eloquent-attributes-performance
branch
from
August 4, 2022 18:57
89bb0f7 to
424e8cf
Compare
Member
|
Thanks! |
chu121su12
pushed a commit
to chu121su12/framework
that referenced
this pull request
Aug 7, 2022
* 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.
Ken-vdE
pushed a commit
to Ken-vdE/framework
that referenced
this pull request
Aug 9, 2022
* 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.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Performance improvements to casts-related functions:
getCasts()in methodsstrncmpwithstr_starts_within cast type checkgetCastType()to eliminate repeated string comparisons for cast types.Background:
I process millions of rows via scout and was curious if there were any obvious bottlenecks in the process to help speed things along. I discovered through profiling that casts-related code represented a significant number of overall calls and time spent processing my models.
In particular calls to
getCasts()were unusually high as well and the time spent ingetCastType()was higher than any other function.First step was to update any methods where
getCasts()was called multiple times.getCastType()seemed to be the primary culprit for the high number of calls togetCasts().When profiling again this helped reduce the calls to
getCasts()but the time spent ingetCastType()was still rather high. I foundisImmutableCustomDateTimeCast()still was usingstrncmpcomparisons whenstr_starts_withwould do instead. This change is not only an improvement to readability while matching the code of the other similar functions, but there's also a small improvement in performance with the change as an added bonus.I then noticed that
getCastType()can be cached as the results of checking the cast types are deterministic and do not need to be repeated for the same input.Results:
With these changes I saw a 5-25% reduction in processing time depending on the complexity, number of casts, and number of attributes of a particular model. From my tests I have noticed significant improvements on both eloquent load times and serialization.
Potential risks:
This introduces a new static member variable
$castTypeCachetoModelthat could cause conflicts if a subclass already defines one by that name. An alternative for this that is to introduce$castTypeCacheas a static variable to thegetCastType()method only, which is often considered bad form but does not introduce any risk of naming collision and results in the same benefit.End user benefits:
General users will likely see negligible benefits as the changes are only really beneficial when processing a lot of models. At scale, any bulk loading and serializing of models will yield note-worthy performance improvements.
Other things to note about casts:
There are further significant performance improvements in caching
hasCast(), however that is a bit more complex as there's no easy to trust that$castsor the results ofgetCasts()does not change during the lifecycle of a model. If a future version of Laravel introduced immutability to$castsand an expectation of determinism forgetCasts()the expensive and repeated calls tohasCast()could be cached and save a significant amount of time.