Skip to content

[Issue] perf(di:compile): memoize Interception Config scope reads during compilation #40852

@m2-assistant

Description

@m2-assistant

This issue is automatically created based on existing pull request: #40614: perf(di:compile): memoize Interception Config scope reads during compilation


Description

Interception\Config\Config::generateIntercepted() is called twice during a single setup:di:compile run:

  1. The Interceptors generation phase (Operation\Interception)
  2. The Interception cache generation phase (Operation\InterceptionCache)

Both phases call $this->_reader->read($scope) for each of the ~8 compilation scopes. Each call fully parses and merges all di.xml files for that scope. The di.xml files don't change between the two calls within the same compile run, so the second set of reads is completely redundant.

On a project with 607 di.xml files across 8 scopes, that's ~4,856 file reads and DOM parse operations being done twice, with nearly 5,000 of them wasted.

Fix: add a $scopeReadCache array property to Config. On the first call for a given scope the result is stored; subsequent calls return the cached value. The cache is instance-scoped so it is automatically discarded between separate bin/magento invocations.

This is safe because:

  • di.xml files don't change during a compile run
  • The Config object is a DI singleton for the duration of the process
  • There is no concurrency — both phases run sequentially in the same process

Related Pull Requests

Fixed Issues (if relevant)

Manual testing scenarios

Timing comparison

# Baseline on 2.4-develop
git checkout 2.4-develop
rm -rf generated/ var/cache/
time php bin/magento setup:di:compile --no-ansi 2>&1 | tee /tmp/compile-baseline.txt

# This branch
git checkout perf/di-compile-interception-scope-cache
rm -rf generated/ var/cache/
time php bin/magento setup:di:compile --no-ansi 2>&1 | tee /tmp/compile-patched.txt

To isolate the specific phase:

grep -i "interception cache" /tmp/compile-baseline.txt
grep -i "interception cache" /tmp/compile-patched.txt

On a project with ~400 modules the Interception cache generation phase typically drops from ~1.8–4.6s to ~0.6–1.7s (63–76% reduction).

Output correctness

cp -r generated/ /tmp/generated_patched
git checkout 2.4-develop && rm -rf generated/ var/cache/
php bin/magento setup:di:compile --no-ansi
diff -r /tmp/generated_patched/ generated/   # should produce no output

Benchmarks on real-world projects

Project Interception cache phase before Interception cache phase after Saved
~470 modules, 877 plugins 1.8s 0.6s 1.2s / 67%
~390 modules (Store1) 4.1s 1.0s 3.1s / 76%
~390 modules (Store2) 4.6s 1.7s 2.9s / 63%

Memory impact

Measured on a ~470-module install:

Metric Baseline Patched Delta
PHP working memory at peak 376 MB 386 MB +10 MB (+2.7%)
OS peak RSS 438 MB 467 MB +29 MB (+6.7%)

The ~29 MB increase is the cached scope data (8 scopes × ~3–4 MB each of parsed di.xml config) being retained across both phases instead of discarded and reloaded. For a CLI compile tool this is an acceptable trade-off and well within the typical memory_limit used for compilation.

Questions or comments

Happy to add integration-level coverage if needed. The existing unit test covers the cache behaviour directly.

Contribution checklist

  • Pull request has a meaningful description of its purpose
  • All commits are accompanied by meaningful commit messages
  • All new or changed code is covered with unit/integration tests (if applicable)
  • README.md files for modified modules are updated — no README changes needed
  • All automated tests passed successfully (all builds are green)

Metadata

Metadata

Assignees

No one assigned

    Labels

    Issue: ready for confirmationPriority: P2A defect with this priority could have functionality issues which are not to expectations.

    Type

    No type
    No fields configured for issues without a type.

    Projects

    Status
    Ready for Development

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions