Improve performance with large number of node views on a page

Created on 6 February 2019, about 6 years ago
Updated 3 February 2025, 2 months ago

This may be somewhat of an edge case, but Glossify has a couple of performance bottlenecks in the following scenario:

  • Page cache has been cleared
  • Several hundred nodes being rendered on a single page
  • A few hundred terms are available

This issue exists even with a smaller number of nodes being rendered, but the performance impact is negligible at that scale. To try and describe the problem better:

  • Cache has been cleared.
  • You have 1 Glossify term.
  • Your homepage is rendering 3 nodes.
  • Each node references the term twice.

What happens is that you render that Glossify term 6 times with a potential 6 uri lookups. The render cache should come into play after the first go, but it is still reaching out to the database (or memcache) to fetch that data.

Three functions are called on every loop for each node being rendered during the page request, even if a value has been previously rendered/looked up: renderTip, renderLink, Url::fromUri. Since the output of the functions is going to be the same during the page request, you can see significant gains by statically caching the values. I have a heavily patched version of this module, so I cannot easily pull out the specific changes for this improvement, but they are similar to this:

static $lookup_caches; // at start of method
// ... snip ...
$word = &$lookup_caches[$term->name_norm][$displaytype];
if (empty($word) && ($displaytype == 'links' || $displaytype == 'tooltips_links')) {
// ... snip ...
  $tipurl = &$lookup_caches[$term->name_norm]['url'];
  if (empty($tipurl)) {
    if (\Drupal::hasContainer()) {
      $tipurl = Url::fromUri('internal:' . str_replace('[id]', $term->id, $urlpattern));
    }
    else {
      $tipurl = str_replace('[id]', $term->id, $urlpattern);
    }
  }
// ... snip ...
   if (empty($word)) {
    $word_link = [
      '#theme' => 'glossify_link',
      '#word' => $term_txt,
      '#tip' => $tip,
       '#tipurl' => $tipurl,
    ];
    $word = $this->renderLink($word_link);
  }
// ... snip ...

And repeat the empty word checks for the renderTip code as well.

These changes had the render process drop from several thousand calls (and almost a minute) to a few hundred.

✨ Feature request
Status

Needs work

Version

3.0

Component

Code

Created by

πŸ‡ΊπŸ‡ΈUnited States steven.wichers

Live updates comments and jobs are added and updated live.
Sign in to follow issues

Comments & Activities

Not all content is available!

It's likely this issue predates Contrib.social: some issue and comment data are missing.

Production build 0.71.5 2024