Skip to content

Commit e9be224

Browse files
dantleechsebastianbergmann
authored andcommitted
Improve source map performance for directories with same path
This PR aggregates the directories to a map of paths to tuples containing prefixes and suffixes. This will reduce the overhead of scanning paths when multiple directory elements are defined with the same path but differnet prefixes or suffixes. Addresses #6111
1 parent 5f8c741 commit e9be224

File tree

2 files changed

+113
-4
lines changed

2 files changed

+113
-4
lines changed

src/TextUI/Configuration/SourceMapper.php

Lines changed: 37 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,10 @@ public function map(Source $source): array
4040

4141
$files = [];
4242

43-
foreach ($source->includeDirectories() as $directory) {
44-
foreach ((new FileIteratorFacade)->getFilesAsArray($directory->path(), $directory->suffix(), $directory->prefix()) as $file) {
43+
$directories = $this->aggregateDirectories($source->includeDirectories());
44+
45+
foreach ($directories as $path => [$prefixes, $suffixes]) {
46+
foreach ((new FileIteratorFacade)->getFilesAsArray($path, $suffixes, $prefixes) as $file) {
4547
$file = realpath($file);
4648

4749
if (!$file) {
@@ -62,8 +64,10 @@ public function map(Source $source): array
6264
$files[$file] = true;
6365
}
6466

65-
foreach ($source->excludeDirectories() as $directory) {
66-
foreach ((new FileIteratorFacade)->getFilesAsArray($directory->path(), $directory->suffix(), $directory->prefix()) as $file) {
67+
$directories = $this->aggregateDirectories($source->excludeDirectories());
68+
69+
foreach ($directories as $path => [$prefixes, $suffixes]) {
70+
foreach ((new FileIteratorFacade)->getFilesAsArray($path, $suffixes, $prefixes) as $file) {
6771
$file = realpath($file);
6872

6973
if (!$file) {
@@ -96,4 +100,33 @@ public function map(Source $source): array
96100

97101
return $files;
98102
}
103+
104+
/**
105+
* @return array<string,array{list<string>,list<string>}>
106+
*/
107+
private function aggregateDirectories(FilterDirectoryCollection $directories): array
108+
{
109+
$aggregated = [];
110+
111+
foreach ($directories as $directory) {
112+
if (!isset($aggregated[$directory->path()])) {
113+
$aggregated[$directory->path()] = [
114+
0 => [],
115+
1 => [],
116+
];
117+
}
118+
$prefix = $directory->prefix();
119+
120+
if ($prefix !== '') {
121+
$aggregated[$directory->path()][0][] = $prefix;
122+
}
123+
$suffix = $directory->suffix();
124+
125+
if ($suffix !== '') {
126+
$aggregated[$directory->path()][1][] = $suffix;
127+
}
128+
}
129+
130+
return $aggregated;
131+
}
99132
}

tests/unit/TextUI/SourceMapperTest.php

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -270,6 +270,82 @@ public static function provider(): Generator
270270
),
271271
),
272272
];
273+
274+
yield 'files included using same directory and different suffixes' => [
275+
[
276+
self::fixturePath('a/c/Prefix.php') => true,
277+
self::fixturePath('a/c/d/Prefix.php') => true,
278+
self::fixturePath('b/e/PrefixExampleSuffix.php') => true,
279+
],
280+
self::createSource(
281+
includeDirectories: FilterDirectoryCollection::fromArray(
282+
[
283+
new FilterDirectory(
284+
self::fixturePath(),
285+
'',
286+
'ExampleSuffix.php',
287+
),
288+
new FilterDirectory(
289+
self::fixturePath(),
290+
'',
291+
'Prefix.php',
292+
),
293+
],
294+
),
295+
),
296+
];
297+
298+
yield 'files included using same directory and different prefixes' => [
299+
[
300+
self::fixturePath('a/c/Suffix.php') => true,
301+
self::fixturePath('a/c/d/Suffix.php') => true,
302+
self::fixturePath('b/e/PrefixExampleSuffix.php') => true,
303+
],
304+
self::createSource(
305+
includeDirectories: FilterDirectoryCollection::fromArray(
306+
[
307+
new FilterDirectory(
308+
self::fixturePath(),
309+
'Suffix',
310+
'.php',
311+
),
312+
new FilterDirectory(
313+
self::fixturePath(),
314+
'PrefixExample',
315+
'.php',
316+
),
317+
],
318+
),
319+
),
320+
];
321+
322+
yield 'files excluded using same directory and different prefixes' => [
323+
[
324+
],
325+
self::createSource(
326+
includeDirectories: FilterDirectoryCollection::fromArray([
327+
new FilterDirectory(
328+
self::fixturePath(),
329+
'',
330+
'.php',
331+
),
332+
]),
333+
excludeDirectories: FilterDirectoryCollection::fromArray(
334+
[
335+
new FilterDirectory(
336+
self::fixturePath(),
337+
'Prefix',
338+
'.php',
339+
),
340+
new FilterDirectory(
341+
self::fixturePath(),
342+
'Suffix',
343+
'.php',
344+
),
345+
],
346+
),
347+
),
348+
];
273349
}
274350

275351
public static function fixturePath(?string $subPath = null): string

0 commit comments

Comments
 (0)