Problem/Motivation
The usage list page loaded every source entity referencing the viewed entity, even entities not shown on the current page. For entities with many references, this loaded and processed data that pagination then discarded.
Proposed resolution
Old pipeline
ListUsageController::getRows() called listSources(), loaded every source entity with loadMultiple(), and built a row for each one. Pagination sliced the finished list afterwards.
New pipeline
getDisplayableEntries()callslistSources()without loading entities.filterDisplayableEntries()checks entity existence and, for inline blocks, the "reusable" field, with entity queries instead of full loads. This gives the exact ordered row list and pager total.listUsagePage()slices this list to the requested page.buildRows()loads only that page's source entities withloadMultiple(), grouped by type, and builds the rows.
Trade-offs
The existence and field checks have moved to filterDisplayableEntries() instead buildRows() (orphaned usage records, soft-deleted inline blocks). This opens a tiny gap where things can change while building the usage records. Given that this will only result in displaying a row that would have been just a moment before this feels acceptable.
Remaining tasks
User interface changes
API changes
Data model changes
Issue fork entity_usage-3612704
Show commands
Start within a Git clone of the project using the version control instructions.
Or, if you do not have SSH keys set up on git.drupalcode.org:
Comments
Comment #2
alexpottI've improved the issue summary with the help of an LLM.
Comment #4
marcoscano👍 this approach sounds good to me.
It would just be nice to double-check we have test coverage for the use-case of paragraphs in the chain (ie usages in DB but that need to be discarded when displaying parents on the UI) as well as a pager. I don't remember if we account for that in the existing test.
Thanks for working on this!
Comment #5
alexpott@marcoscano paragraphs on entity_usage 5.x are no longer an issue - we don't record usages against them anymore - they're transparent :)
Comment #6
marcoscanoTrue! I'm still in a 2.x mindset... 🤦♂️
Thanks!
Comment #7
alexpottComment #8
alexpottAS well can see this approach is massively more performant when dealing with an entity used thousands of times. I installed standard, enabled media, create 1 media image and added it to a node. I then cloned this node 10000 times and went to look at the media image's usage. See the stats:
5.x
MR
Comment #9
alexpottAnd for completeness sake here is the data for a media item with a single usage. So no real performance regression for the extremely simple use-case either.
5.x
MR
Comment #11
alexpott