On /admin/structure/display-builder/instances,
InstanceListBuilder::buildRow() constructs the display buildable
plugin three times for every row: once directly, again inside
Instance::label(), and again inside
Instance::getProfile().
Sorting by name compounds it. The comparator calls
$a->label() and $b->label() on every comparison,
so the cost is O(n log n) plugin constructions rather than O(n).
Measured on a site with 49 instances: roughly 700 constructions per page
render. At 200 instances it is roughly 3,600.
Proposed fix
buildRow()reads the plugin label from
$this->providers, which is already populated from
getDefinitions()in the constructor.
DisplayBuildablePluginBase::label()only returns
$definition['label'], so no plugin needs building for it.Instance::getBuildablePlugin()memoizes on the entity. Its
two callers,getProfile()andgetDisplayLabel(),
are both read-only.
Roughly seven lines across two files. Takes the listing to one construction
per row and none per sort comparison.
Open questions
The memo lives as long as the Instance object, which lives in
the entity static cache. Needs a check that nothing saves a display and then
re-reads profile or label through the same object within one request, plus a
test that documents the staleness contract deliberately rather than leaving it
accidental.
Deliberately not memoizing in PluginItem::getInstance(), which
would fix all three at once: it is a generic field type, so the blast radius is
every consumer of the plugin field type, and these plugins cache
resolved entities internally.
Found while reviewing
#3615031.
Pre-existing, unrelated to that work.
Comments
Comment #2
mogtofu33 commentedComment #3
mogtofu33 commentedComment #4
mogtofu33 commented