Performance: skip parsing files that no advisor or node rewriter can affect (~90% of files on a cold cache)
Maintainers usually reply within 1 day
Nobody has claimed this yet.
Assessment
- Difficulty
- 5/5
- Estimated time
- Over a week
- Newbie friendliness
- 35/100
- Issue type
- Feature
- Clarity
- Mostly clear
- Activity status
- Active
- Tech stack
- php
- Domain
- performance
Research direction
Start in plan mode, as the issue requires an approved design before implementation. Read src/Instrument/Transformer/StreamMetaData.php, SyntaxTreeRewriter, WeavingTransformer, and the pointcut and cache-map APIs; first settle where the pre-check belongs and how unknown match cases and custom transformers veto skipping. Done means tests show unchanged woven output and cache maps against full parsing, with warmup and composer test:performance:transformation benchmarks before and after.
Written by the indexing model from the issue text.
Description
Implementation note: start in plan mode. The pointcut-side API and the fallback rules need an approved design before any code is written.
Problem
On a cache miss, StreamMetaData always parses the full file with php-parser plus a NameResolver pass (src/Instrument/Transformer/StreamMetaData.php:134), before any transformer can decide it has nothing to do.
SyntaxTreeRewriter already skips its tree walk when no rule marker is present (#736). The parse itself is never skipped, and WeavingTransformer then reflects every class against every advisor. In typical setups the pointcuts select classes by namespace or name, so most files are parsed for nothing.
Measurement
Cold cache:warmup:aop over vendor/ (3,935 files, 14 MB of source). Two advisors: execution(public Symfony\Component\Console\Command\**->*(*)) and execution(public Doctrine\ORM\**->*(*)). PHP 8.5, JIT off.
| phase | time |
|---|---|
StreamMetaData (parse + NameResolver) |
6.2 s (67%) |
| WeavingTransformer | 2.3 s |
| SyntaxTreeRewriter | 0.07 s |
| cache writes + flush | 0.16 s |
- Only 393 of 3,935 files (10%) were transformed.
- Tokenizing all files with
PhpToken::tokenize()takes 0.2 s, against about 4 s for the parse alone.
Proposal (to be refined in plan mode)
Before the parse, do a cheap pre-check on the raw source:
- Tokenize, or use another cheap scan, to extract the namespaces and the declared class, trait and enum names (and function names when
INTERCEPT_FUNCTIONSis on). - Ask each advisor whether it could match the declared names. Add an internal, optional capability on pointcuts, for example "decide by name only", which returns yes, no or unknown.
- Name-based class filters and namespace filters answer definitively.
- Inheritance (
Foo+), attribute filters (@within,@execution),!combinations and custom pointcuts answer "unknown", which forces a full parse.
- Skip the parse only when no advisor can match and no
PrefilteredNodeRewritermarker is present (the same check SyntaxTreeRewriter does today). In that case, record the file as untransformed, including its class names for the skip map (CachePathManager::registerClassForResource()), and serve the source as is.
Open questions for the plan
- Where the pre-check lives:
SourceTransformingLoader, a new first stage, or a SourceTransformer capability. Custom transformers registered throughregisterTransformerServices()must be able to opt out of, or veto, the skip. - Exact semantics of "could match" for
||,&&and!, and forwithin(**)-style wildcards. - Introductions and
INTERCEPT_INITIALIZATIONS/INTERCEPT_INCLUDESmarkers. - Interaction with aspects that are first loaded on the miss path (
getUnloadedAspects()).
Acceptance
- No change in the woven output and no change in the cache maps compared with full parsing. A test should prove this over the fixture project and a larger corpus.
- Warmup benchmark before and after.
composer test:performance:transformationbefore and after.
Estimate
Cold warmup about 9 s → 3–4 s (estimated) for configurations with name-based pointcuts. No gain, and no regression, for configurations with inheritance or attribute pointcuts. Medium to high risk, large change.
- Dominant language
- PHP
- Stars
- 1.7k
- Forks
- 166
- Avg merge
- 11h 20m
- Merged PRs (30d)
- 37
Getting set up
This project ships no dev container, Dockerfile or contributing guide, so setting up is up to you: start from its README, and see our first-contribution guide for the general steps.
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from goaop/framework
-
Intercepting a method imported from a trait with #[\Override] fails: OriginalAlias "has #[\Override] attribute, but no matching parent method exists"Possibly taken @lisachenko claimed this 2 days ago. OpenBug PHP8.4
Difficulty 3/5 Half a day Newbie friendliness 62/100
Maintainers usually reply within 1 day
-
Several woven classes in one file: their proxies overwrite each other, all but the last class are lost (Class not found)Possibly taken @lisachenko claimed this 2 days ago. OpenBug
Difficulty 4/5 3-5 days Newbie friendliness 38/100
Maintainers usually reply within 1 day
-
Enhancement Performance To Be Discussed
Difficulty 3/5 Half a day Newbie friendliness 55/100
Maintainers usually reply within 1 day
-
Feature
Difficulty 4/5 3-5 days Newbie friendliness 45/100
Maintainers usually reply within 1 day
-
Bug Known Issue
Difficulty 4/5 3-5 days Newbie friendliness 30/100
goaop/framework#696 · 1 comment ·
Maintainers usually reply within 1 day
Similar issues
-
FrameworkBundle SecurityBundle
Difficulty 2/5 1-3 hours Newbie friendliness 68/100
symfony/symfony-docs#23277 ·
Maintainers usually reply within 3 days
-
[Sync EN] hard link does not need special permissionsPossibly taken @lacatoire claimed this today. Opensync-en
Difficulty 1/5 Under an hour Newbie friendliness 90/100
Maintainers usually reply within 1 day
-
sync-en
Difficulty 1/5 Under an hour Newbie friendliness 76/100
Maintainers usually reply within 4 days
-
feature-request
Difficulty 2/5 1-3 hours Newbie friendliness 72/100
omegaup/omegaup#10323 · 1 comment ·
Maintainers usually reply within 5 days
-
bug mod:appointments
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
3pontos-tech/gil-benefits#303 ·