Problem/Motivation

On a current project this module shows in NewRelic as the most time-consumig.
It's related to the fallback behaviors, apparently abusing the entity cache system and other internals (on initial high level review).

More information will be provided once I have it.

More context on the issue:
We have many languages (6-8) and somewhat long fallback chains on some of them (4-5).
I suspect that due to the chain things are loaded one by one and thus causing delays. Maybe we could change that to load translations
multiple (maybe).
On a cron there are some node loading and translations loading related to Search API indexing and 3rd party data synchronizations.
It is clearly seen that the slow-downs are during the heavy processes doing multitude of entity load operations, and the biggest overhead in that calls comes from the cache gets (as a % portion of the requests).

We need to find what exactly is causing it.

Any ideas on your side will be REALLY apreciated :).

Proposed resolution

Benchmark, profile and see where the cache abuse is coming from.
Mitigate the issue by either a new cache layer or code change (details are TBD).

Remaining tasks

Find the root cause, discussion, patch.

User interface changes

None expected.

API changes

TBD.

Data model changes

TBD.

Release notes snippet

TBD.

Comments

ndobromirov created an issue. See original summary.

ndobromirov’s picture

Issue summary: View changes
ndobromirov’s picture

Issue tags: +DevDaysTransylvania

Biggest overhead I've found (from NewRelic) is the hook_language_fallback_candidates_alter.
The only module that implements it is this one, so I've checked more what it is doing...

There are some issues that I was able to find.
This alter hook is triggered and it is generating the list every time when an entity needs to be translated. The thing is the set of fallbacks are generated from configuration every time (per entity).

In reality all of that is changing per entity bundle (not entity instance). In reality all of that can be cached, so in heavy translation scenarios we get, this list can be preserved in the long run. Maybe a persistent second level cache could help as well.


I think I've found the issue in my scenario - we have around 100 000 iterations related to translations of and to have heavy processing over them and prevent out of memory errors the static cache for the bundle is disabled during that list processing.

I suspect this code path is somewhat protected from entity static cache, but once that is disabled, the overhead is exposed (after some 100k iterations)..


I have a PoC patch that will be posted in near future for review and further discussions.

ndobromirov’s picture

Status: Active » Needs review
StatusFileSize
new6 KB

Here is the promised patch...

There is a new utility method on the controller that moves the alter code there.
There is a in-property cache for the values that will cache all of the things there per bundle, so we skip executions per entity.
Change in the interface, as there is a new method added.

ndobromirov’s picture

I will try to have benchmarks available at near future as well, so we can see the performance difference this will make in 10k+ iterations.

ndobromirov’s picture

I've managed to force the hook to be executed on a node with this snippet.

$nodeStorage = \Drupal::entityTypeManager()->getStorage('node');
$entityType = $nodeStorage->getEntityType();
$entityType->set('static_cache', FALSE);

/* @var $node \Drupal\node\Entity\Node */
$node = $nodeStorage->load(MY_NODE_ID);
$viewBuilder = \Drupal::entityTypeManager()->getViewBuilder('node');
foreach (range(1, 100) as $iteration) {
  $build = $viewBuilder->view($node, 'default', 'da');
  $viewBuilder->resetCache([$node]);
}

Time was aggregated with microtime() in the alter hook's code.
I am seeing a 40-50% speed-up on my simple local setup with 3 languages only.

ndobromirov’s picture

StatusFileSize
new6.03 KB
new1.07 KB

Here is a patch with the discussed changes.

  • ndobromirov authored 6f8a5f3 on 8.x-1.x
    Issue #3058394 by ndobromirov: Heavy handling of fallbacks
    
valthebald’s picture

Status: Needs review » Fixed

Committed to HEAD. Thank you!

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.

adamschan’s picture

I believe this patch created the regression I mentioned at https://www.drupal.org/project/entity_language_fallback/issues/3085077

Should not commit.

valthebald’s picture

@adamschan: thanks for the detailed report, looking into it