Overview

I have a local environment with 22 code components, which isn't a lot. Drupal\canvas\Audit\ComponentAudit::hasUsages took 290ms to run. It grows in time with each code component.

I believe the problem is Drupal\canvas\Audit\ComponentAudit::getConfigEntityDependenciesUsingComponent which relies on the typed config manager to find dependencies.

Blackfire shows this calls

- Drupal\Core\Config\Entity\ConfigDependencyManager::getDependentEntities ~33 times
- Drupal\Core\Config\ConfigManager::getConfigDependencyManager ~33 times

Drupal\Core\Config\Entity\ConfigDependencyManager::createGraphConfigEntityDependencies was called once by getDependentEntities (so there must be some static caching) but it took 269ms. That was about 38% of the response time.

Proposed resolution

See if there's some way we can reliably cache the result of \Drupal\canvas\Audit\ComponentAudit::getConfigEntityDependenciesUsingComponent. The problem is that it's basically inverse of how cache tags work (the data isn't changing, but things referencing the data are.)

My "thanks I hate it" approach is to have \Drupal\canvas\Entity\Component::postSave invalidate the cache tags for any `component` it depends on. Maybe it's not that bad of an idea.

User interface changes

Comments

mglaman created an issue. See original summary.

wim leers’s picture

Title: /canvas/api/v0/config/js_component slow due to component audit » /canvas/api/v0/config/js_component slow due to "view" access check relying on ComponentAudit service
Component: … to be triaged » Data model
Category: Bug report » Task
Issue tags: +Performance, +Needs issue summary update, +D8 cacheability
Related issues: +#3522953: [later phase] Make Component `audit` operation performant/scalable

This isn't a bug. We made Canvas correct, we didn't do any real work yet to make it fast. We only made sure that we made cacheable responses cacheable from the start.

Which BTW is true also for /canvas/api/v0/config/js_component: it's cached by Dynamic Page Cache. So this slow code path already happens only when there's a cache miss. Of course, when constantly editing code components, it'll result in constant cache misses.

Or are you saying it's never being cached by Dynamic Page Cache? If so, that'd indeed be a bug.


AFAICT the Drupal\canvas\Audit\ComponentAudit::hasUsages() calls are happening when normalizing individual JavaScriptComponent config entities: \Drupal\canvas\Entity\JavaScriptComponent::normalizeForClientSide() calls it via this call chain: ::getEntityOperations()::access()\Drupal\canvas\EntityHandlers\VisibleWhenDisabledCanvasConfigEntityAccessControlHandler::checkAccess()\Drupal\canvas\Audit\ComponentAudit::hasUsages().

This is missing from the issue summary.


Two possible solutions are listed. I think the first has a lot of merit, and think this is totally doable! 👍

I see a third, that might intersect with the first: bringing the equivalent of "render caching" to these API responses, aka "per-config entity normalization caching". That way, we'd end up retrieving all already-normalized config entities from cache, only needing to compute the
👆 This would speed up every internal HTTP API response.

Finally: the Component Audit functionality was introduced as MVP and has had zero performance improvements done to it, hence #3522953: [later phase] Make Component `audit` operation performant/scalable