Skip to content

[Toolkit] Stop re-walking the filesystem on every Recipe::getFiles() - #3780

Open
Kocal wants to merge 1 commit into
symfony:3.xfrom
Kocal:perf/toolkit-component-template-index
Open

[Toolkit] Stop re-walking the filesystem on every Recipe::getFiles()#3780
Kocal wants to merge 1 commit into
symfony:3.xfrom
Kocal:perf/toolkit-component-template-index

Conversation

@Kocal

@Kocal Kocal commented Aug 15, 2026

Copy link
Copy Markdown
Member
Q A
Bug fix? no
New feature? no
Deprecations? no
Documentation? no
Issues -
License MIT

Recipe::getFiles() is a generator that runs a Finder over the recipe
directories every time it is iterated. It has six consumers, and several of
them iterate the same recipe more than once: RecipeDocRenderer walks it
twice while building one doc context, on top of the walk PoolResolver just
did, and ComponentFactory::metadataFor() reaches it once per anonymous
component lookup.

Build the list once per Recipe and return it. Recipe is @internal,
immutable, and constructed per kit load from read-only sources, so there is
nothing to invalidate. The return type is already iterable<File>, so
returning an array is signature-compatible and the iterator_to_array() call
sites keep working.

Resolving the shadcn kit's components went from 22,140 Finder walks to one
per recipe. The Toolkit test suite goes from ~13.3 s to ~9.5 s.

Benchmarked on the rendering test suite, from src/Toolkit:

blackfire run --ignore-exit-status symfony php vendor/bin/phpunit \
    --filter 'Kit shadcn, component [a-d]'

Blackfire:

Analysis, implementation and benchmarks by Claude Opus 5.

@Kocal Kocal self-assigned this Aug 15, 2026
@carsonbot carsonbot added Toolkit Status: Needs Review Needs to be reviewed labels Aug 15, 2026
@Kocal

Kocal commented Aug 15, 2026

Copy link
Copy Markdown
Member Author

With #3772, Toolkit unit tests went from ~1m35s to ~33s \o/

@Kocal
Kocal requested review from kbond and smnandre August 15, 2026 05:30
@Kocal
Kocal force-pushed the perf/toolkit-component-template-index branch 3 times, most recently from 3474530 to 045a496 Compare August 15, 2026 22:21
| Q              | A
| -------------- | ---
| Bug fix?       | no
| New feature?   | no
| Deprecations?  | no
| Documentation? | no
| Issues         | -
| License        | MIT

`Recipe::getFiles()` is a generator that runs a `Finder` over the recipe
directories every time it is iterated. It has six consumers, and several of
them iterate the same recipe more than once: `RecipeDocRenderer` walks it
twice while building one doc context, on top of the walk `PoolResolver` just
did, and `ComponentFactory::metadataFor()` reaches it once per anonymous
component lookup.

Build the list once per `Recipe` and return it. `Recipe` is `@internal`,
immutable, and constructed per kit load from read-only sources, so there is
nothing to invalidate. The return type is already `iterable<File>`, so
returning an array is signature-compatible and the `iterator_to_array()` call
sites keep working.

Resolving the shadcn kit's components went from 22,140 `Finder` walks to one
per recipe. The Toolkit test suite goes from ~13.3 s to ~9.5 s.

Benchmarked on the rendering test suite, from `src/Toolkit`:

```bash
blackfire run --ignore-exit-status symfony php vendor/bin/phpunit \
    --filter 'Kit shadcn, component [a-d]'
```

Blackfire:

- before — 19.2s wall / 245MB: https://app.blackfire.io/envs/5f4f9a62-eaa0-45ee-b7b3-a1b879f550e9/profiles/ddc20fda-bf4c-4344-9037-0dc0054d496a/graph
- after — 16.2s wall / 210MB: https://app.blackfire.io/envs/5f4f9a62-eaa0-45ee-b7b3-a1b879f550e9/profiles/2f7d0363-b44a-4a2b-80e6-8f1ed92bc7fb/graph
- diff: https://app.blackfire.io/envs/5f4f9a62-eaa0-45ee-b7b3-a1b879f550e9/profiles/compare/ddc20fda-bf4c-4344-9037-0dc0054d496a...2f7d0363-b44a-4a2b-80e6-8f1ed92bc7fb/graph

Analysis, implementation and benchmarks by Claude Opus 5.
@Kocal
Kocal force-pushed the perf/toolkit-component-template-index branch from 045a496 to f807b3d Compare August 15, 2026 22:56
@Kocal Kocal changed the title [Toolkit] Index recipe files once when resolving component templates [Toolkit] Stop re-walking the filesystem on every Recipe::getFiles() Aug 15, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants