perf(di:compile): avoid PluginList clone per area — 70% reduction in Interceptors generation phase#40613
Conversation
|
Hi @SamJUK. Thank you for your contribution!
Allowed build names are:
You can find more information about the builds here For more details, review the Code Contributions documentation. |
|
The security team has been informed about this pull request due to the presence of risky security keywords. For security vulnerability reports, please visit Adobe's vulnerability disclosure program on HackerOne or email psirt@adobe.com. |
…igurationBuilder setup:di:compile clones $pluginList once per compilation area (8 areas by default). The clone deep-copies the entire PluginList object only to immediately discard all its state in _loadScopedData(). The allocation and copy are pure waste. Add a reset() method to PluginList that clears _inherited and _processed while keeping the underlying _data array intact, then use reset() instead of clone in InterceptionConfigurationBuilder::getPluginsList(). Benchmark results (measured across three real-world installs): | Project | Interceptors before | Interceptors after | Saving | |-------------|--------------------|--------------------|--------| | sandbox | 8.8s | 2.2s | 74% | | ma-griggs | 14.9s | 4.5s | 70% | | elesi | 14.1s | 4.3s | 70% | | Project | Total before | Total after | Total saving | |-------------|-------------|-------------|--------------| | sandbox | 27.2s | 18.5s | 32% | | ma-griggs | 41.3s | 24.5s | 41% | | elesi | 39.1s | 24.2s | 38% | This is the single highest-impact change in the series. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
45f33e6 to
9ea77eb
Compare
|
@magento run all tests |
Description
InterceptionConfigurationBuilder::getPluginsList()clones$this->pluginListonce per compilation area (8 areas by default:global,frontend,adminhtml,crontab,webapi_rest,webapi_soap,graphql,admin).Each clone does two things in sequence:
PluginListobject graph —_data,_inherited,_processed,_pluginInstances,_scopePrioritySchemeand all merged plugin config._loadScopedData(), which re-merges plugin config from scratch into the clone, overwriting everything that was just copied.The clone allocates and copies a large object graph, then throws all the copied data away. With ~877 plugins across 8 areas this creates significant unnecessary allocation and GC pressure in the Interceptors generation phase.
Fix: add a
reset()method to thePluginListsubclass that clears those five properties back to their initial values. Replaceclone $this->pluginListinInterceptionConfigurationBuilderwith$this->pluginList->reset(), reusing the same instance across areas.All five reset properties are ones that
_loadScopedData()fully rebuilds anyway, so the result is identical to the clone approach._scopePrioritySchemeis reset to[Area::AREA_GLOBAL], matching the value set in the parent constructor and the correct starting state before_loadScopedData()runs.This is safe because areas are processed sequentially within a single request — there is no shared mutable state across concurrent callers.
Related Pull Requests
Fixed Issues (if relevant)
Manual testing scenarios
Timing comparison
On a project with ~400 modules expect the Interceptors phase to drop from roughly 14–15s down to 3–5s, and total compile time to improve by around 35–40%.
Output correctness
Benchmarks on real-world projects
Questions or comments
Happy to add integration-level coverage for the
InterceptionConfigurationBuilderflow if that would help reviewers. The existing unit test already covers thereset()method and the call site change.Contribution checklist