Skip to content

Commit 125d787

Browse files
perf: minor render and file-collection optimizations (#156)
* perf: short-circuit exclude pattern matching * perf: cache resolved working directory in result renderer
1 parent c74e830 commit 125d787

2 files changed

Lines changed: 40 additions & 9 deletions

File tree

src/FileDetector/Collector.php

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -80,10 +80,7 @@ public function collectFiles(
8080
if ($excludePatterns) {
8181
$files = array_filter(
8282
$files,
83-
static fn ($file) => !array_filter(
84-
$excludePatterns,
85-
static fn ($pattern) => fnmatch($pattern, basename((string) $file)),
86-
),
83+
fn ($file) => !$this->matchesAnyPattern(basename((string) $file), $excludePatterns),
8784
);
8885
}
8986

@@ -227,6 +224,23 @@ private function findFiles(string $path, array $supportedExtensions, bool $recur
227224
return $files;
228225
}
229226

227+
/**
228+
* Returns true as soon as the basename matches any exclude pattern,
229+
* short-circuiting instead of evaluating every pattern.
230+
*
231+
* @param string[] $patterns
232+
*/
233+
private function matchesAnyPattern(string $basename, array $patterns): bool
234+
{
235+
foreach ($patterns as $pattern) {
236+
if (fnmatch($pattern, $basename)) {
237+
return true;
238+
}
239+
}
240+
241+
return false;
242+
}
243+
230244
/**
231245
* Rejects files larger than the configured limit to avoid loading huge
232246
* (potentially malicious) files entirely into memory.

src/Result/AbstractValidationResultRenderer.php

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,13 @@
2626
*/
2727
abstract class AbstractValidationResultRenderer implements ValidationResultRendererInterface
2828
{
29+
/**
30+
* Resolved current working directory, cached per renderer instance so it is
31+
* not recomputed for every path during grouping. `false` means resolution
32+
* failed; null means not yet resolved.
33+
*/
34+
private string|false|null $resolvedCwd = null;
35+
2936
public function __construct(
3037
protected readonly OutputInterface $output,
3138
protected readonly bool $dryRun = false,
@@ -112,12 +119,8 @@ protected function normalizePath(string $path): string
112119

113120
$normalizedPath = rtrim($realPath, \DIRECTORY_SEPARATOR);
114121

115-
$cwd = getcwd();
122+
$realCwd = $this->resolvedCwd();
116123
// @codeCoverageIgnoreStart
117-
if (false === $cwd) {
118-
return $normalizedPath;
119-
}
120-
$realCwd = realpath($cwd);
121124
if (false === $realCwd) {
122125
return $normalizedPath;
123126
}
@@ -156,4 +159,18 @@ protected function calculateExitCode(ValidationResult $validationResult): int
156159
return $validationResult->getOverallResult()
157160
->resolveErrorToCommandExitCode($this->dryRun, $this->strict);
158161
}
162+
163+
/**
164+
* Resolves and caches the current working directory for this renderer.
165+
*/
166+
private function resolvedCwd(): string|false
167+
{
168+
if (null !== $this->resolvedCwd) {
169+
return $this->resolvedCwd;
170+
}
171+
172+
$cwd = getcwd();
173+
174+
return $this->resolvedCwd = false === $cwd ? false : realpath($cwd);
175+
}
159176
}

0 commit comments

Comments
 (0)