Hacktoberfest 2026: the issues maintainers tagged for October, open and beginner-friendly. Browse Hacktoberfest issues

Performance: INTERCEPT_INCLUDES serves untransformed included files through php://filter in production (no opcache)

Open
#746 0 comments 0 reactions 0 assignees View on GitHub

Maintainers usually reply within 1 day

@lisachenko is already working on this.

Since Oct 7, 2026.

  • #755 by @lisachenko — open

Assessment

Difficulty
4/5
Estimated time
3-5 days
Newbie friendliness
56/100
Issue type
Feature
Clarity
Clearly specified
Activity status
Active
Tech stack
php

Research direction

Start with src/Instrument/Transformer/FilterInjectorTransformer.php, especially rewrite(), and trace how it uses CachePathManager and the include map. Read the related class-cache implementation from #731/#732 and run composer test:performance:transformation to establish a baseline. Add the requested production file-map behavior, then verify intercepted includes of untransformed and woven files in production with and without PREBUILT_CACHE; confirm the performance test still passes.

Written by the indexing model from the issue text.

Description

Enhancement Performance

Problem

With Features::INTERCEPT_INCLUDES, every include/require inside woven code is wrapped in FilterInjectorTransformer::rewrite() (src/Instrument/Transformer/FilterInjectorTransformer.php:118-141). In production, for a file with no woven copy, which is the common case (templates, config files, plain PHP files), the call goes like this:

  1. getCachePathForResource() (:133) calls CachePathManager::queryCacheState(), which loads the full _transformation.cache metadata file (CachePathManager::loadCacheState(), :177). The include map, which is cheap, carries classes only.
  2. getCachePathForResource() returns the rebased path where a woven copy would live, so file_exists($cachedResource) (:136) is a stat call that returns false.
  3. rewrite() falls back to php://filter/.... The file is then read by the stream filter and checked for freshness (filemtime, filesize, isFreshSince()), and it is compiled on every request: opcache never caches php://filter includes.

Classes have used the include map since #731/#732: known untransformed classes are served natively. Includes never got that path.

Measurement

Same mechanism as the debug-mode issue: a 154-line file costs 0.9 µs through a plain include with warm opcache, and 180 µs through a php://filter pass-through (PHP 8.5, JIT off).

Proposal

  • Add a file map for included resources to _include.cache: original path relative to the app root mapped to cacheUri|null. Keep the constant-array format and bump CachePathManager::FORMAT_VERSION.

  • In rewrite() in production:

    • recorded as untransformed → return the original resolved path;
    • recorded as woven → return the recorded cacheUri, with no file_exists;
    • not recorded → php://filter, as today.

    This gives the same semantics as AopComposerLoader::findFile() for known classes: no freshness check in production.

  • Neither path needs _transformation.cache any more.

  • Debug mode is unchanged by this issue; it is covered by the debug-mode issue.

Acceptance

  • Functional coverage for an intercepted include of an untransformed file and of a woven file, in production and with PREBUILT_CACHE.
  • composer test:performance:transformation before and after: FilterInjectorTransformer is touched.

Estimate

About −180 µs per include of an untransformed file per request, plus no more loading of the full metadata file. Low to medium risk, small to medium change.

Dominant language
PHP
Stars
1.7k
Forks
166
Avg merge
10h
Merged PRs (30d)
35

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

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from goaop/framework

All issues in goaop/framework

Similar issues

More PHP issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.