Skip to content

Commit e449e70

Browse files
committed
Improve performance of Box::collectRemainingFiles()
The `->notPath()` filter of Symfony Finder is either accepting a “literal path” or a regular expression and converts each literal path to a regular expression and then filters the file stream by applying each regex individually. This leads to O(bufferedFileNames^2) calls to `preg_match()`, well over 20 million for PHPStan. Fix this by performing a simple `in_array()` check on the buffered files. This brings down the time to compile PHPStan from 2:35 to 0:25 on my machine. I have verified that the resulting PHPStan Phar hash is identical before and after this change. Fixes #1551.
1 parent db022b8 commit e449e70

File tree

1 file changed

+10
-14
lines changed

1 file changed

+10
-14
lines changed

src/Box.php

Lines changed: 10 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -48,9 +48,8 @@
4848
use function extension_loaded;
4949
use function file_exists;
5050
use function getcwd;
51+
use function in_array;
5152
use function is_object;
52-
use function iter\fromPairs;
53-
use function iter\map;
5453
use function openssl_pkey_export;
5554
use function openssl_pkey_get_details;
5655
use function openssl_pkey_get_private;
@@ -222,18 +221,15 @@ private static function collectRemainingFiles(
222221
string $tmp,
223222
array $bufferedFileNames,
224223
): iterable {
225-
return fromPairs(
226-
map(
227-
static fn (SplFileInfo $fileInfo) => [
228-
$fileInfo->getRelativePathname(),
229-
$fileInfo->getPathname(),
230-
],
231-
Finder::create()
232-
->files()
233-
->in($tmp)
234-
->notPath($bufferedFileNames),
235-
),
236-
);
224+
$finder = Finder::create()->files()->in($tmp);
225+
226+
foreach ($finder as $fileInfo) {
227+
if (in_array($fileInfo->getRelativePathname(), $bufferedFileNames, true)) {
228+
continue;
229+
}
230+
231+
yield $fileInfo->getRelativePathname() => $fileInfo->getPathname();
232+
}
237233
}
238234

239235
/**

0 commit comments

Comments
 (0)