Improve performance of EntityReference entity usage tracking plugin

Created on 22 January 2025, about 1 month ago

Problem/Motivation

This plugin does an unnecessary entity load to discover if an entity exists. We can improve this in a couple of ways.

  • Use entity query to do a very simple query to check existence
  • Load all the values in one go by processing the whole field and all values in one go
  • Check whether the entity type is being tracked

Proposed resolution

Do all the improvements.

Remaining tasks

User interface changes

None

API changes

TBD

Data model changes

None

πŸ“Œ Task
Status

Active

Version

2.0

Component

Code

Created by

πŸ‡¬πŸ‡§United Kingdom alexpott πŸ‡ͺπŸ‡ΊπŸŒ

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

Merge Requests

Comments & Activities

  • Issue created by @alexpott
  • Merge request !99Improve performance of... β†’ (Merged) created by alexpott
  • Pipeline finished with Failed
    about 1 month ago
    Total: 260s
    #402777
  • Pipeline finished with Failed
    about 1 month ago
    Total: 214s
    #402802
  • Pipeline finished with Failed
    about 1 month ago
    Total: 347s
    #402813
  • πŸ‡¬πŸ‡§United Kingdom alexpott πŸ‡ͺπŸ‡ΊπŸŒ

    There's quite a bit of test coverage of this code because most of the code is using the entity reference plugin for testing.

  • πŸ‡¬πŸ‡§United Kingdom alexpott πŸ‡ͺπŸ‡ΊπŸŒ

    Here's some number of the effect of this patch on a large site I'm work on.

    Loading the entity usage stats for 2000 node revisions...

    Without patch

    Global stats:
    
      Called functions    :    32.5M
      Distinct functions  :     5.0K
    
      Wall time           :   27.82s
      ZE memory usage     :   60.9MB
    
    Flat profile:
    
     Wall time           | ZE memory usage     |
     Inc.     | *Exc.    | Inc.     | Exc.     | Called   | Function
    ----------+----------+----------+----------+----------+----------
       15.65s |   15.56s |    2.7GB |    2.7GB |   157.3K | Drupal\Core\Database\StatementWrapperIterator::execute
       11.29s |  769.5ms |   57.0MB |   -2.2GB |    21.5K | Drupal\Core\Entity\Sql\SqlContentEntityStorage::loadFromDedicatedTables
        2.53s |  363.1ms |  102.6MB | -408.7MB |    21.5K | Drupal\Core\Entity\Sql\SqlContentEntityStorage::loadFromSharedTables
      717.7ms |  241.0ms |   40.9MB |   40.9MB |    23.5K | Drupal\Core\Entity\ContentEntityBase::__construct
      217.1ms |  151.9ms |    1.3MB |    1.3MB |    20.0K | Drupal\entity_usage\EntityUsageTrackBase::getReferencingFields
      185.0ms |  121.6ms | -136.0MB | -142.3MB |    15.9K | Drupal\entity_lru_cache\LruMemoryCache::set
       17.35s |  104.7ms |    2.5GB |  -53.8MB |   140.1K | Drupal\Core\Database\Query\Select::execute
      393.9ms |   88.2ms |  -86.0MB |  -89.8MB |   118.3K | Drupal\Core\Extension\ModuleHandler::invokeAllWith
      351.7ms |   81.8ms |  162.5MB |    7.9MB |    22.7K | Drupal\Core\Entity\Sql\SqlContentEntityStorage::buildQuery
       13.21s |   81.3ms |   67.1MB | -469.2MB |    17.1K | Drupal\Core\Entity\Sql\SqlContentEntityStorage::getFromStorage
    

    With patch

    *** SPX Report ***
    
    Global stats:
    
      Called functions    :    27.5M
      Distinct functions  :     5.0K
    
      Wall time           :   25.03s
      ZE memory usage     :   58.5MB
    
    Flat profile:
    
     Wall time           | ZE memory usage     |
     Inc.     | *Exc.    | Inc.     | Exc.     | Called   | Function
    ----------+----------+----------+----------+----------+----------
       14.33s |   14.25s |    2.2GB |    2.2GB |   126.6K | Drupal\Core\Database\StatementWrapperIterator::execute
        8.70s |  593.0ms |   67.3MB |   -1.6GB |    18.7K | Drupal\Core\Entity\Sql\SqlContentEntityStorage::loadFromDedicatedTables
      765.3ms |  356.7ms | -119.7MB | -119.7MB |    20.7K | Drupal\Core\Entity\ContentEntityBase::__construct
      242.4ms |  174.8ms |   -1.0MB |   -1.0MB |    20.0K | Drupal\entity_usage\EntityUsageTrackBase::getReferencingFields
      212.2ms |  110.9ms |   52.8MB |   58.0MB |   126.6K | Drupal\Core\Database\StatementWrapperIterator::__construct
      457.2ms |  107.1ms |       0B |       0B |   450.6K | Drupal\Core\Entity\Sql\DefaultTableMapping::requiresDedicatedTableStorage
      541.8ms |   98.3ms |  -61.0MB |  -93.9MB |       10 | Drupal\mysql\Driver\Database\mysql\Insert::execute
      204.1ms |   82.8ms |    5.4MB |    5.4MB |   116.1K | Drupal\Core\Entity\Sql\DefaultTableMapping::getFieldColumnName
      133.4ms |   79.7ms |   43.7MB |   43.7MB |   113.4K | 1@Drupal\Core\Database\Query\Select::arguments
      320.6ms |   74.1ms |  -74.6MB |  -78.2MB |   103.0K | Drupal\Core\Extension\ModuleHandler::invokeAllWith
    

    Note I also have πŸ“Œ Add the ability to bulk insert to EntityUsage service Active applied in both cases.

  • Pipeline finished with Failed
    about 1 month ago
    Total: 2886s
    #402823
  • Pipeline finished with Success
    about 1 month ago
    Total: 212s
    #402930
  • Pipeline finished with Skipped
    about 1 month ago
    #403497
  • First commit to issue fork.
  • πŸ‡ͺπŸ‡ΈSpain marcoscano Barcelona, Spain

    Nice improvements, thank you!

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

Production build 0.71.5 2024