Problem/Motivation
ContentEntityBase::hasTranslationChanges is being called in core two times during the saving process.
1. ChangedItem::preSave
2. ContentEntityStorageBase::populateAffectedRevisionTranslations
In each of this cases the method will be called for each translation and having a lot of entity translations with complex fields one might want to somehow cache the output of the first execution of the method in order to serve the result on subsequent calls from this cache instead of having the complex logic running over and over again.
Additionally the core uses the method two times during the saving process but one might have hook_entity_update and running the method there as well in order to do stuff based on the output of the method, so caching the output of the method will be really useful and will have a real performance boost.
Proposed resolution
1. In ContentEntityBase::preSave flag the entity as being in a state of saving. - Should we set the flag at this point or it would be better to do in the storage after the field preSave method has been executed as after it the field values might have changed.. but actually the only place where the method might be correctly used is in the hook_entity_update which is running after field preSave which makes it unnecessary setting the flag from the storage.
2. In ContentEntityBase::hasTranslationChanges check if the flag from ::preSave is set and if so cache the output, otherwise if it is already cached serve it from the cache.
3. In ContentEntityBase::postSave reset the ::preSave flag and the cache of the ::hasTranslationChanges method.
With this change our system gained a real performance boost as we use the method also in hook_entity_update and during save we call it a lot of times on a lot of entities.
Numbers: 14 % less memory usage and 65 % faster saving.
Remaining tasks
Review & Commit.
User interface changes
None.
API changes
None.
Data model changes
None.